Skip to content

Commit c3bd1f5

Browse files
committed
Add universal2 (i.e., M1 hardware support) to the macOS build.
1 parent 62bfe8d commit c3bd1f5

File tree

1 file changed

+57
-34
lines changed

1 file changed

+57
-34
lines changed

Makefile

Lines changed: 57 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,8 @@ LIBFFI_VERSION=3.3
5050
OS=macOS iOS tvOS watchOS
5151

5252
# macOS targets
53-
TARGETS-macOS=macosx.x86_64
53+
TARGETS-macOS=macosx.x86_64 macosx.arm64
54+
PYTHON_TARGETS-macOS=macOS
5455
CFLAGS-macOS=-mmacosx-version-min=$(MACOSX_DEPLOYMENT_TARGET)
5556

5657
# iOS targets
@@ -176,7 +177,8 @@ downloads/Python-$(PYTHON_VERSION).tgz:
176177
mkdir -p downloads
177178
if [ ! -e downloads/Python-$(PYTHON_VERSION).tgz ]; then curl -L https://www.python.org/ftp/python/$(PYTHON_VERSION)/Python-$(PYTHON_VERSION).tgz > downloads/Python-$(PYTHON_VERSION).tgz; fi
178179

179-
PYTHON_DIR-macOS=build/macOS/Python-$(PYTHON_VERSION)-macosx.x86_64
180+
# Some Python targets needed to identify the host build
181+
PYTHON_DIR-macOS=build/macOS/Python-$(PYTHON_VERSION)-macOS
180182
PYTHON_HOST=$(PYTHON_DIR-macOS)/dist/lib/libpython$(PYTHON_VER).a
181183

182184
# Build for specified target (from $(TARGETS))
@@ -209,14 +211,6 @@ OPENSSL_DIR-$1=build/$2/openssl-$(OPENSSL_VERSION)-$1
209211
BZIP2_DIR-$1=build/$2/bzip2-$(BZIP2_VERSION)-$1
210212
XZ_DIR-$1=build/$2/xz-$(XZ_VERSION)-$1
211213
LIBFFI_DIR-$1=build/$2/libffi-$(LIBFFI_VERSION)
212-
PYTHON_DIR-$1=build/$2/Python-$(PYTHON_VERSION)-$1
213-
pyconfig.h-$1=pyconfig-$$(ARCH-$1).h
214-
215-
ifeq ($2,macOS)
216-
PYTHON_HOST_DEP-$1=
217-
else
218-
PYTHON_HOST-$1=$(PYTHON_HOST)
219-
endif
220214

221215
# Unpack OpenSSL
222216
$$(OPENSSL_DIR-$1)/Makefile: downloads/openssl-$(OPENSSL_VERSION).tgz
@@ -239,7 +233,7 @@ endif
239233
ifeq ($2,macOS)
240234
cd $$(OPENSSL_DIR-$1) && \
241235
CC="$$(CC-$1)" MACOSX_DEPLOYMENT_TARGET=$$(MACOSX_DEPLOYMENT_TARGET) \
242-
./Configure darwin64-x86_64-cc no-tests --prefix=$(PROJECT_DIR)/build/$2/openssl --openssldir=$(PROJECT_DIR)/build/$2/openssl
236+
./Configure darwin64-$$(ARCH-$1)-cc no-tests --prefix=$(PROJECT_DIR)/build/$2/openssl --openssldir=$(PROJECT_DIR)/build/$2/openssl
243237
else
244238
cd $$(OPENSSL_DIR-$1) && \
245239
CC="$$(CC-$1)" \
@@ -288,9 +282,14 @@ $$(XZ_DIR-$1)/Makefile: downloads/xz-$(XZ_VERSION).tgz
288282
$$(XZ_DIR-$1)/src/liblzma/.libs/liblzma.a: $$(XZ_DIR-$1)/Makefile
289283
cd $$(XZ_DIR-$1) && make && make install
290284

291-
# No need to build libFFI on macOS
285+
# macOS builds use their own libFFI, and are compiled as a single
286+
# universal2 build. As a result, the macOS Python build is configured
287+
# in the `build` macro, rather than the `build-target` macro.
292288
ifneq ($2,macOS)
293289
LIBFFI_BUILD_DIR-$1=build_$$(SDK-$1)-$$(ARCH-$1)
290+
PYTHON_DIR-$1=build/$2/Python-$(PYTHON_VERSION)-$1
291+
pyconfig.h-$1=pyconfig-$$(ARCH-$1).h
292+
PYTHON_HOST-$1=$(PYTHON_HOST)
294293

