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