How to Compile OpenSSL 1.1.1 for Apple Silicon

You have an app on the Mac App Store which depends on OpenSSL for receipt validation, among other things. This validation may be done through Receigen, Swifty Receipt Validator, or your own home-grown receipt validation logic.

But Apple recently announced another instruction set that you need to support in your mac app: ARM64. These new machines could come as early as Big Sur’s general availability, which is likely in October 2020. This means that you have about three months left to update your macOS application.

Unfortunately CocoaPods hasn’t offer any OpenSSL distributions for Apple Silicon macintosh computers yet. Sure there are a few pre-compiled ARM64 binaries but those links against iOS frameworks, not macOS.

Wouldn’t it be great if you have your Mac App ready for Apple Silicon on the same day Big Sur is on Golden Master?

Here are the steps that you need to do to get a copy of OpenSSL ready for inclusion in your Universal 2 application for the Mac:

  1. Download OpenSSL 1.1.1g sources.
  2. Extract the archive into two different folders, one for Intel and the other for ARM instruction sets, respectively.
  3. Configure and compile each separately.
  4. Join results of the two together to create a Universal Library.

In this article I’m going to assume that you are going to extract OpenSSL sources into sibling folders with the following names:

  • openssl-1.1.1g-x86_x64 – for the Intel build.
  • openssl-1.1.1g-arm64 – for the ARM build.

Building the Intel Half

Building the x86_64 portion would be straight-forward since this is currently supported by OpenSSL 1.1.1g. You need to extract the OpenSSL sources into a dedicated folder for the architecture, run configure and then make. Optionally set the macOS deployment target if you need your app to run on earlier versions of the operating system.

You can find an example below. Pay special attention on the arguments to the Configure script.

## Specify minimum deployment target as needed by your app
$ export MACOSX_DEPLOYMENT_TARGET=10.13

$ cd openssl-1.1.1g-x86_x64
$ ./Configure darwin64-x86_64-cc shared
$ caffeinate make

By the time make completes, you should get four files that comprises of the static and dynamic libraries of OpenSSL.

  • libssl.1.1.dylib
  • libcrypto.1.1.1.dylib
  • libssl.a
  • libcrypto.a

Building the ARM Half

However the arm64 portion requires changes to OpenSSL’s build configuration as the macOS build of the instruction set is not currently supported by the library.

Having extracted the OpenSSL sources (be sure extract it into a separate location than the one you’ve used to build the Intel portion), then modify file Configurations/10.main.conf to add the macOS arm64 build configuration. Add the following snippet at around line 1560, right under the entry for “darwin64-x86_64-cc”.

"darwin64-arm64-cc" => {
    inherit_from     => [ "darwin-common", asm("aarch64_asm") ],
    CFLAGS           => add("-Wall"),
    cflags           => add("-arch arm64 -isysroot /Applications/Xcode-beta.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk"),
    lib_cppflags     => add("-DL_ENDIAN"),
    bn_ops           => "SIXTY_FOUR_BIT_LONG",
    perlasm_scheme   => "macosx",
},

(Special thanks to OpenSSL PR 12254 for the above configuration snippet).

When you’re done, the file should look like the following:

OpenSSL macOS ARM64 Configuration

Then run Configure and make similar to before. Take note that the Configure script takes a different set of arguments.

% cd openssl-1.1.1g-arm64
% ./Configure shared enable-rc5 zlib darwin64-arm64-cc no-asm
% caffeinate make

By the time make completes, you would get four files that comprises of the static and dynamic libraries of OpenSSL, having the same file names as the ones previously compiled for Intel. This is why you should create a copy for each architecture and compile it in two different folders.

Creating Universal Libraries

Having the libraries compiled for the respective Intel and ARM64 instruction sets, the last step would be combining the two halves of the each library file into their respective universal library files. Use lipo for this, as follows.

% mkdir openssl-mac

% lipo -create openssl-1.1.1g-arm64/libcrypto.1.1.dylib openssl-1.1.1g-x86_x64/libcrypto.1.1.dylib  -output openssl-mac/libcrypto.1.1.1.dylib

% lipo -create openssl-1.1.1g-arm64/libssl.1.1.dylib openssl-1.1.1g-x86_x64/libssl.1.1.dylib -output openssl-mac/libssl.1.1.dylib

