Skip to content

Commit 0f2d634

Browse files
committed
Add a standalone libFFI build.
1 parent 8f659c8 commit 0f2d634

File tree

7 files changed

+276
-26
lines changed

7 files changed

+276
-26
lines changed

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,6 @@ build/*
66
downloads/*
77
diff/*
88
dist/*
9-
.env
9+
.envrc
10+
.vscode/
11+
local/*

Makefile

Lines changed: 129 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
#
22
# Useful targets:
3-
# - all - build everything
4-
# - macOS - build everything for macOS
5-
# - iOS - build everything for iOS
6-
# - tvOS - build everything for tvOS
7-
# - watchOS - build everything for watchOS
3+
# - all - build everything
4+
# - macOS - build everything for macOS
5+
# - iOS - build everything for iOS
6+
# - tvOS - build everything for tvOS
7+
# - watchOS - build everything for watchOS
88
# - OpenSSL-macOS - build OpenSSL for macOS
99
# - OpenSSL-iOS - build OpenSSL for iOS
1010
# - OpenSSL-tvOS - build OpenSSL for tvOS
@@ -17,6 +17,9 @@
1717
# - XZ-iOS - build XZ for iOS
1818
# - XZ-tvOS - build XZ for tvOS
1919
# - XZ-watchOS - build XZ for watchOS
20+
# - libFFI-iOS - build libFFI for iOS
21+
# - libFFI-tvOS - build libFFI for tvOS
22+
# - libFFI-watchOS - build libFFI for watchOS
2023
# - Python-macOS - build Python for macOS
2124
# - Python-iOS - build Python for iOS
2225
# - Python-tvOS - build Python for tvOS
@@ -41,6 +44,8 @@ BZIP2_VERSION=1.0.8
4144

4245
XZ_VERSION=5.2.5
4346

47+
LIBFFI_VERSION=3.3
48+
4449
# Supported OS
4550
OS=macOS iOS tvOS watchOS
4651

@@ -82,7 +87,7 @@ clean:
8287
distclean: clean
8388
rm -rf downloads
8489

85-
downloads: downloads/openssl-$(OPENSSL_VERSION).tgz downloads/bzip2-$(BZIP2_VERSION).tgz downloads/xz-$(XZ_VERSION).tgz downloads/Python-$(PYTHON_VERSION).tgz
90+
downloads: downloads/openssl-$(OPENSSL_VERSION).tgz downloads/bzip2-$(BZIP2_VERSION).tgz downloads/xz-$(XZ_VERSION).tgz downloads/libffi-$(LIBFFI_VERSION).tgz downloads/Python-$(PYTHON_VERSION).tgz
8691

8792
update-patch:
8893
# Generate a diff from the clone of the python/cpython Github repository
@@ -99,8 +104,9 @@ update-patch:
99104
# Clean the OpenSSL project
100105
clean-OpenSSL:
101106
rm -rf build/*/openssl-$(OPENSSL_VERSION)-* \
107+
build/*/openssl \
102108
build/*/libssl.a build/*/libcrypto.a \
103-
build/*/OpenSSL
109+
build/*/Support/OpenSSL
104110

105111
# Download original OpenSSL source code archive.
106112
downloads/openssl-$(OPENSSL_VERSION).tgz:
@@ -114,9 +120,10 @@ downloads/openssl-$(OPENSSL_VERSION).tgz:
114120
###########################################################################
115121

116122
# Clean the bzip2 project
117-
clean-bzip2:
123+
clean-BZip2:
118124
rm -rf build/*/bzip2-$(BZIP2_VERSION)-* \
119-
build/*/bzip2
125+
build/*/bzip2 \
126+
build/*/Support/BZip2
120127

121128
# Download original BZip2 source code archive.
122129
downloads/bzip2-$(BZIP2_VERSION).tgz:
@@ -128,15 +135,30 @@ downloads/bzip2-$(BZIP2_VERSION).tgz:
128135
###########################################################################
129136

130137
# Clean the XZ project
131-
clean-xz:
138+
clean-XZ:
132139
rm -rf build/*/xz-$(XZ_VERSION)-* \
133-
build/*/xz
140+
build/*/xz \
141+
build/*/Support/XZ
134142

135143
# Download original XZ source code archive.
136144
downloads/xz-$(XZ_VERSION).tgz:
137145
mkdir -p downloads
138146
if [ ! -e downloads/xz-$(XZ_VERSION).tgz ]; then curl --fail -L http://tukaani.org/xz/xz-$(XZ_VERSION).tar.gz -o downloads/xz-$(XZ_VERSION).tgz; fi
139147

148+
###########################################################################
149+
# LIBFFI
150+
###########################################################################
151+
152+
# Clean the LibFFI project
153+
clean-libFFI:
154+
rm -rf build/*/libffi-$(LIBFFI_VERSION) \
155+
build/*/Support/libFFI
156+
157+
# Download original XZ source code archive.
158+
downloads/libffi-$(LIBFFI_VERSION).tgz:
159+
mkdir -p downloads
160+
if [ ! -e downloads/libffi-$(LIBFFI_VERSION).tgz ]; then curl --fail -L http://github.com/libffi/libffi/releases/download/v$(LIBFFI_VERSION)/libffi-$(LIBFFI_VERSION).tar.gz -o downloads/libffi-$(LIBFFI_VERSION).tgz; fi
161+
140162
###########################################################################
141163
# Python
142164
###########################################################################
@@ -147,7 +169,7 @@ clean-Python:
147169
build/*/Python-$(PYTHON_VERSION)-* \
148170
build/*/libpython$(PYTHON_VER).a \
149171
build/*/pyconfig-*.h \
150-
build/*/Python
172+
build/*/Support/Python
151173