295294
# Build LibFFI
296295
$$(LIBFFI_DIR-$1)/libffi.$1.a: $$(LIBFFI_DIR-$1)/darwin_common
@@ -300,8 +299,6 @@ $$(LIBFFI_DIR-$1)/libffi.$1.a: $$(LIBFFI_DIR-$1)/darwin_common
300299
# include the target in the final filename for disambiguation
301300
cp $$(LIBFFI_DIR-$1)/$$(LIBFFI_BUILD_DIR-$1)/.libs/libffi.a $$(LIBFFI_DIR-$1)/libffi.$1.a
302301

303-
endif
304-
305302
# Unpack Python
306303
$$(PYTHON_DIR-$1)/Makefile: downloads/Python-$(PYTHON_VERSION).tgz $$(PYTHON_HOST-$1)
307304
# Unpack target Python
@@ -312,21 +309,14 @@ $$(PYTHON_DIR-$1)/Makefile: downloads/Python-$(PYTHON_VERSION).tgz $$(PYTHON_HOS
312309
# Copy in the embedded module configuration
313310
cat $(PROJECT_DIR)/patch/Python/Setup.embedded $(PROJECT_DIR)/patch/Python/Setup.$2 > $$(PYTHON_DIR-$1)/Modules/Setup.local
314311
# Configure target Python
315-
ifeq ($2,macOS)
316-
cd $$(PYTHON_DIR-$1) && MACOSX_DEPLOYMENT_TARGET=$$(MACOSX_DEPLOYMENT_TARGET) ./configure \
317-
--prefix=$(PROJECT_DIR)/$$(PYTHON_DIR-$1)/dist \
318-
--without-doc-strings --enable-ipv6 --without-ensurepip \
319-
$$(PYTHON_CONFIGURE-$2)
320-
else
321312
cd $$(PYTHON_DIR-$1) && PATH=$(PROJECT_DIR)/$(PYTHON_DIR-macOS)/dist/bin:$(PATH) ./configure \
322313
CC="$$(CC-$1)" LD="$$(CC-$1)" \
323314
--host=$$(MACHINE_DETAILED-$1)-apple-$(shell echo $2 | tr '[:upper:]' '[:lower:]') \
324-
--build=x86_64-apple-darwin$(shell uname -r) \
315+
--build=x86_64-apple-darwin \
325316
--prefix=$(PROJECT_DIR)/$$(PYTHON_DIR-$1)/dist \
326317
--without-doc-strings --enable-ipv6 --without-ensurepip \
327318
ac_cv_file__dev_ptmx=no ac_cv_file__dev_ptc=no \
328319
$$(PYTHON_CONFIGURE-$2)
329-
endif
330320

331321
# Build Python
332322
$$(PYTHON_DIR-$1)/dist/lib/libpython$(PYTHON_VER).a: build/$2/Support/OpenSSL build/$2/Support/BZip2 build/$2/Support/XZ build/$2/Support/libFFI $$(PYTHON_DIR-$1)/Makefile
@@ -336,6 +326,8 @@ $$(PYTHON_DIR-$1)/dist/lib/libpython$(PYTHON_VER).a: build/$2/Support/OpenSSL bu
336326
build/$2/$$(pyconfig.h-$1): $$(PYTHON_DIR-$1)/dist/include/python$(PYTHON_VER)/pyconfig.h
337327
cp -f $$^ $$@
338328

329+
endif
330+
339331
# Dump vars (for test)
340332
vars-$1:
341333
@echo "ARCH-$1: $$(ARCH-$1)"
@@ -386,7 +378,7 @@ endif
386378
echo "OpenSSL: $(OPENSSL_VERSION)" >> build/$1/Support/VERSIONS
387379
echo "XZ: $(XZ_VERSION)" >> build/$1/Support/VERSIONS
388380
ifeq ($1,macOS)
389-
cp -r build/$1/Python-$(PYTHON_VERSION)-macosx.x86_64/dist build/$1/python
381+
cp -r build/$1/Python-$(PYTHON_VERSION)-macOS/dist build/$1/python
390382
mv build/$1/Support/VERSIONS build/$1/python/VERSIONS
391383
tar zcvf $$@ -X patch/Python/exclude.macOS -C build/$1/python `ls -A build/$1/python`
392384
else
@@ -459,11 +451,42 @@ build/$1/xz/lib/liblzma.a: $$(foreach target,$$(TARGETS-$1),$$(XZ_DIR-$$(target)
459451
# Build libFFI
460452
libFFI-$1: $$(LIBFFI_FRAMEWORK-$1)
461453

454+
# macOS builds a single Python universal2 target; thus it needs to be
455+
# configured in the `build` macro, not the `build-target` macro.
456+
# macOS also uses the system-provided libFFI, so there's no need to package
457+
# a libFFI framework for macOS.
462458
ifeq ($1,macOS)
463-
$$(LIBFFI_FRAMEWORK-$1): # noop
464-
else
459+
# Some targets that are needed for consistency between macOS and other builds,
460+
# but are no-ops on macOS.
461+
$$(LIBFFI_FRAMEWORK-$1):
462+
463+
build/$1/$$(pyconfig.h-$1):
464+
465+
# Unpack Python
466+
$$(PYTHON_DIR-$1)/Makefile: downloads/Python-$(PYTHON_VERSION).tgz
467+
# Unpack target Python
468+
mkdir -p $$(PYTHON_DIR-$1)
469+
tar zxf downloads/Python-$(PYTHON_VERSION).tgz --strip-components 1 -C $$(PYTHON_DIR-$1)
470+
# Apply target Python patches
471+
cd $$(PYTHON_DIR-$1) && patch -p1 < $(PROJECT_DIR)/patch/Python/Python.patch
472+
# Copy in the embedded module configuration
473+
cat $(PROJECT_DIR)/patch/Python/Setup.embedded $(PROJECT_DIR)/patch/Python/Setup.$1 > $$(PYTHON_DIR-$1)/Modules/Setup.local
474+
# Configure target Python
475+
cd $$(PYTHON_DIR-$1) && MACOSX_DEPLOYMENT_TARGET=$$(MACOSX_DEPLOYMENT_TARGET) ./configure \
476+
--prefix=$(PROJECT_DIR)/$$(PYTHON_DIR-$1)/dist \
477+
--without-doc-strings --enable-ipv6 --without-ensurepip --enable-universalsdk --with-universal-archs=universal2 \
478+
$$(PYTHON_CONFIGURE-$1)
479+
480+
# Build Python
481+
$$(PYTHON_DIR-$1)/dist/lib/libpython$(PYTHON_VER).a: build/$1/Support/OpenSSL build/$1/Support/BZip2 build/$1/Support/XZ build/$1/Support/libFFI $$(PYTHON_DIR-$1)/Makefile
482+
# Build target Python
483+
cd $$(PYTHON_DIR-$1) && PATH="$(PROJECT_DIR)/$(PYTHON_DIR-$1)/dist/bin:$(PATH)" make all install
465484

485+
else
486+
# The LibFFI folder is shared between all architectures for the OS
466487
LIBFFI_DIR-$1=build/$1/libffi-$(LIBFFI_VERSION)
488+
# The Python targets are the same as they are for every other library
489+
PYTHON_TARGETS-$1=$$(TARGETS-$1)
467490

468491
# Unpack LibFFI and generate source & headers
469492
$$(LIBFFI_DIR-$1)/darwin_common: downloads/libffi-$(LIBFFI_VERSION).tgz
@@ -472,8 +495,9 @@ $$(LIBFFI_DIR-$1)/darwin_common: downloads/libffi-$(LIBFFI_VERSION).tgz
472495
tar zxf downloads/libffi-$(LIBFFI_VERSION).tgz --strip-components 1 -C $$(LIBFFI_DIR-$1)
473496
# Apply libffi patches. Apple builds of libffi use a utility script; that
474497
# script doesn't work with Python3 using the out-of-the-box version in
475-
# libffi 3.3. This patch matches what is in trunk as of Feb 2021 (and will
476-
# presumably be in libffi 3.4 or whatever comes next)
498+
# libffi 3.3. This patch adds some changes that will be included in libFFI
499+
# 3.4 (whenever that is released), plus some extra targets to support
500+
# tvOS and watchOS.
477501
cd $$(LIBFFI_DIR-$1) && patch -p1 < $(PROJECT_DIR)/patch/libffi/libffi.patch
478502
# Configure the build
479503
cd $$(LIBFFI_DIR-$1) && python generate-darwin-source-and-headers.py --only-$(shell echo $1 | tr '[:upper:]' '[:lower:]')
@@ -500,32 +524,30 @@ $1: Python-$1
500524
Python-$1: dist/Python-$(PYTHON_VER)-$1-support.$(BUILD_NUMBER).tar.gz
501525

502526
# Build Python
503-
$$(PYTHON_FRAMEWORK-$1): build/$1/libpython$(PYTHON_VER).a $$(foreach target,$$(TARGETS-$1),build/$1/$$(pyconfig.h-$$(target)))
527+
$$(PYTHON_FRAMEWORK-$1): build/$1/libpython$(PYTHON_VER).a $$(foreach target,$$(PYTHON_TARGETS-$1),build/$1/$$(pyconfig.h-$$(target)))
504528
mkdir -p $$(PYTHON_RESOURCES-$1)/include/python$(PYTHON_VER)
505529

506530
# Copy the headers. The headers are the same for every platform, except for pyconfig.h
507531
# We ship a master pyconfig.h for iOS, tvOS and watchOS that delegates to architecture
508532
# specific versions; on macOS, we can use the original version as-is.
509-
cp -f -r $$(PYTHON_DIR-$$(firstword $$(TARGETS-$1)))/dist/include/python$(PYTHON_VER) $$(PYTHON_FRAMEWORK-$1)/Headers
533+
cp -f -r $$(PYTHON_DIR-$$(firstword $$(PYTHON_TARGETS-$1)))/dist/include/python$(PYTHON_VER) $$(PYTHON_FRAMEWORK-$1)/Headers
534+
ifneq ($1,macOS)
510535
cp -f $$(filter %.h,$$^) $$(PYTHON_FRAMEWORK-$1)/Headers
511-
ifeq ($1,macOS)
512-
mv $$(PYTHON_FRAMEWORK-$1)/Headers/pyconfig-x86_64.h $$(PYTHON_FRAMEWORK-$1)/Headers/pyconfig.h
513-
else
514536
cp -f $(PROJECT_DIR)/patch/Python/pyconfig-$1.h $$(PYTHON_FRAMEWORK-$1)/Headers/pyconfig.h
515537
endif
516538
# Copy Python.h and pyconfig.h into the resources include directory
517539
cp -f -r $$(PYTHON_FRAMEWORK-$1)/Headers/pyconfig*.h $$(PYTHON_RESOURCES-$1)/include/python$(PYTHON_VER)
518540
cp -f -r $$(PYTHON_FRAMEWORK-$1)/Headers/Python.h $$(PYTHON_RESOURCES-$1)/include/python$(PYTHON_VER)
519541

520542
# Copy the standard library from the simulator build
521-
cp -f -r $$(PYTHON_DIR-$$(firstword $$(TARGETS-$1)))/dist/lib $$(PYTHON_RESOURCES-$1)
543+
cp -f -r $$(PYTHON_DIR-$$(firstword $$(PYTHON_TARGETS-$1)))/dist/lib $$(PYTHON_RESOURCES-$1)
522544

523545
# Copy fat library
524546
cp -f $$(filter %.a,$$^) $$(PYTHON_FRAMEWORK-$1)/libPython.a
525547

526548

527549
# Build libpython fat library
528-
build/$1/libpython$(PYTHON_VER).a: $$(foreach target,$$(TARGETS-$1),$$(PYTHON_DIR-$$(target))/dist/lib/libpython$(PYTHON_VER).a)
550+
build/$1/libpython$(PYTHON_VER).a: $$(foreach target,$$(PYTHON_TARGETS-$1),$$(PYTHON_DIR-$$(target))/dist/lib/libpython$(PYTHON_VER).a)
529551
# Create a fat binary for the libPython library
530552
mkdir -p build/$1
531553
xcrun lipo -create -output $$@ $$^
@@ -538,6 +560,7 @@ vars-$1: $$(foreach target,$$(TARGETS-$1),vars-$$(target))
538560
@echo "PYTHON_FRAMEWORK-$1: $$(PYTHON_FRAMEWORK-$1)"
539561
@echo "LIBFFI_DIR-$1: $$(LIBFFI_DIR-$1)"
540562
@echo "PYTHON_RESOURCES-$1: $$(PYTHON_RESOURCES-$1)"
563+
@echo "PYTHON_TARGETS-$1: $$(PYTHON_TARGETS-$1)"
541564

542565
endef
543566

0 commit comments

Comments
 (0)