% lipo -create openssl-1.1.1g-arm64/libcrypto.a openssl-1.1.1g-x86_x64/libcrypto.a -output openssl-mac/libcrypto.a

% lipo -create openssl-1.1.1g-arm64/libssl.a openssl-1.1.1g-x86_x64/libssl.a -output openssl-mac/libssl.a

When you’re done combining the library files, check them using the file tool and verify that indeed you have a universal library.

% file libcrypto.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

If you use OpenSSL for license validation, you should use the static library version. Which are the libcrypto.a and libssl.a files. Static linking reduces the risk of code injection via library replacement. In other words, it’ll be harder to for crackers to replace the OpenSSL libraries inside your app bundle and make your app use their compromised replacement version instead.

Nevertheless if you use OpenSSL as dynamic libraries, then you would need to change its install names be embeddable into your app bundle’s Frameworks folder. Plain compilation of OpenSSL dynamic libraries are meant to be installed in a shared folder.

Use install_name_tool on the dynamic versions of the library files as follows:

% 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

As always, it’ll be prudent to check your work. Use otool -D to print the install name of a dynamic library.

% otool -D libssl.1.1.dylib 

libssl.1.1.dylib:
@rpath/libssl.1.1.dylib

Next Steps

In case you’re in a hurry, I’ve compiled these libraries for you that you can download and drop them into your project. These were built on Xcode 12 Beta 4 running on the Apple Silicon version of Big Sur. These library files are temporary stop-gap until OpenSSL officially support Apple Silicon.

This article was tested with Xcode 12 Beta 4 running on the Apple Silicon version of Big Sur Beta 4. You don’t need an Apple Silicon mac to compile libraries or applications for the processor — Xcode 12 can produce ARM64 binaries even when running on Intel macs. However to test the ARM64 half of a Universal Binary you would need an Apple Silicon mac.

An Apple Silicon mac can run both the Intel and the ARM64 portions of a universal binary application. But not the other way around. Intel binaries are emulated under Rosetta 2 on Apple Silicon, but there is no emulation of ARM64 on Intel-based mac.

But even when you don’t have an Apple Silicon Mac (yet), merely compiling for Universal Binary would be a good start. You’ll know which pre-built 3rd party libraries to update, for which OpenSSL is likely one of several. There are likely ARM-related compiler warnings to heed out for.

Why wait? Get your Xcode Beta copy today and start building your Mac app for ARM64!

Until next time.



Avoid App Review rules by distributing outside the Mac App Store!


Get my FREE cheat sheets to help you distribute real macOS applications directly to power users.

* indicates required

When you subscribe you’ll also get programming tips, business advices, and career rants from the trenches about twice a month. I respect your e-mail privacy.

Avoid Delays and Rejections when Submitting Your App to The Store!


Follow my FREE cheat sheets to design, develop, or even amend your app to deserve its virtual shelf space in the App Store.

* indicates required

When you subscribe you’ll also get programming tips, business advices, and career rants from the trenches about twice a month. I respect your e-mail privacy.

