@@ -161,6 +161,13 @@ def getFullVersion():
161161 --universal-archs=x universal architectures (options: %(UNIVERSALOPTS)r, default: %(UNIVERSALARCHS)r)
162162""" )% globals ()
163163
164+ # Dict of object file names with shared library names to check after building.
165+ # This is to ensure that we ended up dynamically linking with the shared
166+ # library paths and versions we expected. For example:
167+ # EXPECTED_SHARED_LIBS['_tkinter.so'] = [
168+ # '/Library/Frameworks/Tcl.framework/Versions/8.5/Tcl',
169+ # '/Library/Frameworks/Tk.framework/Versions/8.5/Tk']
170+ EXPECTED_SHARED_LIBS = {}
164171
165172# Instructions for building libraries that are necessary for building a
166173# batteries included python.
@@ -460,27 +467,40 @@ def checkEnvironment():
460467 # Because we only support dynamic load of only one major/minor version of
461468 # Tcl/Tk, ensure:
462469 # 1. there are no user-installed frameworks of Tcl/Tk with version
463- # higher than the Apple-supplied system version
464- # 2. there is a user-installed framework in /Library/Frameworks with the
465- # same version as the system version. This allows users to choose
466- # to install a newer patch level.
470+ # higher than the Apple-supplied system version in
471+ # SDKROOT/System/Library/Frameworks
472+ # 2. there is a user-installed framework (usually ActiveTcl) in (or linked
473+ # in) SDKROOT/Library/Frameworks with the same version as the system
474+ # version. This allows users to choose to install a newer patch level.
467475
476+ frameworks = {}
468477 for framework in ['Tcl' , 'Tk' ]:
469- #fw = dict(lower=framework.lower(),
470- # upper=framework.upper(),
471- # cap=framework.capitalize())
472- #fwpth = "Library/Frameworks/%(cap)s.framework/%(lower)sConfig.sh" % fw
473- fwpth = 'Library/Frameworks/Tcl.framework/Versions/Current'
478+ fwpth = 'Library/Frameworks/%s.framework/Versions/Current' % framework
474479 sysfw = os .path .join (SDKPATH , 'System' , fwpth )
475- libfw = os .path .join ('/' , fwpth )
480+ libfw = os .path .join (SDKPATH , fwpth )
476481 usrfw = os .path .join (os .getenv ('HOME' ), fwpth )
477- #version = "%(upper)s_VERSION" % fw
482+ frameworks [framework ] = os .readlink (sysfw )
483+ if not os .path .exists (libfw ):
484+ fatal ("Please install a link to a current %s %s as %s so "
485+ "the user can override the system framework."
486+ % (framework , frameworks [framework ], libfw ))
478487 if os .readlink (libfw ) != os .readlink (sysfw ):
479488 fatal ("Version of %s must match %s" % (libfw , sysfw ) )
480489 if os .path .exists (usrfw ):
481490 fatal ("Please rename %s to avoid possible dynamic load issues."
482491 % usrfw )
483492
493+ if frameworks ['Tcl' ] != frameworks ['Tk' ]:
494+ fatal ("The Tcl and Tk frameworks are not the same version." )
495+
496+ # add files to check after build
497+ EXPECTED_SHARED_LIBS ['_tkinter.so' ] = [
498+ "/Library/Frameworks/Tcl.framework/Versions/%s/Tcl"
499+ % frameworks ['Tcl' ],
500+ "/Library/Frameworks/Tk.framework/Versions/%s/Tk"
501+ % frameworks ['Tk' ],
502+ ]
503+
484504 # Remove inherited environment variables which might influence build
485505 environ_var_prefixes = ['CPATH' , 'C_INCLUDE_' , 'DYLD_' , 'LANG' , 'LC_' ,
486506 'LD_' , 'LIBRARY_' , 'PATH' , 'PYTHON' ]
@@ -861,12 +881,12 @@ def buildPython():
861881 frmDir = os .path .join (rootDir , 'Library' , 'Frameworks' , 'Python.framework' )
862882 gid = grp .getgrnam ('admin' ).gr_gid
863883
884+ shared_lib_error = False
864885 for dirpath , dirnames , filenames in os .walk (frmDir ):
865886 for dn in dirnames :
866887 os .chmod (os .path .join (dirpath , dn ), STAT_0o775 )
867888 os .chown (os .path .join (dirpath , dn ), - 1 , gid )
868889
869-
870890 for fn in filenames :
871891 if os .path .islink (fn ):
872892 continue
@@ -877,6 +897,19 @@ def buildPython():
877897 os .chmod (p , stat .S_IMODE (st .st_mode ) | stat .S_IWGRP )
878898 os .chown (p , - 1 , gid )
879899
900+ if fn in EXPECTED_SHARED_LIBS :
901+ # check to see that this file was linked with the
902+ # expected library path and version
903+ data = captureCommand ("otool -L %s" % shellQuote (p ))
904+ for sl in EXPECTED_SHARED_LIBS [fn ]:
905+ if ("\t %s " % sl ) not in data :
906+ print ("Expected shared lib %s was not linked with %s"
907+ % (sl , p ))
908+ shared_lib_error = True
909+
910+ if shared_lib_error :
911+ fatal ("Unexpected shared library errors." )
912+
880913 if PYTHON_3 :
881914 LDVERSION = None
882915 VERSION = None
0 commit comments