8

I have a project which needs to use Libcrypto - and I have two versions of Libcrypto (libcrypto.a (from OpenSSL 1.1.1) built for ARM64) and (lcrypto.a (from OpenSSL 1.0.2) for Intel). Leaving aside the issues of whether it's good practice or not to have two different versions, I can say that if I include libcrypto.a then I can build and run on M1 and it works fine on M1. If I include lcrypto.a then I can build and run on Intel and it works fine on Intel. What I can't do is include them both (linker error - The linked library 'lcrypto.a' is missing one or more architectures required by this target: arm64.) - and if I can't include them both then I can't build a fat binary, and my app is less than entirely useful!

My question is How can I include both in my project - or where can I get (and how can I include) a fat version of Libcrypto? I've looked at this https://github.com/balthisar/openssl-xcframeworks/releases and this https://developer.apple.com/forums/thread/670631 but I'm none the wiser. I think I built a Fat Binary - but the Fat Binary I thought that I built doesn't work for either architecture!

Frant
  • 4,492
  • 1
  • 14
  • 21
headbanger
  • 1,082
  • 9
  • 23
  • 2
    Use command lipo to combine. https://cutecoder.org/programming/compile-open-ssl-apple-silicon/ (Creating Universal Libraries). Some parts of the tutorial have already been implemented by openssl team. – Marek H Aug 31 '21 at 17:01
  • 1
    I'm confused as to why your artifact is called `lcrypto.a` in the first place. Intuitively, that seems wrong as a compiler/linker would never find that file when using `-lcrypto`. – Siguza Aug 31 '21 at 21:12
  • @MarekH if I could mark your answer as correct, I would. That was just the ticket. Thank you. – headbanger Sep 01 '21 at 17:53
  • 2
    Does this answer your question? [Build Multiarch OpenSSL on OS X](https://stackoverflow.com/questions/25530429/build-multiarch-openssl-on-os-x) – Marek H Sep 02 '21 at 13:12

1 Answers1

10

Use command lipo to combine binaries

Compile Intel and ARM versions separately (arm version requires Xcode 12).

export MACOSX_DEPLOYMENT_TARGET=10.9
cp -r openssl-1.1.1o openssl-1.1.1o-arm64 
cp -r openssl-1.1.1o openssl-1.1.1o-x86_x64 

Build the Intel half

cd openssl-1.1.1o-x86_x64 
./Configure darwin64-x86_64-cc shared
make

Build the Arm half

export MACOSX_DEPLOYMENT_TARGET=10.15 /* arm64 only with Big Sur -> minimum might be 10.16 or 11.0 */)
cd ../openssl-1.1.1o-arm64 
./Configure enable-rc5 zlib darwin64-arm64-cc no-asm
make

To create universal binary use command lipo:

cd ..
mkdir openssl-mac
lipo -create openssl-1.1.1o-arm64/libcrypto.a openssl-1.1.1o-x86_x64/libcrypto.a -output openssl-mac/libcrypto.a
lipo -create openssl-1.1.1o-arm64/libssl.a openssl-1.1.1o-x86_x64/libssl.a -output openssl-mac/libssl.a

Verify that resulting binary contains both architectures:

file libcrypto.a libssl.a
libcrypto.a: Mach-O universal binary with 2 architectures: [x86_64:current ar archive random library] [arm64]
libcrypto.a (for architecture x86_64):  current ar archive random library
libcrypto.a (for architecture arm64):   current ar archive random library
libssl.a: Mach-O universal binary with 2 architectures: [x86_64:current ar archive random library] [arm64]
libssl.a (for architecture x86_64):  current ar archive random library
libssl.a (for architecture arm64):   current ar archive random library

PS: If you plan to use dynamic library combine dylib files using lipo and run instal_name_tool

cd openssl-mac
install_name_tool -id '@rpath/libcrypto.1.1.1.dylib' libcrypto.1.1.1.dylib
install_name_tool -id '@rpath/libssl.1.1.dylib' libssl.1.1.dylib
otool -D libssl.1.1.dylib /* to verify */

Result:

libssl.1.1.dylib:
@rpath/libssl.1.1.dylib
Marek H
  • 4,771
  • 2
  • 25
  • 41
  • while using those commands, don't forget to switch architectures, either with switching terminals or by using the command `arch -arch x86_64 ./Configure ...` or `arch -arch arm64 ./Configure ...`. – Janos Vinceller May 06 '22 at 10:57