152174
# Download original Python source code archive.
153175
downloads/Python-$(PYTHON_VERSION).tgz:
@@ -186,6 +208,7 @@ LDFLAGS-$1=-arch $$(ARCH-$1) -isysroot=$$(SDK_ROOT-$1)
186208
OPENSSL_DIR-$1=build/$2/openssl-$(OPENSSL_VERSION)-$1
187209
BZIP2_DIR-$1=build/$2/bzip2-$(BZIP2_VERSION)-$1
188210
XZ_DIR-$1=build/$2/xz-$(XZ_VERSION)-$1
211+
LIBFFI_DIR-$1=build/$2/libffi-$(LIBFFI_VERSION)
189212
PYTHON_DIR-$1=build/$2/Python-$(PYTHON_VERSION)-$1
190213
pyconfig.h-$1=pyconfig-$$(ARCH-$1).h
191214

@@ -265,29 +288,52 @@ $$(XZ_DIR-$1)/Makefile: downloads/xz-$(XZ_VERSION).tgz
265288
$$(XZ_DIR-$1)/src/liblzma/.libs/liblzma.a: $$(XZ_DIR-$1)/Makefile
266289
cd $$(XZ_DIR-$1) && make && make install
267290

291+
# No need to build libFFI on macOS
292+
ifneq ($2,macOS)
293+
294+
# libFFI has it's own internal build directories for each Apple platform
295+
ifeq ($$(ARCH-$1),x86_64)
296+
LIBFFI_BUILD_DIR-$1=build_iphonesimulator-x86_64
297+
else ifeq ($$(ARCH-$1),i386)
298+
LIBFFI_BUILD_DIR-$1=build_iphonesimulator-i386
299+
else ifeq ($$(ARCH-$1),arm64)
300+
LIBFFI_BUILD_DIR-$1=build_iphoneos-arm64
301+
else ifeq ($$(ARCH-$1),armv7)
302+
LIBFFI_BUILD_DIR-$1=build_iphoneos-armv7
303+
else ifeq ($$(ARCH-$1),armv7k)
304+
LIBFFI_BUILD_DIR-$1=build_iphoneos-armv7
305+
else
306+
# This is a canary - it should never occur, so if you see it,
307+
# you've got a problem.
308+
LIBFFI_BUILD_DIR-$1=build_other
309+
endif
310+
311+
# Build LibFFI
312+
$$(LIBFFI_DIR-$1)/libffi.$1.a: $$(LIBFFI_DIR-$1)/darwin_common
313+
cd $$(LIBFFI_DIR-$1)/$$(LIBFFI_BUILD_DIR-$1) && make
314+
315+
# Copy in the lib to a non-BUILD_DIR dependent location;
316+
# include the target in the final filename for disambiguation
317+
cp $$(LIBFFI_DIR-$1)/$$(LIBFFI_BUILD_DIR-$1)/.libs/libffi.a $$(LIBFFI_DIR-$1)/libffi.$1.a
318+
319+
endif
320+
268321
# Unpack Python
269322
$$(PYTHON_DIR-$1)/Makefile: downloads/Python-$(PYTHON_VERSION).tgz $$(PYTHON_HOST-$1)
270323
# Unpack target Python
271324
mkdir -p $$(PYTHON_DIR-$1)
272325
tar zxf downloads/Python-$(PYTHON_VERSION).tgz --strip-components 1 -C $$(PYTHON_DIR-$1)
273326
# Apply target Python patches
274327
cd $$(PYTHON_DIR-$1) && patch -p1 < $(PROJECT_DIR)/patch/Python/Python.patch
328+
# Copy in the embedded module configuration
329+
cat $(PROJECT_DIR)/patch/Python/Setup.embedded $(PROJECT_DIR)/patch/Python/Setup.$2 > $$(PYTHON_DIR-$1)/Modules/Setup.local
275330
# Configure target Python
276331
ifeq ($2,macOS)
277-
# A locally hosted Python requires a full Setup.local configuration
278-
# because there's no PYTHON_HOST_PLATFORM to cause Setup.local to be
279-
# generated
280-
cat $(PROJECT_DIR)/patch/Python/Setup.embedded $(PROJECT_DIR)/patch/Python/Setup.macOS-x86_64 > $$(PYTHON_DIR-$1)/Modules/Setup.local
281-
# Make a fully embedded macOS build
282332
cd $$(PYTHON_DIR-$1) && MACOSX_DEPLOYMENT_TARGET=$$(MACOSX_DEPLOYMENT_TARGET) ./configure \
283333
--prefix=$(PROJECT_DIR)/$$(PYTHON_DIR-$1)/dist \
284334
--without-doc-strings --enable-ipv6 --without-ensurepip \
285335
$$(PYTHON_CONFIGURE-$2)
286336
else
287-
# Copy in the embedded and platform/arch configuration
288-
cp -f $(PROJECT_DIR)/patch/Python/Setup.embedded $$(PYTHON_DIR-$1)/Modules/Setup.embedded
289-
if [ -e "$(PROJECT_DIR)/patch/Python/Setup.$2-$$(ARCH-$1)" ]; then \
290-
cp -f $(PROJECT_DIR)/patch/Python/Setup.$2-$$(ARCH-$1) $$(PYTHON_DIR-$1)/Modules/Setup.$2-$$(ARCH-$1); fi
291337
cd $$(PYTHON_DIR-$1) && PATH=$(PROJECT_DIR)/$(PYTHON_DIR-macOS)/dist/bin:$(PATH) ./configure \
292338
CC="$$(CC-$1)" LD="$$(CC-$1)" \
293339
--host=$$(MACHINE_DETAILED-$1)-apple-$(shell echo $2 | tr '[:upper:]' '[:lower:]') \
@@ -299,7 +345,7 @@ else
299345
endif
300346

