I have previously documented the process of bringing hext to PyPi (i.e.
pip install hext), but that was only for Linux-based systems.
These are my notes on porting my python builds to Mac OS X.
Note This is actually my first time screwing around with any Apple product! The primary target audience is ‘Me in 6 Months’, so YMMV.
I’ve bought this quaint little machine off of Ebay:
- Macbook Pro from Mid-2009
- 2.26GHz Intel Core 2 Duo, 4GB DDR3, 128GB SSD
- Highest supported version of OS X for this machine: 10.11.6 — El Capitan
Assuming that later versions of Mac OS X are downwards binary compatible, El Capitan is the ideal build target, because it is the oldest version of Mac OS X that is still supported.
Side story: I erased the hard drive, assuming that I can reinstall the OS with the builtin recovery system. But it turns out that if your Apple-ID is brand new, the App Store refuses the request to download the OS and you’re stuck. So I contacted Apple Support and got an appointment at a “Genius Bar”. They happily installed the OS, despite me having never been a customer, and the device being 10 years old — I initially assumed they would tell me to go pound sand, but nah! All free of charge. One funny little thing though: I was just done configuring the OS and was packing up my stuff when loud music started playing in the store and the employees hastily formed two lines at the exit, like a guard of honor, chanting and clapping their hands. Either a colleague was leaving for good, or maybe this is a daily occurrence, you know, Apple being Apple :)
Getting comfortable with Mac OS X
- When downloading gzipped packages, Safari seems to automatically gunzip the archive. That makes it impossible to verify checksums or signatures. This can be disabled in Safari’s preferences dialog.
- Bash shortcuts like
[alt]+[d]are accessible as
[esc],[d]in the default terminal emulator.
- Mac OS X uses
- There’s no
- There’s no
otool -L <binary>.
- To know the minimum Mac OS X version a binary was built for, run
otool -l <binary>and look for
- There’s no
As I understand it, installing Xcode is the equivalent of
apt install build-essentials on Debian-based systems.
Xcode can be installed through the App Store. Unless of course your system isn’t officially supported by Xcode anymore, like OS X 10.11 in my case.
Luckily Apple provides downloads for older versions of Xcode.
For Mac OS X 10.11 the required packages are named:
- Xcode 8.2.1
- Command Line Tools (macOS 10.11) for Xcode 8.2
Installing Xcode is as simple as dragging the unpacked folder into “Applications” and launching Xcode. The “Command Line Tools” ship with an installer.
Building Hext’s Dependencies
Building on Mac OS X is pretty much straightforward. I only had to adjust some stuff from my previous notes on building Hext statically on Linux-based systems.
- Build & install GCC. No changes.
- Build & install ICU4C. See below.
- Build & install Boost. No changes.
- Install rapidjson. No changes.
- Build & install Gumbo. No changes.
- Build & install Google Test. No changes.
- Install CMake. See below.
- Build & install SWIG with PCRE. See below.
Side Question: Why not use Homebrew? Homebrew would be perfect, but:
- Homebrew does not support Mac OS X 10.11 anymore
- I need static libraries, not dynamic ones
- These libraries will get statically linked into a dynamic library (the resulting Hext python module).
Boost.Regex depends on ICU4C for Unicode support.
The CMake project provides official binaries for CMake on Mac OS X 10.7 or later. After installing, the cmake utility is found in
Swig and PCRE
Place the latest PCRE source tarball in Swig’s source directory and run
Then configure and build Swig the usual way.
A Python dependency. Only needed for testing.
A Python dependency. Not necessary, but convenient.
Building Python 2.7, 3.4, 3.5, 3.6 and 3.7
Side Question: Why not use pyenv? I haven’t used pyenv before, but if I understand correctly, pyenv doesn’t let me install two instances of the same Python version. Specifically, I need two instances of the latest Python 2.7:
- One with narrow Unicode support (
--enable-unicode=ucs2), such as the version that is shipped with Mac OS X 10.11.
- And one with wide Unicode support (
These two Pythons are ABI incompatible, therefore I need to compile a module for each version.
My build script:
Building A Python Module
The linker complains that there are unresolved symbols (libpython), because it cannot know that this shared object is linked at runtime of the Python interpreter, when libpython is guaranteed to be available.
This is fixed by passing
My script for building the python modules for all installed python versions:
otool -L to list dependencies on dynamically shared objects:
libSystem.B.dylib is the equivalent of
libc, if I understand correctly.
This library is present on all versions of Mac OS X and is backwards compatible, and therefore a safe dependency.