9576
|
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
|