Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Build Multiarch OpenSSL on OS X

I need to build OpenSSL on OS X for 32 and 64 bit architectures. What are the options I need to give to ./Configure so that I get it built for both architectures into same .a file?

like image 557
Seema Kadavan Avatar asked Aug 27 '14 14:08

Seema Kadavan


People also ask

How do I create an open SSL file?

You must use a C compiler to build the OpenSSL library. You cannot use a C++ compiler. Later, once the library is built, it is OK to create user programs with a C++ compiler. But the library proper must be built with a C compiler.


1 Answers

./Configure so that I get it built for both architectures into same .a file?

You have to be careful with OpenSSL and multiarch libraries because the library is not multiarch safe. That's because each configuration has its own <openssl/opensslconf.h> file, and each platform's BIGNUM is different.

Supplying -arch x86_64 -arch i386 will result in a build failure because of the way OpenSSL's build system forms commands. Also see Getting libcrypto ar error while compiling OpenSSL for Mac.

The same procedure detailed below applies to iOS, too. The only thing that changes is the -arch. For iOS, you will probably use armv7, armv7s, arm64 and i386 (for 32-bit simulator debug) and x86_64 (for 64-bit simulator debug).

There's another not-so-apparent trick required. OpenSSL hard codes some default paths based on --prefix and --openssldir, so you have to build 32-bit for the installation directory, install, and then move it; then build 64-bit for the installation directory, install, and then move it; and then create the fat library in the install directory. Also see How to determine the default location for openssl.cnf?

Finally, do not replace OS X's supplied OpenSSL. OpenSSL 1.0.x and 1.1.x are not binary compatible with the Apple's 0.9.8 version of OpenSSL. Because of incompatibilities, the procedures below uses $HOME/ssl. You can use /usr/local/ssl or any other location that suits your taste.


Before you begin, OpenSSL wiki has a page on Compilation and Installation. There's lots of options to supply to config. Choose the ones that suit your taste. I always use no-ssl2, and usually use no-ssl3, no-comp. On mobile devices I use no-srp, no-psk, no-hw, no-dso and no-engines.


Here are the instructions for building the library. You will configure, build, install and then move for each architecture you are supporting in your multiarch build.

32-bit

make clean && make dclean

KERNEL_BITS=32 ./config no-ssl2 no-ssl3 --prefix=$HOME/ssl
make depend
make
make install_sw

mv $HOME/ssl/include/openssl/opensslconf.h $HOME/ssl/include/openssl/opensslconf-x86.h
mv $HOME/ssl/include/openssl/bn.h $HOME/ssl/include/openssl/bn-x86.h
mv $HOME/ssl/ $HOME/ssl-x86

64-bit

make clean && make dclean

KERNEL_BITS=64 ./config no-ssl2 no-ssl3 --prefix=$HOME/ssl
make depend
make
make install_sw

mv $HOME/ssl/include/openssl/opensslconf.h $HOME/ssl/include/openssl/opensslconf-x64.h
mv $HOME/ssl/include/openssl/bn.h $HOME/ssl/include/openssl/bn-x64.h
mv $HOME/ssl/ $HOME/ssl-x64

Headers

You need to copy one set of headers (it does not matter which), copy opensslconf-x86.h, opensslconf-x64.h bn-x86.h and bn-x64.h, create a new <openssl/opensslconf.h>, create a new <openssl/bn.h>, and finally create the multiarch libraries.

rm -rf $HOME/ssl

mkdir -p $HOME/ssl/bin
mkdir -p $HOME/ssl/include/openssl
mkdir -p $HOME/ssl/lib