301347
# Build Python
302-
$$(PYTHON_DIR-$1)/dist/lib/libpython$(PYTHON_VER).a: build/$2/Support/OpenSSL build/$2/Support/BZip2 build/$2/Support/XZ $$(PYTHON_DIR-$1)/Makefile
348+
$$(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
303349
# Build target Python
304350
cd $$(PYTHON_DIR-$1) && PATH="$(PROJECT_DIR)/$(PYTHON_DIR-macOS)/dist/bin:$(PATH)" make all install
305351

@@ -313,6 +359,14 @@ vars-$1:
313359
@echo "SDK-$1: $$(SDK-$1)"
314360
@echo "SDK_ROOT-$1: $$(SDK_ROOT-$1)"
315361
@echo "CC-$1: $$(CC-$1)"
362+
@echo "LIBFFI_BUILD_DIR-$1: $$(LIBFFI_BUILD_DIR-$1)"
363+
@echo "OPENSSL_DIR-$1: $$(OPENSSL_DIR-$1)"
364+
@echo "BZIP2_DIR-$1: $$(BZIP2_DIR-$1)"
365+
@echo "XZ_DIR-$1: $$(XZ_DIR-$1)"
366+
@echo "LIBFFI_DIR-$1: $$(LIBFFI_DIR-$1)"
367+
@echo "PYTHON_DIR-$1: $$(PYTHON_DIR-$1)"
368+
@echo "pyconfig.h-$1: $$(pyconfig.h-$1)"
369+
316370
endef
317371

318372
#
@@ -325,6 +379,7 @@ $$(foreach target,$$(TARGETS-$1),$$(eval $$(call build-target,$$(target),$1)))
325379
OPENSSL_FRAMEWORK-$1=build/$1/Support/OpenSSL
326380
BZIP2_FRAMEWORK-$1=build/$1/Support/BZip2
327381
XZ_FRAMEWORK-$1=build/$1/Support/XZ
382+
LIBFFI_FRAMEWORK-$1=build/$1/Support/libFFI
328383
PYTHON_FRAMEWORK-$1=build/$1/Support/Python
329384
PYTHON_RESOURCES-$1=$$(PYTHON_FRAMEWORK-$1)/Resources
330385

@@ -333,11 +388,16 @@ $1: dist/Python-$(PYTHON_VER)-$1-support.$(BUILD_NUMBER).tar.gz
333388
clean-$1:
334389
rm -rf build/$1
335390

336-
dist/Python-$(PYTHON_VER)-$1-support.$(BUILD_NUMBER).tar.gz: $$(BZIP2_FRAMEWORK-$1) $$(XZ_FRAMEWORK-$1) $$(OPENSSL_FRAMEWORK-$1) $$(PYTHON_FRAMEWORK-$1)
391+
dist/Python-$(PYTHON_VER)-$1-support.$(BUILD_NUMBER).tar.gz: $$(BZIP2_FRAMEWORK-$1) $$(XZ_FRAMEWORK-$1) $$(OPENSSL_FRAMEWORK-$1) $$(LIBFFI_FRAMEWORK-$1) $$(PYTHON_FRAMEWORK-$1)
337392
mkdir -p dist
338393
echo "Python version: $(PYTHON_VERSION) " > build/$1/Support/VERSIONS
339394
echo "Build: $(BUILD_NUMBER)" >> build/$1/Support/VERSIONS
340395
echo "---------------------" >> build/$1/Support/VERSIONS
396+
ifeq ($1,macOS)
397+
echo "libFFI: macOS native" >> build/$1/Support/VERSIONS
398+
else
399+
echo "libFFI: $(LIBFFI_VERSION)" >> build/$1/Support/VERSIONS
400+
endif
341401
echo "BZip2: $(BZIP2_VERSION)" >> build/$1/Support/VERSIONS
342402
echo "OpenSSL: $(OPENSSL_VERSION)" >> build/$1/Support/VERSIONS
343403
echo "XZ: $(XZ_VERSION)" >> build/$1/Support/VERSIONS
@@ -412,6 +472,45 @@ build/$1/xz/lib/liblzma.a: $$(foreach target,$$(TARGETS-$1),$$(XZ_DIR-$$(target)
412472
mkdir -p build/$1
413473
xcrun lipo -create -o $$@ $$^
414474

475+
# Build libFFI
476+
libFFI-$1: $$(LIBFFI_FRAMEWORK-$1)
477+
478+
ifeq ($1,macOS)
479+
$$(LIBFFI_FRAMEWORK-$1): # noop
480+
else
481+
482+
LIBFFI_DIR-$1=build/$1/libffi-$(LIBFFI_VERSION)
483+
484+
# Unpack LibFFI and generate source & headers
485+
$$(LIBFFI_DIR-$1)/darwin_common: downloads/libffi-$(LIBFFI_VERSION).tgz
486+
# Unpack sources
487+
mkdir -p $$(LIBFFI_DIR-$1)
488+
tar zxf downloads/libffi-$(LIBFFI_VERSION).tgz --strip-components 1 -C $$(LIBFFI_DIR-$1)
489+
# Apply libffi patches. Apple builds of libffi use a utility script; that
490+
# script doesn't work with Python3 using the out-of-the-box version in
491+
# libffi 3.3. This patch matches what is in trunk as of Feb 2021 (and will
492+
# presumably be in libffi 3.4 or whatever comes next)
493+
cd $$(LIBFFI_DIR-$1) && patch -p1 < $(PROJECT_DIR)/patch/libffi/libffi.patch
494+
# Configure the build
495+
cd $$(LIBFFI_DIR-$1) && python generate-darwin-source-and-headers.py --only-ios
496+
497+
$$(LIBFFI_FRAMEWORK-$1): $$(LIBFFI_DIR-$1)/libffi.a
498+
# Create framework directory structure
499+
mkdir -p $$(LIBFFI_FRAMEWORK-$1)
500+
501+
# Copy the headers.
502+
cp -f -r $$(LIBFFI_DIR-$1)/darwin_common/include $$(LIBFFI_FRAMEWORK-$1)/Headers
503+
cp -f -r $$(LIBFFI_DIR-$1)/darwin_ios/include/* $$(LIBFFI_FRAMEWORK-$1)/Headers
504+
505+
# Create the fat library
506+
xcrun libtool -no_warning_for_no_symbols -static \
507+
-o $$(LIBFFI_FRAMEWORK-$1)/libFFI.a $$^
508+
509+
$$(LIBFFI_DIR-$1)/libffi.a: $$(foreach target,$$(TARGETS-$1),$$(LIBFFI_DIR-$1)/libffi.$$(target).a)
510+
xcrun lipo -create -o $$@ $$^
511+
512+
endif
513+
415514
$1: Python-$1
416515

417516
Python-$1: dist/Python-$(PYTHON_VER)-$1-support.$(BUILD_NUMBER).tar.gz
@@ -448,6 +547,13 @@ build/$1/libpython$(PYTHON_VER).a: $$(foreach target,$$(TARGETS-$1),$$(PYTHON_DI
448547
xcrun lipo -create -output $$@ $$^
449548

450549
vars-$1: $$(foreach target,$$(TARGETS-$1),vars-$$(target))
550+
@echo "OPENSSL_FRAMEWORK-$1: $$(OPENSSL_FRAMEWORK-$1)"
551+
@echo "BZIP2_FRAMEWORK-$1: $$(BZIP2_FRAMEWORK-$1)"
552+
@echo "XZ_FRAMEWORK-$1: $$(XZ_FRAMEWORK-$1)"
553+
@echo "LIBFFI_FRAMEWORK-$1: $$(LIBFFI_FRAMEWORK-$1)"
554+
@echo "PYTHON_FRAMEWORK-$1: $$(PYTHON_FRAMEWORK-$1)"
555+
@echo "LIBFFI_DIR-$1: $$(LIBFFI_DIR-$1)"
556+
@echo "PYTHON_RESOURCES-$1: $$(PYTHON_RESOURCES-$1)"
451557

452558
endef
453559

patch/Python/Setup.iOS

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
2+
#####################################################################
3+
# iOS: Platform specific configuration
4+
#####################################################################
5+
_ctypes _ctypes/_ctypes.c \
6+
_ctypes/callbacks.c \
7+
_ctypes/callproc.c \
8+
_ctypes/stgdict.c \
9+
_ctypes/cfield.c \
10+
_ctypes/malloc_closure.c \
11+
-I$(srcdir)/Modules/_ctypes/darwin \
12+
-I$(srcdir)/../Support/libFFI/Headers \
13+
-DPy_BUILD_CORE_MODULE \
14+
-DHAVE_FFI_PREP_CIF_VAR=1 \
15+
-DHAVE_FFI_PREP_CLOSURE_LOC=1 -DHAVE_FFI_CLOSURE_ALLOC=1 \
16+
-L$(srcdir)/../Support/libFFI \
17+
-lFFI
18+
19+
20+
_decimal _decimal/_decimal.c \
21+
_decimal/libmpdec/basearith.c \
22+
_decimal/libmpdec/constants.c \
23+
_decimal/libmpdec/context.c \
24+
_decimal/libmpdec/convolute.c \
25+
_decimal/libmpdec/crt.c \
26+
_decimal/libmpdec/difradix2.c \
27+
_decimal/libmpdec/fnt.c \
28+
_decimal/libmpdec/fourstep.c \
29+
_decimal/libmpdec/io.c \
30+
_decimal/libmpdec/mpalloc.c \
31+
_decimal/libmpdec/mpdecimal.c \
32+
_decimal/libmpdec/numbertheory.c \
33+
_decimal/libmpdec/sixstep.c \
34+
_decimal/libmpdec/transpose.c \
35+
-I$(srcdir)/Modules/_decimal/libmpdec \
36+
-DCONFIG_64=1 -DANSI=1 -DHAVE_UINT128_T=1

patch/Python/Setup.macOS-x86_64 renamed to patch/Python/Setup.macOS

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11

22
#####################################################################
3-
# macOS x86_64: Platform specific configuration
3+
# macOS: Platform specific configuration
44
#####################################################################
55
_ctypes _ctypes/_ctypes.c \
66
_ctypes/callbacks.c \
77
_ctypes/callproc.c \
88
_ctypes/stgdict.c \
99
_ctypes/cfield.c \
1010
_ctypes/malloc_closure.c \
11-
-I$(src_dir)/Modules/_ctypes/darwin \
11+
-I$(srcdir)/Modules/_ctypes/darwin \
1212
-I/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/ffi \
1313
-DPy_BUILD_CORE_MODULE -DUSING_MALLOC_CLOSURE_DOT_C=1 -DMACOSX \
1414
-DUSING_APPLE_OS_LIBFFI=1 -DHAVE_FFI_PREP_CIF_VAR=1 \

patch/Python/Setup.tvOS

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
2+
#####################################################################
3+
# tvOS: Platform specific configuration
4+
#####################################################################
5+
_ctypes _ctypes/_ctypes.c \
6+
_ctypes/callbacks.c \
7+
_ctypes/callproc.c \
8+
_ctypes/stgdict.c \
9+
_ctypes/cfield.c \
10+
_ctypes/malloc_closure.c \
11+
-I$(srcdir)/Modules/_ctypes/darwin \
12+
-I$(srcdir)/../Support/libFFI/Headers \
13+
-DPy_BUILD_CORE_MODULE \
14+
-DHAVE_FFI_PREP_CIF_VAR=1 \
15+
-DHAVE_FFI_PREP_CLOSURE_LOC=1 -DHAVE_FFI_CLOSURE_ALLOC=1 \
16+
-L$(srcdir)/../Support/libFFI \
17+
-lFFI
18+
19+
20+
_decimal _decimal/_decimal.c \
21+
_decimal/libmpdec/basearith.c \
22+
_decimal/libmpdec/constants.c \
23+
_decimal/libmpdec/context.c \
24+
_decimal/libmpdec/convolute.c \
25+
_decimal/libmpdec/crt.c \
26+
_decimal/libmpdec/difradix2.c \
27+
_decimal/libmpdec/fnt.c \
28+
_decimal/libmpdec/fourstep.c \
29+
_decimal/libmpdec/io.c \
30+
_decimal/libmpdec/mpalloc.c \
31+
_decimal/libmpdec/mpdecimal.c \
32+
_decimal/libmpdec/numbertheory.c \
33+
_decimal/libmpdec/sixstep.c \
34+
_decimal/libmpdec/transpose.c \
35+
-I$(srcdir)/Modules/_decimal/libmpdec \
36+
-DCONFIG_64=1 -DANSI=1 -DHAVE_UINT128_T=1

0 commit comments

Comments
 (0)