Skip to content

Commit aefa54c

Browse files
authored
Merge pull request #4936 from randombit/jack/universal-binary-doc
Improve docs regarding building universal binaries for macOS [ci skip]
2 parents f406b8e + b66ec2a commit aefa54c

1 file changed

Lines changed: 41 additions & 12 deletions

File tree

doc/building.rst

Lines changed: 41 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -197,19 +197,48 @@ that the Botan libraries were installed into.
197197
On macOS
198198
--------------
199199

200-
A build on macOS works much like that on any other Unix-like system.
200+
A standard build on macOS works much like that on any other Unix-like system.
201+
202+
One notable difference with macOS is the common usage of "universal binaries",
203+
which is effectively a multiarch binary. This was used first for the PowerPC to
204+
x86 transition, and more recently for the x86 to Aarch64 transition.
205+
206+
Building a universal binary is a bit trickier for Botan compared with a standard
207+
application, as the library makes use of many architecture specific extensions,
208+
for example AES-NI and AVX2 on x86, and NEON and the ARMv8 crypto extensions on
209+
Aarch64. Botan's build system also assumes that it is knowable at setup time
210+
which files are to be compiled.
211+
212+
Typically (for software with no architecture dependent code) a universal binary
213+
is built by adding additional compilation flags that look something like
214+
``-force_cpusubtype_ALL -arch x86_64 -arch arm64``. This effectively causes XCode
215+
to compile each file twice, once for x86_64 and again for Aarch64. For most source
216+
files this works fine, but for architecture-specific files it will result in errors
217+
when code specific to one architecture is encountered when compiling for a different
218+
architecture, resulting in errors like::
201219

202-
To build a universal binary for macOS, for older macOs releases,
203-
you need to set some additional build flags.
204-
Do this with the `configure.py` flag `--cc-abi-flags`::
205-
206-
--cc-abi-flags="-force_cpusubtype_ALL -mmacosx-version-min=10.4 -arch i386 -arch ppc"
207-
208-
209-
for mac M1 on arm64, you can build the x86_64 arch version via Rosetta separately.
210-
Do this with with `arch -x86_64 configure.py --library-suffix=-x86_64`
211-
Then using lipo to create a fat binary.
212-
`lipo -create libbotan-arm64.dylib libbotan-x86_64.dylib -o libbotan.dylib`
220+
$ make
221+
...
222+
error: unknown target CPU 'armv8.2-a+sha3'
223+
note: valid target CPU values are: ...
224+
225+
There are currently two ways of proceeding.
226+
227+
The first is to use ``--cpu=generic``. This disables all architecture specific
228+
code, which has performance implications, especially for algorithms with
229+
dedicated hardware support like AES. This can be alleviated somewhat by making
230+
sure the CommonCrypto provider (module ``commoncrypto``) is built, since then
231+
Botan offloads many of these specific operations to CommonCrypto, which will be
232+
able to use the CPU instructions.
233+
234+
The second, and recommended, approach is to build twice and use ``lipo`` to
235+
combine the two binaries. This looks something like::
236+
237+
$ ./configure.py --with-build-dir=botan_x86_64 --disable-cc-tests --build-targets=shared --cpu=x86_64 --extra-cxxflags='-arch x86_64' --ldflags='-arch x86_64' --library-suffix=-x86_64
238+
$ make -j8 -f botan_x86_64/Makefile
239+
$ ./configure.py --with-build-dir=botan_aarch64 --disable-cc-tests --build-targets=shared --cpu=aarch64 --extra-cxxflags='-arch arm64' --ldflags='-arch arm64' --library-suffix=-aarch64
240+
$ make -j8 -f botan_aarch64/Makefile
241+
$ lipo -create botan_aarch64/libbotan-3-aarch64.dylib botan_x86_64/libbotan-3-x86_64.dylib -o libbotan-3.dylib
213242

214243
On Windows
215244
--------------

0 commit comments

Comments
 (0)