It’s counter-intuitive, but 64-bit binaries are more memory-hungry and often slower than 32-bit ones. It makes sense to build 64-bit binaries when:
There’s also the 2G file size restriction, but it can be worked around by adding the -D_LARGEFILE64_SOURCE=1 flag to the C preprocessor as documented in lf64(5).
When building packages, the general guideline with regard to bitness is that executables should default to 32-bit, unless there are reasons to default them to 64-bit. So the default would be:
/opt/csw/bin/foo (32-bit binary)
/opt/csw/bin/sparcv9/foo (64-bit binary)
If /opt/csw/bin is in PATH, the 32-bit binary will be run by default, but if the user wants, they can run the 64-bit binary as well.
To run the 64-bit binary where/when possible, you can use isaexec:
/opt/csw/bin/foo → isaexec (hardlink)
/opt/csw/bin/sparcv8/foo (32-bit binary)
/opt/csw/bin/sparcv9/foo (64-bit binary)
The isaexec program is a wrapper which detects the architecture and looks for the most advanced binary the current architecture can run. On sparc, it almost always means running a 64-bit binary. So if you use isaexec, it means defaulting to 64-bit in most cases.
Development packages in most cases don’t distinguish between 32-bit and 64-bit ‒ you don’t have to do anything.
However, there are some software projects (e.g. gmp) which install different headers depending on bitness. These have to be handled specifically, but providing both 32-bit and 64-bit header files with a specific switch file. For example:
/opt/csw/include/foo.h (the switch file)
/opt/csw/include/foo-32.h
/opt/csw/include/foo-64.h
The contents of foo.h would be:
/* Allow 32 and 64 bit headers to coexist */
#if defined __amd64 || defined __x86_64 || defined __sparcv9
#include "foo-64.h"
#else
#include "foo-32.h"
#endif
To implement the following in GAR, you need to set EXTRA_PAX_ARGS to rewrite specific header names to be bit-specific, and then manually install the switch file:
EXTRA_PAX_ARGS_32 = -s ",^\.$(includedir)/foo.h$$,.$(includedir)/foo-32.h,p"
EXTRA_PAX_ARGS_64 = -s ",^\.$(includedir)/foo.h$$,.$(includedir)/foo-64.h,p"
EXTRA_PAX_ARGS = $(EXTRA_PAX_ARGS_$(MEMORYMODEL))
(...)
include gar/category.mk
post-merge:
ginstall $(FILEDIR)/foo.h $(PKGROOT)$(includedir)/foo.h
@$(MAKECOOKIE)
This operation must happen in the post-merge stage, because this operation must be done after we’ve built binaries for all architectures and we’re merging them into a single directory tree. See the modulations in GAR video for more information.
Usually only binaries and libraries differ; all other files have the same content regardless to the architecture. However, some software projects might embed architecture specific information into files which aren’t binaries and don’t have a mechanism of choosing the right version of the file at runtime:
/opt/csw/bin/foo → isaexec (hardlink)
/opt/csw/sparcv8/foo (32-bit binary, has /opt/csw/lib in RUNPATH)
/opt/csw/sparcv9/foo (64-bit binary, has /opt/csw/lib/64 in RUNPATH)
/opt/csw/lib/64 → sparcv9 (symlink)
/opt/csw/lib/libfoo.so.1 (32-bit library)
/opt/csw/lib/sparcv9/libfoo.so.1 (64-bit library)
/opt/csw/lib/foo/arch_specific_data (ZONK! no mechanism to differentiate!)
The 64-bit header files example shown above is a lucky case, because header files follow the C syntax, so you can use the #if defined conditional statement. In the general case there is no single solution, it all depends on whether you can write a conditional statement such that you get the 32-bit or 64-bit content depending on a choice made at runtime.
To compile a 64-bit binary, you add -m64 to the compiler invocation. See more about Linking against OpenCSW libraries.
In GAR, there’s a shortcut:
BUILD64 = 1