cp $HOME/ssl-x86/openssl.cnf $HOME/ssl/openssl.cnf
cp $HOME/ssl-x86/include/openssl/* $HOME/ssl/include/openssl
cp $HOME/ssl-x86/include/openssl/opensslconf-x86.h $HOME/ssl/include/openssl/opensslconf-x86.h
cp $HOME/ssl-x64/include/openssl/opensslconf-x64.h $HOME/ssl/include/openssl/opensslconf-x64.h
cp $HOME/ssl-x86/include/openssl/bn-x86.h $HOME/ssl/include/openssl/bn-x86.h
cp $HOME/ssl-x64/include/openssl/bn-x64.h $HOME/ssl/include/openssl/bn-x64.h

New <opensslconf.h>

If you have not done so, create $HOME/ssl/include/openssl/opensslconf.h. Be sure you use a new header guard (OPENSSL_MULTIARCH_CONF_HEADER):

cat $HOME/ssl/include/openssl/opensslconf.h
#ifndef OPENSSL_MULTIARCH_CONF_HEADER
#define OPENSSL_MULTIARCH_CONF_HEADER

#if __i386 || __i386__
# include "opensslconf-x86.h"
#elif __x86_64 || __x86_64__ || __amd64 || __amd64__
# include "opensslconf-x64.h"
#else
# error Unknown architecture
#endif

#endif /* OPENSSL_MULTIARCH_CONF_HEADER */

New <bn.h>

Create $HOME/ssl/include/openssl/bn.h. Be sure you use a new header guard (OPENSSL_MULTIARCH_BN_HEADER):

cat $HOME/ssl/include/openssl/bn.h
#ifndef OPENSSL_MULTIARCH_BN_HEADER
#define OPENSSL_MULTIARCH_BN_HEADER

#if __i386 || __i386__
# include "bn-x86.h"
#elif __x86_64 || __x86_64__ || __amd64 || __amd64__
# include "bn-x64.h"
#else
# error Unknown architecture
#endif

#endif /* OPENSSL_MULTIARCH_BN_HEADER */

Libraries

At this point, you have a x86 build of the library located at $HOME/ssl-x86 and a x64 build of the library located at $HOME/ssl-x64. You combine them with lipo at $HOME/ssl.

lipo -create $HOME/ssl-x86/lib/libcrypto.a \
             $HOME/ssl-x64/lib/libcrypto.a \
             -output $HOME/ssl/lib/libcrypto.a

lipo -create $HOME/ssl-x86/lib/libssl.a \
             $HOME/ssl-x64/lib/libssl.a \
             -output $HOME/ssl/lib/libssl.a

lipo -create $HOME/ssl-x86/bin/openssl \
             $HOME/ssl-x64/bin/openssl \
             -output $HOME/ssl/bin/openssl

Share Libraries

If you configured with shared, then you need to perform:

lipo -create $HOME/ssl-x86/lib/libcrypto.1.0.0.dylib \
             $HOME/ssl-x64/lib/libcrypto.1.0.0.dylib \
             -output $HOME/ssl/lib/libcrypto.1.0.0.dylib

lipo -create $HOME/ssl-x86/lib/libssl.1.0.0.dylib \
             $HOME/ssl-x64/lib/libssl.1.0.0.dylib \
             -output $HOME/ssl/lib/libssl.1.0.0.dylib

Then, you need to recreate the softlinks:

ln -s $HOME/ssl/lib/libcrypto.dylib $HOME/ssl/lib/libcrypto.1.0.0.dylib
ln -s $HOME/ssl/lib/libssl.dylib $HOME/ssl/lib/libssl.1.0.0.dylib

Finally, test things. Verify the libraries are multiarch:

ls $HOME/ssl/lib/
libcrypto.a libssl.a

lipo -info $HOME/ssl/lib/libcrypto.a 
Architectures in the fat file: $HOME/ssl/lib/libcrypto.a are: i386 x86_64 
lipo -info $HOME/ssl/lib/libssl.a 
Architectures in the fat file: $HOME/ssl/lib/libssl.a are: i386 x86_64

And then a test program:

#include <openssl/opensslconf.h>
#include <openssl/ssl.h>

int main(int argc, char* argv[])
{
  SSL_library_init();
  return 0;
}

And:

$ clang -arch i386 -arch x86_64 -I $HOME/ssl/include test.c -o test.exe -L $HOME/ssl/lib -lssl -lcrypto
$ DYLD_LIBRARY_PATH=$HOME/ssl/lib; ./test.exe 
$

DYLD_LIBRARY_PATH is used in case you built the dynamic libraries on OS X.


If desired, you can delete the non-multiarch installations:

rm -rf $HOME/ssl-x86
rm -rf $HOME/ssl-x64
like image 197
jww Avatar answered Sep 29 '22 22:09

jww