1- PROJECTDIR =$(shell pwd)
1+ #
2+ # Useful targets:
3+ # - all-iOS - build everything for iOS
4+ # - all-tvOS - build everything for tvOS
5+ # - all-watchOS - build everything for watchOS
6+ # - OpenSSL.framework-iOS - build OpenSSL.framework for iOS
7+ # - OpenSSL.framework-tvOS - build OpenSSL.framework for tvOS
8+ # - OpenSSL.framework-watchOS - build OpenSSL.framework for watchOS
9+ # - Python-host - build host python
10+ # - Python.framework-iOS - build Python.framework for iOS
11+ # - Python.framework-tvOS - build Python.framework for tvOS
12+ # - Python.framework-watchOS - build Python.framework for watchOS
13+
14+ # Current director
15+ PROJECT_DIR =$(shell pwd)
216
317BUILD_NUMBER =3
418
519# Version of packages that will be compiled by this meta-package
6- PYTHON_VERSION =3.4.2
20+ PYTHON_VERSION = 3.4.2
21+ PYTHON_VER = $(basename $(PYTHON_VERSION ) )
722
823OPENSSL_VERSION_NUMBER =1.0.2
924OPENSSL_REVISION =d
1025OPENSSL_VERSION =$(OPENSSL_VERSION_NUMBER )$(OPENSSL_REVISION )
1126
27+ # Supported OS
1228OS = iOS tvOS watchOS
29+
30+ # iOS targets
1331TARGETS-iOS = iphonesimulator.x86_64 iphonesimulator.i386\
1432 iphoneos.armv7 iphoneos.armv7s iphoneos.arm64
1533CFLAGS-iOS = -miphoneos-version-min=7.0
1634CFLAGS-iphoneos.armv7 = -fembed-bitcode
1735CFLAGS-iphoneos.armv7s = -fembed-bitcode
1836CFLAGS-iphoneos.arm64 = -fembed-bitcode
1937
38+ # tvOS targets
2039TARGETS-tvOS = appletvsimulator.x86_64 appletvos.arm64
2140CFLAGS-tvOS = -mtvos-version-min=9.0
2241CFLAGS-appletvos.arm64 = -fembed-bitcode
42+ PYTHON_CONFIGURE-tvOS = ac_cv_func_sigaltstack=no
2343
44+ # watchOS targets
2445TARGETS-watchOS = watchsimulator.i386 watchos.armv7k
2546CFLAGS-watchOS = -mwatchos-version-min=2.0
26- CFLAGS-watchos.armv7 = -fembed-bitcode
47+ CFLAGS-watchos.armv7k = -fembed-bitcode
48+ PYTHON_CONFIGURE-watchOS=ac_cv_func_sigaltstack =no
2749
28- all : $(foreach os,$(OS ) ,Python -$(PYTHON_VERSION ) - $( os )-support.b $( BUILD_NUMBER ) .tar.gz )
50+ all : $(foreach os,$(OS ) ,all -$(os ) )
2951
3052# Clean all builds
3153clean :
32- rm -rf build dist $(foreach os,$(OS ) ,Python-$(PYTHON_VERSION ) -$(os ) -support.b$(BUILD_NUMBER ) .tar.gz)
54+ rm -rf build $(foreach os,$(OS ) ,Python-$(PYTHON_VERSION ) -$(os ) -support.b$(BUILD_NUMBER ) .tar.gz)
3355
3456# Full clean - includes all downloaded products
3557distclean : clean
@@ -45,124 +67,236 @@ downloads: downloads/openssl-$(OPENSSL_VERSION).tgz downloads/Python-$(PYTHON_VE
4567
4668# Clean the OpenSSL project
4769clean-OpenSSL :
48- rm -rf build/OpenSSL
49- rm -rf dist/OpenSSL.framework
70+ rm -rf build/* /openssl-$(OPENSSL_VERSION ) -* build/* /OpenSSL.framework
5071
5172# Download original OpenSSL source code archive.
5273downloads/openssl-$(OPENSSL_VERSION ) .tgz :
5374 mkdir downloads
5475 -if [ ! -e downloads/openssl-$( OPENSSL_VERSION) .tgz ]; then curl --fail -L http://openssl.org/source/openssl-$(OPENSSL_VERSION ) .tar.gz -o downloads/openssl-$(OPENSSL_VERSION ) .tgz; fi
5576 if [ ! -e downloads/openssl-$( OPENSSL_VERSION) .tgz ]; then curl --fail -L http://openssl.org/source/old/$( OPENSSL_VERSION_NUMBER) /openssl-$( OPENSSL_VERSION) .tar.gz -o downloads/openssl-$( OPENSSL_VERSION) .tgz; fi
5677
57- define build-openssl-target
78+ # ##########################################################################
79+ # Python
80+ # ##########################################################################
81+
82+ # Clean the Python project
83+ clean-Python :
84+ rm -rf build/* /Python-$(PYTHON_VERSION ) -* build/* /Python.framework
85+
86+ # Download original Python source code archive.
87+ downloads/Python-$(PYTHON_VERSION ) .tgz :
88+ mkdir downloads
89+ 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
90+
91+ PYTHON_DIR-host = build/Python-$(PYTHON_VERSION ) -host
92+
93+ Python-host : $(PYTHON_DIR-host ) /dist/bin/python$(PYTHON_VER )
94+
95+ # Unpack host Python
96+ $(PYTHON_DIR-host ) /configure : downloads/Python-$(PYTHON_VERSION ) .tgz
97+ # Unpack host Python
98+ mkdir -p $(PYTHON_DIR-host )
99+ tar zxf downloads/Python-$(PYTHON_VERSION ) .tgz --strip-components 1 -C $(PYTHON_DIR-host )
100+ # Configure host Python
101+ cd $(PYTHON_DIR-host ) && ./configure --prefix=$(PROJECT_DIR ) /$(PYTHON_DIR-host ) /dist --without-ensurepip
102+
103+ # Build host Python
104+ $(PYTHON_DIR-host ) /dist/bin/python$(PYTHON_VER ) : $(PYTHON_DIR-host ) /Makefile
105+ # Build host Python
106+ make -C $(PYTHON_DIR-host ) all install
107+
108+ #
109+ # Build for specified target (from $(TARGETS))
110+ #
111+ # Parameters:
112+ # - $1 - target
113+ # - $2 - OS
114+ define build-target
58115ARCH-$1= $$(subst .,,$$(suffix $1) )
59116SDK-$1= $$(basename $1)
60117
61118SDK_ROOT-$1= $$(shell xcrun --sdk $$(SDK-$1 ) --show-sdk-path)
62- CC-$1= $$( shell xcrun -find -sdk $$(SDK-$1 ) clang) \
119+ CC-$1= xcrun --sdk $$(SDK-$1 ) clang\
63120 -arch $$(ARCH-$1 ) --sysroot=$$(SDK_ROOT-$1 ) $$(CFLAGS-$2 ) $$(CFLAGS-$1 )
64121
65- build/OpenSSL/$1/Makefile: downloads/openssl-$(OPENSSL_VERSION ) .tgz
122+ OPENSSL_DIR-$1= build/$2/openssl-$(OPENSSL_VERSION ) -$1
123+ PYTHON_DIR-$1= build/$2/Python-$(PYTHON_VERSION ) -$1
124+
125+ # Unpack OpenSSL
126+ $$(OPENSSL_DIR-$1 ) /Makefile: downloads/openssl-$(OPENSSL_VERSION ) .tgz
66127 # Unpack sources
67- mkdir -p build/OpenSSL/$1
68- tar zxf downloads/openssl-$(OPENSSL_VERSION ) .tgz --strip-components 1 -C build/OpenSSL/$1
128+ mkdir -p $$( OPENSSL_DIR-$1 )
129+ tar zxf downloads/openssl-$(OPENSSL_VERSION ) .tgz --strip-components 1 -C $$( OPENSSL_DIR-$1 )
69130ifeq ($$(findstring simulator,$$(SDK-$1 ) ) ,)
70131 # Tweak ui_openssl.c
71- sed -ie "s!static volatile sig_atomic_t intr_signal;!static volatile intr_signal;!" build/OpenSSL/$1 /crypto/ui/ui_openssl.c
132+ sed -ie "s!static volatile sig_atomic_t intr_signal;!static volatile intr_signal;!" $$(OPENSSL_DIR-$1) /crypto/ui/ui_openssl.c
72133endif
73134ifeq ($$(findstring iphone,$$(SDK-$1 ) ) ,)
74135 # Patch apps/speed.c to not use fork() since it's not available on tvOS
75- sed -ie 's/define HAVE_FORK 1/define HAVE_FORK 0/' build/OpenSSL/$1 /apps/speed.c
136+ sed -ie 's/define HAVE_FORK 1/define HAVE_FORK 0/' $$(OPENSSL_DIR-$1) /apps/speed.c
76137 # Patch Configure to build for tvOS or watchOS, not iOS
77- LANG=C sed -ie 's/-D_REENTRANT:iOS/-D_REENTRANT:$2/' build/OpenSSL/$1 /Configure
138+ LANG=C sed -ie 's/-D_REENTRANT:iOS/-D_REENTRANT:$2/' $$(OPENSSL_DIR-$1) /Configure
78139endif
79140 # Configure the build
80- cd build/OpenSSL/$1 && \
141+ cd $$( OPENSSL_DIR-$1 ) && \
81142 CC="$$(CC-$1 ) " \
82143 CROSS_TOP="$$(dir $$(SDK_ROOT-$1 ) ) .." \
83144 CROSS_SDK="$$(notdir $$(SDK_ROOT-$1 ) ) " \
84- ./Configure iphoneos-cross no-asm --openssldir=$(PROJECTDIR ) /build/OpenSSL/$1
145+ ./Configure iphoneos-cross no-asm --openssldir=$(PROJECT_DIR ) / $$( OPENSSL_DIR-$1 )
85146
86- build/OpenSSL/$1/libssl.a build/OpenSSL/$1/libcrypto.a: build/OpenSSL/$1/Makefile
147+ # Build OpenSSL
148+ $$(OPENSSL_DIR-$1 ) /libssl.a $$(OPENSSL_DIR-$1 ) /libcrypto.a: $$(OPENSSL_DIR-$1 ) /Makefile
87149 # Make the build
88- cd build/OpenSSL/$1 && \
150+ cd $$( OPENSSL_DIR-$1 ) && \
89151 CC="$$(CC-$1 ) " \
90152 CROSS_TOP="$$(dir $$(SDK_ROOT-$1 ) ) .." \
91153 CROSS_SDK="$$(notdir $$(SDK_ROOT-$1 ) ) " \
92154 make all
93155
156+ # Unpack Python
157+ $$(PYTHON_DIR-$1 ) /Makefile: downloads/Python-$(PYTHON_VERSION ) .tgz
158+ # Unpack target Python
159+ mkdir -p $$(PYTHON_DIR-$1 )
160+ tar zxf downloads/Python-$(PYTHON_VERSION ) .tgz --strip-components 1 -C $$(PYTHON_DIR-$1 )
161+ # Apply target Python patches
162+ cd $$(PYTHON_DIR-$1 ) && patch -p1 <$(PROJECT_DIR ) /patch/Python/Python.patch
163+ ifeq ($$(findstring iphone,$$(SDK-$1 ) ) ,)
164+ cd $$(PYTHON_DIR-$1) && patch -p1 <$(PROJECT_DIR)/patch/Python/Python-tvos.patch
165+ endif
166+ cp $(PROJECT_DIR ) /patch/Python/Setup.embedded $$(PYTHON_DIR-$1 ) /Modules/Setup.embedded
167+ # Configure target Python
168+ cd $$(PYTHON_DIR-$1 ) && PATH=$(PROJECT_DIR ) /$(PYTHON_DIR-host ) /dist/bin:$(PATH ) ./configure \
169+ CC="$$(CC-$1 ) " LD="$$(CC-$1 ) " \
170+ --host=$$(ARCH-$1 ) -apple-ios --build=x86_64-apple-darwin$(shell uname -r) \
171+ --prefix=$(PROJECT_DIR ) /$$(PYTHON_DIR-$1 ) /dist \
172+ --without-pymalloc --without-doc-strings --disable-ipv6 --without-ensurepip \
173+ ac_cv_file__dev_ptmx=no ac_cv_file__dev_ptc=no \
174+ $$(PYTHON_CONFIGURE-$2 )
175+
176+ # Build Python
177+ $$(PYTHON_DIR-$1 ) /dist/lib/libpython$(PYTHON_VER ) .a: $$(PYTHON_DIR-$1 ) /Makefile build/$2/OpenSSL.framework
178+ # Build target Python
179+ cd $$(PYTHON_DIR-$1 ) && PATH=$(PROJECT_DIR ) /$(PYTHON_DIR-host ) /dist/bin:$(PATH ) make all install
180+
181+ # Dump vars (for test)
94182vars-$1:
95183 @echo "ARCH-$1: $$(ARCH-$1 ) "
96184 @echo "SDK-$1: $$(SDK-$1 ) "
97185 @echo "SDK_ROOT-$1: $$(SDK_ROOT-$1 ) "
98186 @echo "CC-$1: $$(CC-$1 ) "
99187endef
100188
101- define build-openssl
102- $$(foreach target,$$(TARGETS-$1 ) ,$$(eval $$(call build-openssl-target,$$(target ) ,$1) ) )
189+ #
190+ # Build for specified OS (from $(OS))
191+ # Parameters:
192+ # - $1 - OS
193+ define build
194+ $$(foreach target,$$(TARGETS-$1 ) ,$$(eval $$(call build-target,$$(target ) ,$1) ) )
195+
196+ all-$1: Python-$(PYTHON_VERSION ) -$1-support.b$(BUILD_NUMBER ) .tar.gz
103197
104- Python- $( PYTHON_VERSION ) -$1-support.b $( BUILD_NUMBER ) .tar.gz: dist/$1/OpenSSL.framework dist/$1/Python.framework
105- tar zcvf $$@ -C dist /$1 Python.framework OpenSSL.framework
198+ clean-$1:
199+ rm -rf build /$1
106200
107- build/OpenSSL/$1/libssl.a: $$(foreach target,$$(TARGETS-$1 ) ,build/OpenSSL/$$(target ) /libssl.a)
108- mkdir -p build/OpenSSL/$1
109- lipo -create $$^ -output $$@
201+ Python-$(PYTHON_VERSION ) -$1-support.b$(BUILD_NUMBER ) .tar.gz: build/$1/OpenSSL.framework build/$1/Python.framework
202+ tar zcvf $$@ -C build/$1 Python.framework OpenSSL.framework
110203
111- build/OpenSSL/$1/libcrypto.a: $$(foreach target,$$(TARGETS-$1 ) ,build/OpenSSL/$$(target ) /libcrypto.a)
112- mkdir -p build/OpenSSL/$1
113- lipo -create $$^ -output $$@
204+ OpenSSL.framework-$1: build/$1/OpenSSL.framework
114205
115- dist/$1/OpenSSL.framework: build/OpenSSL/$1/libssl.a build/OpenSSL/$1/libcrypto.a
206+ # Build OpenSSL.framework
207+ build/$1/OpenSSL.framework: build/$1/libssl.a build/$1/libcrypto.a
116208 # Create framework directory structure
117- mkdir -p dist /$1/OpenSSL.framework/Versions/$(OPENSSL_VERSION )
118- ln -fs $(OPENSSL_VERSION ) dist /$1/OpenSSL.framework/Versions/Current
209+ mkdir -p build /$1/OpenSSL.framework/Versions/$(OPENSSL_VERSION )
210+ ln -fs $(OPENSSL_VERSION ) build /$1/OpenSSL.framework/Versions/Current
119211
120212 # Copy the headers (use the version from the simulator because reasons)
121- cp -r build/OpenSSL/ $$(firstword $$(TARGETS-$1 ) ) /include dist /$1/OpenSSL.framework/Versions/Current/Headers
213+ cp -r $$(OPENSSL_DIR- $$( firstword $$(TARGETS-$1 ) )) /include build /$1/OpenSSL.framework/Versions/Current/Headers
122214
123215 # Link the current Headers to the top level
124- ln -fs Versions/Current/Headers dist /$1/OpenSSL.framework
216+ ln -fs Versions/Current/Headers build /$1/OpenSSL.framework
125217
126218 # Create the fat library
127- $(shell xcrun -find libtool) -no_warning_for_no_symbols -static \
128- -o dist/$1/OpenSSL.framework/Versions/Current/OpenSSL \
129- build/OpenSSL/$1/libcrypto.a \
130- build/OpenSSL/$1/libssl.a
219+ xcrun libtool -no_warning_for_no_symbols -static \
220+ -o build/$1/OpenSSL.framework/Versions/Current/OpenSSL $$^
131221
132222 # Link the fat Library to the top level
133- ln -fs Versions/Current/OpenSSL dist/$1/OpenSSL.framework
223+ ln -fs Versions/Current/OpenSSL build/$1/OpenSSL.framework
224+
225+ build/$1/libssl.a: $$(foreach target,$$(TARGETS-$1 ) ,$$(OPENSSL_DIR-$$(target ) ) /libssl.a)
226+ mkdir -p build/$1
227+ xcrun lipo -create -output $$@ $$^
228+
229+ build/$1/libcrypto.a: $$(foreach target,$$(TARGETS-$1 ) ,$$(OPENSSL_DIR-$$(target ) ) /libcrypto.a)
230+ mkdir -p build/$1
231+ xcrun lipo -create -output $$@ $$^
232+
233+ Python.framework-$1: build/$1/Python.framework
234+
235+ # Build Python.framework
236+ build/$1/Python.framework: build/$1/libpython$(PYTHON_VER ) .a
237+
238+ # Build libpython fat library
239+ build/$1/libpython$(PYTHON_VER ) .a: $$(foreach target,$$(TARGETS-$1 ) ,$$(PYTHON_DIR-$$(target ) ) /dist/lib/libpython$(PYTHON_VER ) .a)
240+ mkdir -p build/$1
241+ xcrun lipo -create -output $$@ $$^
242+
134243endef
135244
136- $(foreach os,$(OS),$(eval $(call build-openssl ,$(os))))
245+ $(foreach os,$(OS),$(eval $(call build,$(os))))
137246
138- # ##########################################################################
139- # Python
140- # ##########################################################################
247+ _framework :
248+ # Create the framework directory and set it as the current version
249+ mkdir -p $(FRAMEWORK_DIR ) /Versions/$(PYTHON_VERSION ) /
250+ cd $(FRAMEWORK_DIR ) /Versions && ln -fs $(PYTHON_VERSION ) Current
141251
142- # Clean the Python project
143- clean-Python :
144- rm -rf build/Python-$(PYTHON_VERSION )
145- rm -rf build/python
146- rm -rf dist/Python.framework
252+ # Copy the headers. The headers are the same for every platform, except for pyconfig.h;
253+ # use the x86_64 simulator build because reasons.
254+ cp -r build/ios-simulator-x86_64/include/python$(PYTHON_VERSION) $(FRAMEWORK_DIR)/Versions/$(PYTHON_VERSION)/Headers
147255
148- # Download original Python source code archive.
149- downloads/Python-$(PYTHON_VERSION ) .tgz :
150- mkdir downloads
151- 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
256+ # The only headers that change between versions is pyconfig.h; copy each supported version...
257+ cp build/ios-simulator-i386/include/python$(PYTHON_VERSION)/pyconfig.h $(FRAMEWORK_DIR)/Versions/$(PYTHON_VERSION)/Headers/pyconfig-i386.h
258+ cp build/ios-simulator-x86_64/include/python$(PYTHON_VERSION)/pyconfig.h $(FRAMEWORK_DIR)/Versions/$(PYTHON_VERSION)/Headers/pyconfig-x86_64.h
259+ # ARMv7 and ARMv7S headers are the same; don't copy this one.
260+ # cp build/ios-armv7s/include/python$(PYTHON_VERSION)/pyconfig.h $(FRAMEWORK_DIR)/Versions/$(PYTHON_VERSION)/Headers/pyconfig-armv7s.h
261+ cp build/ios-armv7/include/python$(PYTHON_VERSION)/pyconfig.h $(FRAMEWORK_DIR)/Versions/$(PYTHON_VERSION)/Headers/pyconfig-armv7.h
262+ cp build/ios-arm64/include/python$(PYTHON_VERSION)/pyconfig.h $(FRAMEWORK_DIR)/Versions/$(PYTHON_VERSION)/Headers/pyconfig-arm64.h
263+ # ... and then copy in a master pyconfig.h to unify them all.
264+ cp include/pyconfig.h $(FRAMEWORK_DIR)/Versions/$(PYTHON_VERSION)/Headers/pyconfig.h
152265
153- build/Python-$(PYTHON_VERSION ) /Makefile : downloads/Python-$(PYTHON_VERSION ) .tgz
154- # Unpack sources
155- mkdir build
156- tar zxf downloads/Python-$(PYTHON_VERSION ) .tgz -C build
157- # Apply patches
158- cd build/Python-$(PYTHON_VERSION ) && patch -p1 < ../../patch/Python/Python.patch
159- cd build/Python-$(PYTHON_VERSION ) && cp ../../patch/Python/Setup.embedded Modules/Setup.embedded
160-
161- # build/Python-$(PYTHON_VERSION)/Python.framework: dist/OpenSSL.framework build/Python-$(PYTHON_VERSION)/Makefile
162- build/Python-$(PYTHON_VERSION ) /iOS/Python.framework : build/Python-$(PYTHON_VERSION ) /Makefile
163- # Configure and make the build
164- cd build/Python-$(PYTHON_VERSION ) /iOS && make
165-
166- dist/Python.framework : build/Python-$(PYTHON_VERSION ) /Python.framework
167- mkdir dist
168- mv build/Python-$(PYTHON_VERSION ) /Python.framework dist
266+ # Link the current Headers to the top level
267+ cd $(FRAMEWORK_DIR) && ln -fs Versions/Current/Headers
268+
269+ # Copy the standard library from the simulator build. Again, the
270+ # pure Python standard library is the same on every platform;
271+ # use the simulator version because reasons.
272+ mkdir -p $(FRAMEWORK_DIR)/Versions/$(PYTHON_VERSION)/Resources
273+ cp -r build/ios-simulator-x86_64/lib $(FRAMEWORK_DIR)/Versions/$(PYTHON_VERSION)/Resources
274+
275+ # Copy Python.h and pyconfig.h into the resources include directory
276+ mkdir -p $(FRAMEWORK_DIR)/Versions/$(PYTHON_VERSION)/Resources/include/python$(PYTHON_VERSION)
277+ cp -r $(FRAMEWORK_DIR)/Versions/$(PYTHON_VERSION)/Headers/pyconfig*.h $(FRAMEWORK_DIR)/Versions/$(PYTHON_VERSION)/Resources/include/python$(PYTHON_VERSION)
278+ cp -r $(FRAMEWORK_DIR)/Versions/$(PYTHON_VERSION)/Headers/Python.h $(FRAMEWORK_DIR)/Versions/$(PYTHON_VERSION)/Resources/include/python$(PYTHON_VERSION)
279+
280+ # Remove the pieces of the resources directory that aren't needed:
281+ # libpython.a isn't needed in the lib directory
282+ rm -f $(FRAMEWORK_DIR)/Versions/$(PYTHON_VERSION)/Resources/lib/libpython$(PYTHON_VERSION).a
283+ # pkgconfig isn't needed on the device
284+ rm -rf $(FRAMEWORK_DIR)/Versions/$(PYTHON_VERSION)/Resources/lib/pkgconfig
285+
286+ ifneq ($(TEST ) ,)
287+ # Do the pruning and compression.
288+ cd $(FRAMEWORK_DIR)/Versions/$(PYTHON_VERSION)/Resources/lib/python$(PYTHON_VERSION);
289+ rm -rf *test* lib* bsddb curses ensurepip hotshot idlelib tkinter turtledemo wsgiref \
290+ config-$(PYTHON_VERSION) ctypes/test distutils/tests site-packages sqlite3/test; \
291+ find . -name "*.pyc" -exec rm -rf {} \;
292+ zip -r ../python$(subst .,,$(PYTHON_VER)).zip *;
293+ endif
294+
295+ # Link the current Resources to the top level
296+ cd $(FRAMEWORK_DIR) && ln -fs Versions/Current/Resources
297+
298+ # Create a fat binary for the libPython library
299+ cp libpython.a $(FRAMEWORK_DIR)/Versions/$(PYTHON_VERSION)/Python
300+
301+ # Link the current Python library to the top level
302+ cd $(FRAMEWORK_DIR) && ln -fs Versions/Current/Python
0 commit comments