16 thoughts on “How to Compile OpenSSL 1.1.1 for Apple Silicon

  1. Hi Sasmito, I followed exactly with your steps and use this for arm:
    ./Configure shared enable-rc5 zlib darwin64-arm64-cc no-asm
    caffeinate make

    And use lipo for both Intel and Mac.

    I could successfully build all .a library. But after I build my project with libssl.a and libcryto.a, I had this error:
    Undefined symbols for architecture arm64:
    deflate”, referenced from:
    _zlib_stateful_compress_block in libcrypto.a(c_zlib.o)
    _bio_zlib_write in libcrypto.a(c_zlib.o)
    _bio_zlib_ctrl in libcrypto.a(c_zlib.o)
    “_deflateEnd”, referenced from:
    _zlib_stateful_finish in libcrypto.a(c_zlib.o)
    _bio_zlib_free in libcrypto.a(c_zlib.o)
    “_deflateInit
    “, referenced from:
    zlib_stateful_init in libcrypto.a(c_zlib.o)
    _bio_zlib_write in libcrypto.a(c_zlib.o)
    “_inflate”, referenced from:
    _zlib_stateful_expand_block in libcrypto.a(c_zlib.o)
    _bio_zlib_read in libcrypto.a(c_zlib.o)
    “_inflateEnd”, referenced from:
    _zlib_stateful_finish in libcrypto.a(c_zlib.o)
    _bio_zlib_free in libcrypto.a(c_zlib.o)
    “_inflateInit
    “, referenced from:
    _zlib_stateful_init in libcrypto.a(c_zlib.o)
    _bio_zlib_read in libcrypto.a(c_zlib.o)
    “_zError”, referenced from:
    _bio_zlib_write in libcrypto.a(c_zlib.o)
    _bio_zlib_read in libcrypto.a(c_zlib.o)
    _bio_zlib_ctrl in libcrypto.a(c_zlib.o)
    ld: symbol(s) not found for architecture arm64

    Can you help me with it?

  2. This is a very useful tutorial – thank you. One problem though – when I try to use the built libraries I get the following error…

    ld: library not found for -lcrypto.1.1.1
    clang: error: linker command failed with exit code 1 (use -v to see invocation)

    What am I doing wrong here? Incidentally, and to preempt a possible followup question from me, I can get this to work if I install openssl with Home-brew – but then Xcode crashes when I try to notarise – I think that the two problems are related since without openssl (which I need) Xcode doesn’t crash!

  3. Thanks for this ! I have moved up to openssl-1.1.1k. I’m using Xcode Version 12.5 (12E262)

    I used % ./Configure shared darwin64-arm64-cc no-asm

    And

    “darwin64-arm64-cc” => {
    inherit_from => [ “darwin-common”, asm(“aarch64_asm”) ],
    CFLAGS => add(“-Wall”),
    cflags => add(“-arch arm64”),
    lib_cppflags => add(“-DL_ENDIAN”),
    bn_ops => “SIXTY_FOUR_BIT_LONG”,
    perlasm_scheme => “macosx”,
    },

    All compiled and linked very smoothly.

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

    libssl.1.1.dylib:
    @rpath/libssl.1.1.dylib

    In Xcode, project navigator, I scroll down to Frameworks, and Add files to project. libssl.a and libcryto.a

    no problems.

    But when I compile release version I get the following:

    ld: warning: ignoring file /usr/local/ssl/lib/libcrypto.a, building for macOS-arm64 but attempting to link with file built for unknown-x86_64
    ld: warning: ignoring file /usr/local/ssl/lib/libssl.a, building for macOS-arm64 but attempting to link with file built for unknown-x86_64
    Undefined symbols for architecture arm64:
    “_ASN1_get_object”, referenced from:
    _dictionaryWithAppStoreReceipt in ReceiptValidator.o
    “_BIO_free”, referenced from:
    _dictionaryWithAppStoreReceipt in ReceiptValidator.o
    “_BIO_new”, referenced from:
    _dictionaryWithAppStoreReceipt in ReceiptValidator.o
    “_BIO_s_mem”, referenced from:
    _dictionaryWithAppStoreReceipt in ReceiptValidator.o
    “_ERR_load_PKCS7_strings”, referenced from:
    _dictionaryWithAppStoreReceipt in ReceiptValidator.o
    “_ERR_load_X509_strings”, referenced from:
    _dictionaryWithAppStoreReceipt in ReceiptValidator.o
    “_EVP_cleanup”, referenced from:
    _dictionaryWithAppStoreReceipt in ReceiptValidator.o
    “_OBJ_obj2nid”, referenced from:
    _dictionaryWithAppStoreReceipt in ReceiptValidator.o
    “_OpenSSL_add_all_digests”, referenced from:
    _dictionaryWithAppStoreReceipt in ReceiptValidator.o
    “_PKCS7_free”, referenced from:
    _dictionaryWithAppStoreReceipt in ReceiptValidator.o
    “_PKCS7_verify”, referenced from:
    _dictionaryWithAppStoreReceipt in ReceiptValidator.o
    “_SHA1”, referenced from:
    -[ReceiptValidator offlineReceiptValidator:] in ReceiptValidator.o
    “_X509_STORE_add_cert”, referenced from:
    _dictionaryWithAppStoreReceipt in ReceiptValidator.o
    “_X509_STORE_free”, referenced from:
    _dictionaryWithAppStoreReceipt in ReceiptValidator.o
    “_X509_STORE_new”, referenced from:
    _dictionaryWithAppStoreReceipt in ReceiptValidator.o
    “_X509_free”, referenced from:
    _dictionaryWithAppStoreReceipt in ReceiptValidator.o
    “_d2i_PKCS7”, referenced from:
    _dictionaryWithAppStoreReceipt in ReceiptValidator.o
    “_d2i_X509”, referenced from:
    _dictionaryWithAppStoreReceipt in ReceiptValidator.o
    ld: symbol(s) not found for architecture arm64

    Any ideas ?

    Thanks ! ~ Jay

  4. Hi, Can you help me? I am trying to run django with docker but it returns an error with cryptography and it refers to openssl:

    creating build/temp.linux-aarch64-3.7/build/temp.linux-aarch64-3.7
    gcc -pthread -Wno-unused-result -Wsign-compare -DNDEBUG -g -fwrapv -O3 -Wall -fPIC -I/usr/local/include/python3.7m -c build/temp.linux-aarch64-3.7/_openssl.c -o build/temp.linux-aarch64-3.7/build/temp.linux-aarch64-3.7/_openssl.o -Wconversion -Wno-error=sign-conversion
    build/temp.linux-aarch64-3.7/_openssl.c:575:30: fatal error: openssl/opensslv.h: No such file or directory
    #include <openssl/opensslv.h>
    ^
    compilation terminated.
    error: command ‘gcc’ failed with exit status 1

    ERROR: Failed building wheel for cryptography
    ERROR: Could not build wheels for cryptography which use PEP 517 and cannot be installed directly

    I did all the steps mentioned, up to the openssl-mac folder

  5. Now that Xcode is “out,” one should change the isysroot as follows for the ARM config:

    inherit_from => [ "darwin-common", asm("aarch64_asm") ],
    CFLAGS => add("-Wall"),
    cflags => add("-arch arm64 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk"),
    lib_cppflags => add("-DL_ENDIAN"),
    bn_ops => "SIXTY_FOUR_BIT_LONG",
    perlasm_scheme => "macosx",

    },

    (i.e. remove “-beta”.)

    I followed the steps in reverse order and had issues. I imagine if you do the ARM side first (as I did) you’ll want to do this first too:

    export MACOSX_DEPLOYMENT_TARGET=10.13

    (I did it in that order because I was doing this on an ARM machine, though of course I could have done it in the order indicated.)

  6. Thanks for this tutorial. Do you how I can build this with a macOS deployment target of 10.11? I can build the intel half with a 10.11 deployment target, but the ARM half fails. When I combine the two to make a universal library and link it in my project Xcode generates tons of warnings “object file .o was built for a newer version of macOS than being linked.”

    1. For the ARM half, macOS 11 would be the minimum deployment target. Build the two separately and then lipo them together.

      1. I was still getting a bunch of warning about “object file .o was built for a newer version of macOS than being linked.” But perhaps those warnings were cached from when I previously built libssl without properly specifying the deployment target. After re-doing the entire process and deleted DerivedData those warnings have gone away now.

        I did also have to remove the zlib option when building the ARM half. Everything seems to be all good now. Thanks a lot for this guide.

  7. I am now using the release version of Xcode Version 12.2 (12B45b)

    build Intel == success

    build arm:

    this is my result. Can you guide me through how to rectify the 2 issues shown below?

    steve@Steves-iMac openssl-1.1.1g % ./Configure shared enable-rc5 zlib darwin64-arm64-cc no-asm
    Configuring OpenSSL version 1.1.1g (0x1010107fL) for darwin64-arm64-cc
    Using os-specific seed configuration
    Creating configdata.pm
    Creating Makefile

    ************************************************************************* ***
    *** OpenSSL has been successfully configured

    steve@Steves-iMac openssl-1.1.1g % make
    perl “-I.” -Mconfigdata “util/dofile.pl” \
    “-oMakefile” include/crypto/bn_conf.h.in > include/crypto/bn_conf.h
    perl “-I.” -Mconfigdata “util/dofile.pl” \
    “-oMakefile” include/crypto/dso_conf.h.in > include/crypto/dso_conf.h
    perl “-I.” -Mconfigdata “util/dofile.pl” \
    “-oMakefile” include/openssl/opensslconf.h.in > include/openssl/opensslconf.h
    /Applications/Xcode.app/Contents/Developer/usr/bin/make depend && /Applications/Xcode.app/Contents/Developer/usr/bin/make _all
    cc -I. -Iinclude -fPIC -arch arm64 -isysroot /Applications/Xcode-beta.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk -O3 -Wall -DL_ENDIAN -DOPENSSL_PIC -DOPENSSLDIR=”\”/usr/local/ssl\”” -DENGINESDIR=”\”/usr/local/lib/engines-1.1\”” -D_REENTRANT -DZLIB -DNDEBUG -MMD -MF apps/app_rand.d.tmp -MT apps/app_rand.o -c -o apps/app_rand.o apps/app_rand.c
    clang: warning: no such sysroot directory: ‘/Applications/Xcode-beta.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk’ [-Wmissing-sysroot]
    clang: warning: using sysroot for ‘MacOSX’ but targeting ‘iPhone’ [-Wincompatible-sysroot]
    In file included from apps/app_rand.c:10:
    In file included from apps/apps.h:13:
    In file included from ./e_os.h:16:
    In file included from include/openssl/e_os2.h:243:
    /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/12.0.0/include/inttypes.h:21:15: fatal error:
    ‘inttypes.h’ file not found
    #include_next <inttypes.h>

    1. The answer to this is in the text snippet that is shown above for ‘darwin64-x86_64-cc’…
      In the proposed snippet it references ‘Xcode-beta.app’.
      Once this was altered to refer to ‘Xcode.app’ and a redo on ‘Configure’ – voila!

  8. Thank you for the guide. I can compile it for Apple silicon successfully, and there is no problem to compile my Xcode project for “My Mac (Rosetta)” on the DTK Mac. But there is problem when compiling for “My Mac” (for Apple Silicon), even using the .a files you provided directly.

    Mac: DTK
    OS: Big Sur beta 7
    Xcode: Version 12.2 beta 1

    Error messages:

    Undefined symbols for architecture arm64:
    deflate”, referenced from:
    _zlib_stateful_compress_block in libcrypto.a(c_zlib.o)
    _bio_zlib_write in libcrypto.a(c_zlib.o)
    _bio_zlib_ctrl in libcrypto.a(c_zlib.o)
    “_deflateEnd”, referenced from:
    _zlib_stateful_finish in libcrypto.a(c_zlib.o)
    _bio_zlib_free in libcrypto.a(c_zlib.o)
    “_deflateInit
    “, referenced from:
    zlib_stateful_init in libcrypto.a(c_zlib.o)
    _bio_zlib_write in libcrypto.a(c_zlib.o)
    “_inflate”, referenced from:
    _zlib_stateful_expand_block in libcrypto.a(c_zlib.o)
    _bio_zlib_read in libcrypto.a(c_zlib.o)
    “_inflateEnd”, referenced from:
    _zlib_stateful_finish in libcrypto.a(c_zlib.o)
    _bio_zlib_free in libcrypto.a(c_zlib.o)
    “_inflateInit
    “, referenced from:
    _zlib_stateful_init in libcrypto.a(c_zlib.o)
    _bio_zlib_read in libcrypto.a(c_zlib.o)
    “_zError”, referenced from:
    _bio_zlib_write in libcrypto.a(c_zlib.o)
    _bio_zlib_read in libcrypto.a(c_zlib.o)
    _bio_zlib_ctrl in libcrypto.a(c_zlib.o)

    ld: symbol(s) not found for architecture arm64

    If it’s convenient for you, would you please help to let me know the direction to resolve the issues?

    Thank you.

    1. Those are zlib symbols. Probably your app should link to the SDK-provided libz instead of having a local copy.

    2. Using the 1.1.1i version, I altered the arm configuration command as follows:

      % ./Configure shared darwin64-arm64-cc no-asm

      I also skipped the following from the Configurations/10.main.conf file (no longer on beta)
      -isysroot /Applications/Xcode-beta.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk

      That seemed to resolve the zlib issue for me.

  9. Great job. Thanks. I followed your instructions. Everything was precise and correct. Activity Monitor shows Apple silicon for CPU and I am able to validate App Store credentials. Let me know if you would like a free license for EazyDraw – thanks again.

Leave a Reply