Home | History | Annotate | Download | only in docs
      1 Building the same code for multiple ISAs
      2 
      3 
      4 1 Introduction
      5 
      6   Building both 32-bit and 64-bit variants of the same library is now really
      7   easy.  What's more, adding more ISAs, for example SSE2 is also easy.
      8   This document explains how to change a 32-bit only spec file to support
      9   multiple ISAs.
     10 
     11 2 Include files
     12 
     13   There are a bunch of include files in the include subdirectory that
     14   define macros useful for building code for various ISAs:
     15 
     16   base.inc - default macros, used for building 32-bit binaries
     17              automatically included by Solaris.inc, but you can
     18              include this to reset macros to the defaults after
     19 	     including one of the other includes below.
     20 
     21   arch64.inc - macros for building 64-bit binaries: amd64 or sparcv9
     22 
     23   x86_sse2.inc - macros for building binaries that make use of Intel SSE2
     24              extensions.
     25 
     26   You need to include Solaris.inc before including any of these files.
     27 
     28   What they do is, they set macros that define the compiler flags:
     29 
     30   %gcc_optflags - C compiler flags for building with gcc
     31   %suncc_optflags - C compiler flags for building with Sun Studio cc
     32   %gcc_cxx_optflags - C++ compiler flags for building with g++
     33   %suncc_cxx_optflags - C++ compiler flags for building with Sun Studio CC
     34 
     35   %optflags - C compiler flags for the current C compiler ($CC)
     36   %cxx_optflags - C++ compiler flags for the current C++ compiler ($CXX)
     37 
     38   and update the directory macros for the given architecture:
     39 
     40   %_bindir - set to %{_prefix}/bin/<ISA specific dir>, e.g. /usr/bin/amd64
     41   %_libdir - same with /usr/lib/<ISA>
     42   %_libexecdir - same as %_libdir
     43   %_pkg_config_path - directory that contains the pkgconfig files for
     44              this ISA, e.g. /usr/lib/sparcv9/pkgconfig
     45 
     46   They also define some handy macros:
     47 
     48   can_isaexec - 1 if multiple ISAs are built, 0 if only 32-bit
     49                 If 1, we can use isaexec to automatically run the
     50                 executable that best matches the current system, see
     51                 details in "Using isaexec" below.
     52   gtk_doc_option - always set to --disable-gtk-doc for non-default
     53                 ISAs so that we only build the gtk docs for the base ISA.
     54 		In the case of the base ISA, you can continue to the
     55 		--without-gtk-doc or --with-gtk-doc to control whether
     56 		or not to build the gtk-doc API documentation
     57 
     58 3 Using the ISA specific include files
     59 
     60   pkgbuild processes the "child" spec files when it reads the %use line.
     61   Macros defined in the parent spec file before the %use line are visible
     62   in the child spec file, macros defined or redefined after the %use line
     63   do not affect the child spec file.
     64 
     65   This means that changing %{_libdir} to /usr/lib/amd64 using %define
     66   before the %use line will cause the libdir of the child spec to be
     67   /usr/lib/amd64, if it uses the --libdir=%{_libdir} configure option.
     68   We can also control the compiler flags used in the child spec by
     69   defining optflags before the %use line and setting CFLAGS="%optflags"
     70   in the child spec.
     71 
     72   So adding a new ISA of a library is as simple as including the
     73   appropriate .inc file (which sets up optflags, _libdir, etc.) and then
     74   using %use:
     75 
     76     %include Solaris.inc              <- always include before arch64.inc
     77 
     78     %ifarch amd64 sparcv9
     79     %include arch64.inc               <- sets %optflags, %_libdir, etc.
     80     %use flac_64 = flac.spec          <- process the child spec
     81     %endif
     82 
     83     %include base.inc                 <- reset %optflags, %_libdir, etc.
     84     %use flac = flac.spec             <- process the child spec again
     85                                          note that we assign a different
     86                                          label from the 64-bit variant
     87 
     88   Then we add another section for %prep:
     89 
     90     %prep
     91     rm -rf %name-%version
     92     mkdir %name-%version
     93 
     94     %ifarch amd64 sparcv9
     95     mkdir %name-%version/%_arch64
     96     %flac_64.prep -d %name-%version/%_arch64
     97     %endif
     98 
     99     mkdir %name-%version/%base_arch
    100     %flac.prep -d %name-%version/%base_arch
    101 
    102   The above sets up the following directory structure under
    103   %_topdir/BUILD (considering an amd64 platform for this example):
    104 
    105     .../packages/BUILD
    106 	   |
    107            +-----> SUNWflac-1.1.4
    108                        |
    109                        +-----> i86
    110                        |        |
    111                        |        +-----> flac-1.1.4
    112                        |
    113                        +-----> amd64
    114                                 |
    115                                 +-----> flac-1.1.4
    116 
    117   Now we need to build both source trees:
    118 
    119     %build
    120     %ifarch amd64 sparcv9
    121     %flac_64.build -d %name-%version/%_arch64
    122     %endif
    123 
    124     %flac.build -d %name-%version/%base_arch
    125 
    126   And then install both trees:
    127 
    128     %install
    129     rm -rf $RPM_BUILD_ROOT
    130 
    131     %ifarch amd64 sparcv9
    132     %flac_64.install -d %name-%version/%_arch64
    133     %endif
    134 
    135     %flac.install -d %name-%version/%base_arch
    136 
    137   Finally, update %files to include the 64-bit binaries:
    138 
    139     %ifarch amd64 sparcv9
    140     %dir %attr (0755, root, bin) %{_bindir}/%{_arch64}
    141     %{_bindir}/%{_arch64}/*
    142     %dir %attr (0755, root, bin) %{_libdir}/%{_arch64}
    143     %{_libdir}/%{_arch64}/lib*.so*
    144     %endif
    145 
    146   Note that we didn't need to touch base-specs/flac.spec for this.
    147   We do need to make sure that:
    148     - it sets CFLAGS="%optflags" and LDFLAGS="%{_ldflags}"
    149     - it passes at least --libdir=%{_libdir} and --bindir=%{_bindir}
    150       to configure (for modules using the GNU autotools)
    151 
    152 4 Using isaexec
    153 
    154   There is one more trick we can do: setting up the executables so that
    155   the OS will automatically execute the one best suited for the
    156   architecture it's running on.
    157 
    158   To do that, we need to move the base executables into a subdirectory
    159   under the bin directory and hard link /usr/lib/isaexec using the name
    160   of the executable.  isaexec will look for executables with the same
    161   name under the ISA-specific subdirectories, in the order printed by
    162   isalist, for example:
    163 
    164     laca@ultra20:~> isalist
    165     amd64 pentium_pro+mmx pentium_pro pentium+mmx pentium i486 i386 i86
    166 
    167   I.e. the binary in bin/amd64 will be run if it's found, if not then
    168   bin/pentium_pro+mmx, etc. finally i86.
    169 
    170   In the following example we're moving the 32-bit "flac" binary into the
    171   i86 subdir.  Note that the 64-bit version is automatically installed
    172   in the amd64 subdir, because arch64.inc sets _bindir to
    173   %{_prefix}/bin/amd64.
    174 
    175   This goes into %install:
    176 
    177     %if %can_isaexec
    178     mkdir $RPM_BUILD_ROOT%{_bindir}/%{base_isa}
    179     cd $RPM_BUILD_ROOT%{_bindir}
    180     mv flac metaflac %{base_isa}
    181     ln -s ../../usr/lib/isaexec flac
    182     ln -s ../../usr/lib/isaexec metaflac
    183     %endif
    184 
    185   In the %file list, %{_bindir}/flac and %{_bindir}/metaflac must be
    186   flagged at hard links using the %hard flag.  You need pkgbuild 1.1.2
    187   or later for hard links.
    188 
    189     %hard %{_bindir}/flac
    190     %hard %{_bindir}/metaflac
    191