Compile Universal Binary For Mac
Programming
How to Compile OpenSSL 1.1.1 for Apple Silicon
For everything else, you could compile these yourself, but the real trick has not been the universal binary itself, but making a universal binary that is still 10.2 compatible (per SDL requirements). There are also the additional hoops of needing to recompile all the dependencies as universal binaries with the same constraints, e.g, not only.
- For everything else, you could compile these yourself, but the real trick has not been the universal binary itself, but making a universal binary that is still 10.2 compatible (per SDL requirements). There are also the additional hoops of needing to recompile all the dependencies as universal binaries with the same constraints, e.g, not only.
- If you want to compile universal binaries to distribute, add ' +universal' at the end of each line. (Everything will need to be compiled first, so have patience.) Install libpng, liblzma' (provided by xz package)', pkgconfig (required for lzma detection), lzo2 and libiconv (the required zlib will be installed as dependency automatically).
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:
- Download OpenSSL 1.1.1g sources.
- Extract the archive into two different folders, one for Intel and the other for ARM instruction sets, respectively.
- Configure and compile each separately.
- 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.
By the time make
Engelhard 1 oz silver bar serial number lookup 1-800. 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
”. The incredible machine download.
(Special thanks to OpenSSL PR 12254 for the above configuration snippet).
When you’re done, the file should look like the following:
Then run Configure
and make
similar to before. Take note that the Configure
script takes a different set of arguments.
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.
When you’re done combining the library files, check them using the file
tool and verify that indeed you have a universal 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:
As always, it’ll be prudent to check your work. Use otool -D
to print the install name of a dynamic library.
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.
Leave a Reply
I’ve put together an Xcode template for creating Universal Binary Mach-O plugins for REALbasic. The template will compile a dylib for PPC, and a bundle for Universal Binary – and put these in a plugin folder ready for conversion to a .rbx file.
Updated 3/10/08 for version 1.4 of the template.
Updated 8/1/07 for version 1.3 of the template.
Updated 26/8/06 for version 1.2 of the template.
Updated 23/8/06 for version 1.1 of the template.
To use this template, start by downloading my template files (.zip format, 27KB), and unzip the downloaded template files archive.
Then, do the following:
- Make sure you have Xcode installed. You can download it for free from Apple by signing up for a free Apple Developer Connection Online membership. This template has been tested with Xcode 3.1.1. When you install Xcode, be sure to install the “Mac OS X 10.3.9 package” (it isn’t selected by default), or the plugin template won’t work.
- Make sure you are using REALbasic 2006r4 or later for Mac OS X. 2006r4 was the first version to support Universal Binary builds, and so you’ll need this version or later to test your Universal Binary plugin.
- Make sure you use the latest REALbasic Plugin SDK (included in the REALbasic download for Mac OS X, in the “/Extras/Plugins SDK/” folder).
- Copy the folder “REALbasic”, from the downloaded template files, to “/Developer/Library/Xcode/Project Templates/” (which is where Xcode keeps its project templates).
- Launch Xcode.
- Select “File > New Project…”.
- Select the REALbasic category under the Mac OS X category, and then select the “REALbasic Universal Binary Mach-O Plugin”. Click “Choose…” to use this template.
- Give the project a name. This will also be the name of your plugin, and the folder the project lives in. By default the new folder will be created in your home folder, but you can change this to another location.
- Click “Finish”. A new project will open, and a new project folder will be created on your hard disk, wherever you chose above.
- Find this folder on your hard disk, and copy the “Glue Code” and “Includes” folders from the latest Plugins SDK into the root level of your new project’s folder. Switch back to Xcode, and you should see that the “Glue Code” and “Includes” folders and files in the Xcode file list have turned from red text to black text.
- By default, the plugin contains one global method, called CurrentArchitecture. You can now compile your plugin, and give this method a test! Just select “Build > Build” in Xcode (or press Apple-B), and both the PPC and Universal Binary dylibs will be built.
- The first time you build the project, you will get four warnings that build folders do not exist. Ignore these warnings – they’re just caused by Xcode creating the folder structure for your plugin.
- Once you have built the empty plugin, you’ll find that a new folder will have be created by Xcode in your project folder. It will have the same name as the project. This folder is the skeleton structure of your plugin. It will contain one folder, called “Build Resources”. “Build Resources” will contain two folders: “Mac Carbon Mach-O”, containing the PPC dylib, and “Mac Carbon Mach-O Universal”, containing the Universal Binary bundle.
- To make these two files into a plugin (also known as a .rbx file), you’ll need to use the “Plugin Converter” from the REALbasic Plugins SDK. Open the “Plugin converter.rb” project, and build the project. This will build an application called “RB Plugin Converter”.
- Run this application, and click on the “Convert Folder” button. Find your project folder, and select the subfolder with the same name (you’re selecting the folder that contains the “Build Resources” folder). Click on “Choose”.
- The Plugin Converter will prompt you to select where you want to save the built plugin. Select your REALbasic Plugins folder (something like “/Applications/REALbasic 2008r4/Plugins/”, and click “Save”. A file called “YourProjectName.rbx” will be created in the Plugins folder. This is your plugin!
- Your plugin is now ready to go. Launch REALbasic, open the sample project included with the template download – “PluginTest.rbp” – and build the project. It will build as a Universal Binary application called “PluginTest.app”. If you run “PluginTest.app” on a PowerPC Mac, it will use the CurrentArchitecture global method to display a message saying that it is running the PowerPC code. The same goes for if you run the app under Rosetta on an Intel Mac. If you run “PluginTest.app” natively on an Intel Mac, then it will say it is running the Intel plugin code.
- Once you have finished developing and testing your plugin, switch Xcode to use the “Deployment” build configuration. You can do this from Xcode’s “Project > Set Active Build Configuration” menu. Build the plugin again. The Deployment build configuration strips out any unused code and symbols, and results in a much smaller plugin file. Use this version of the plugin in any applications you distribute.
Version 1.4, 3/10/08
Updated the instructions for REALbasic 2008r4 and Xcode 3.1.1.
Version 1.3, 8/1/07
Changed the Universal Binary part of the plugin to be a bundle rather than a dynamic library. This will take advantage of a new feature in future versions of REALbasic, where the Universal Binary part of the plugin will be loaded directly into memory and not written out to disk.
Changed the target order to ensure that “Build All” is the default.
Version 1.2, 26/8/06
Added in an exports file to the Deployment build configuration for both PPC and UB, and set this build configuration to use Dead Code Stripping. This reduces the size of the built Deployment plugin considerably.
Changed the SDKs and Mac OS X Deployment Targets to build for 10.3.9 with GCC 3.3 for the PPC target and the PPC part of the UB target; and to build for 10.4u with GCC 4.0 for the i386 part of the UB target. This means that 10.3 can be supported for backwards compatability.
Disabled Prebinding for the i386 part of the UB target, as it is 10.4 only and therefore doesn’t need prebinding.
Removed the unused “Default” build configuration.
Version 1.1, 23/8/06
The PowerPC dylib is now built as a PowerPC target when compiled on an Intel machine. Previously it was being compiled as $(NATIVE_ARCH), which would build as PPC on PPC, and Intel on Intel. Thanks to Philippe Rigaux for spotting this error.
The UB dylib now compiles against the 10.4u SDK, at /Developer/SDKs/MacOSX10.4u.sdk/. This means that it will actually compile :-)
A sample global method, CurrentArchitecture, is now included in the plugin template.
A few other compile settings have been moved from being Target settings to being Project settings, to avoid duplication.
Compile Universal Binary For Mac Os
Version 1.0, 21/8/06
Compile Universal Binary For Mac Download
Initial release.