in Mac/BuildScript/build-installer.py [0:0]
def buildPython():
print("Building a universal python for %s architectures" % UNIVERSALARCHS)
buildDir = os.path.join(WORKDIR, '_bld', 'python')
rootDir = os.path.join(WORKDIR, '_root')
if os.path.exists(buildDir):
shutil.rmtree(buildDir)
if os.path.exists(rootDir):
shutil.rmtree(rootDir)
os.makedirs(buildDir)
os.makedirs(rootDir)
os.makedirs(os.path.join(rootDir, 'empty-dir'))
curdir = os.getcwd()
os.chdir(buildDir)
# Extract the version from the configure file, needed to calculate
# several paths.
version = getVersion()
# Since the extra libs are not in their installed framework location
# during the build, augment the library path so that the interpreter
# will find them during its extension import sanity checks.
print("Running configure...")
runCommand("%s -C --enable-framework --enable-universalsdk=/ "
"--with-universal-archs=%s "
"%s "
"%s "
"%s "
"%s "
"%s "
"LDFLAGS='-g -L%s/libraries/usr/local/lib' "
"CFLAGS='-g -I%s/libraries/usr/local/include' 2>&1"%(
shellQuote(os.path.join(SRCDIR, 'configure')),
UNIVERSALARCHS,
(' ', '--with-computed-gotos ')[PYTHON_3],
(' ', '--without-ensurepip ')[PYTHON_3],
(' ', "--with-openssl='%s/libraries/usr/local'"%(
shellQuote(WORKDIR)[1:-1],))[PYTHON_3],
(' ', "--with-tcltk-includes='-I%s/libraries/usr/local/include'"%(
shellQuote(WORKDIR)[1:-1],))[internalTk()],
(' ', "--with-tcltk-libs='-L%s/libraries/usr/local/lib -ltcl8.6 -ltk8.6'"%(
shellQuote(WORKDIR)[1:-1],))[internalTk()],
shellQuote(WORKDIR)[1:-1],
shellQuote(WORKDIR)[1:-1]))
# As of macOS 10.11 with SYSTEM INTEGRITY PROTECTION, DYLD_*
# environment variables are no longer automatically inherited
# by child processes from their parents. We used to just set
# DYLD_LIBRARY_PATH, pointing to the third-party libs,
# in build-installer.py's process environment and it was
# passed through the make utility into the environment of
# setup.py. Instead, we now append DYLD_LIBRARY_PATH to
# the existing RUNSHARED configuration value when we call
# make for extension module builds.
runshared_for_make = "".join([
" RUNSHARED=",
"'",
grepValue("Makefile", "RUNSHARED"),
' DYLD_LIBRARY_PATH=',
os.path.join(WORKDIR, 'libraries', 'usr', 'local', 'lib'),
"'" ])
# Look for environment value BUILDINSTALLER_BUILDPYTHON_MAKE_EXTRAS
# and, if defined, append its value to the make command. This allows
# us to pass in version control tags, like GITTAG, to a build from a
# tarball rather than from a vcs checkout, thus eliminating the need
# to have a working copy of the vcs program on the build machine.
#
# A typical use might be:
# export BUILDINSTALLER_BUILDPYTHON_MAKE_EXTRAS=" \
# GITVERSION='echo 123456789a' \
# GITTAG='echo v3.6.0' \
# GITBRANCH='echo 3.6'"
make_extras = os.getenv("BUILDINSTALLER_BUILDPYTHON_MAKE_EXTRAS")
if make_extras:
make_cmd = "make " + make_extras + runshared_for_make
else:
make_cmd = "make" + runshared_for_make
print("Running " + make_cmd)
runCommand(make_cmd)
make_cmd = "make install DESTDIR=%s %s"%(
shellQuote(rootDir),
runshared_for_make)
print("Running " + make_cmd)
runCommand(make_cmd)
make_cmd = "make frameworkinstallextras DESTDIR=%s %s"%(
shellQuote(rootDir),
runshared_for_make)
print("Running " + make_cmd)
runCommand(make_cmd)
print("Copying required shared libraries")
if os.path.exists(os.path.join(WORKDIR, 'libraries', 'Library')):
build_lib_dir = os.path.join(
WORKDIR, 'libraries', 'Library', 'Frameworks',
'Python.framework', 'Versions', getVersion(), 'lib')
fw_lib_dir = os.path.join(
WORKDIR, '_root', 'Library', 'Frameworks',
'Python.framework', 'Versions', getVersion(), 'lib')
if internalTk():
# move Tcl and Tk pkgconfig files
runCommand("mv %s/pkgconfig/* %s/pkgconfig"%(
shellQuote(build_lib_dir),
shellQuote(fw_lib_dir) ))
runCommand("rm -r %s/pkgconfig"%(
shellQuote(build_lib_dir), ))
runCommand("mv %s/* %s"%(
shellQuote(build_lib_dir),
shellQuote(fw_lib_dir) ))
frmDir = os.path.join(rootDir, 'Library', 'Frameworks', 'Python.framework')
frmDirVersioned = os.path.join(frmDir, 'Versions', version)
path_to_lib = os.path.join(frmDirVersioned, 'lib', 'python%s'%(version,))
# create directory for OpenSSL certificates
sslDir = os.path.join(frmDirVersioned, 'etc', 'openssl')
os.makedirs(sslDir)
print("Fix file modes")
gid = grp.getgrnam('admin').gr_gid
shared_lib_error = False
for dirpath, dirnames, filenames in os.walk(frmDir):
for dn in dirnames:
os.chmod(os.path.join(dirpath, dn), STAT_0o775)
os.chown(os.path.join(dirpath, dn), -1, gid)
for fn in filenames:
if os.path.islink(fn):
continue
# "chmod g+w $fn"
p = os.path.join(dirpath, fn)
st = os.stat(p)
os.chmod(p, stat.S_IMODE(st.st_mode) | stat.S_IWGRP)
os.chown(p, -1, gid)
if fn in EXPECTED_SHARED_LIBS:
# check to see that this file was linked with the
# expected library path and version
data = captureCommand("otool -L %s" % shellQuote(p))
for sl in EXPECTED_SHARED_LIBS[fn]:
if ("\t%s " % sl) not in data:
print("Expected shared lib %s was not linked with %s"
% (sl, p))
shared_lib_error = True
if shared_lib_error:
fatal("Unexpected shared library errors.")
if PYTHON_3:
LDVERSION=None
VERSION=None
ABIFLAGS=None
fp = open(os.path.join(buildDir, 'Makefile'), 'r')
for ln in fp:
if ln.startswith('VERSION='):
VERSION=ln.split()[1]
if ln.startswith('ABIFLAGS='):
ABIFLAGS=ln.split()
ABIFLAGS=ABIFLAGS[1] if len(ABIFLAGS) > 1 else ''
if ln.startswith('LDVERSION='):
LDVERSION=ln.split()[1]
fp.close()
LDVERSION = LDVERSION.replace('$(VERSION)', VERSION)
LDVERSION = LDVERSION.replace('$(ABIFLAGS)', ABIFLAGS)
config_suffix = '-' + LDVERSION
if getVersionMajorMinor() >= (3, 6):
config_suffix = config_suffix + '-darwin'
else:
config_suffix = '' # Python 2.x
# We added some directories to the search path during the configure
# phase. Remove those because those directories won't be there on
# the end-users system. Also remove the directories from _sysconfigdata.py
# (added in 3.3) if it exists.
include_path = '-I%s/libraries/usr/local/include' % (WORKDIR,)
lib_path = '-L%s/libraries/usr/local/lib' % (WORKDIR,)
# fix Makefile
path = os.path.join(path_to_lib, 'config' + config_suffix, 'Makefile')
fp = open(path, 'r')
data = fp.read()
fp.close()
for p in (include_path, lib_path):
data = data.replace(" " + p, '')
data = data.replace(p + " ", '')
fp = open(path, 'w')
fp.write(data)
fp.close()
# fix _sysconfigdata
#
# TODO: make this more robust! test_sysconfig_module of
# distutils.tests.test_sysconfig.SysconfigTestCase tests that
# the output from get_config_var in both sysconfig and
# distutils.sysconfig is exactly the same for both CFLAGS and
# LDFLAGS. The fixing up is now complicated by the pretty
# printing in _sysconfigdata.py. Also, we are using the
# pprint from the Python running the installer build which
# may not cosmetically format the same as the pprint in the Python
# being built (and which is used to originally generate
# _sysconfigdata.py).
import pprint
if getVersionMajorMinor() >= (3, 6):
# XXX this is extra-fragile
path = os.path.join(path_to_lib,
'_sysconfigdata_%s_darwin_darwin.py' % (ABIFLAGS,))
else:
path = os.path.join(path_to_lib, '_sysconfigdata.py')
fp = open(path, 'r')
data = fp.read()
fp.close()
# create build_time_vars dict
if RUNNING_ON_PYTHON2:
exec(data)
else:
g_dict = {}
l_dict = {}
exec(data, g_dict, l_dict)
build_time_vars = l_dict['build_time_vars']
vars = {}
for k, v in build_time_vars.items():
if type(v) == type(''):
for p in (include_path, lib_path):
v = v.replace(' ' + p, '')
v = v.replace(p + ' ', '')
vars[k] = v
fp = open(path, 'w')
# duplicated from sysconfig._generate_posix_vars()
fp.write('# system configuration generated and used by'
' the sysconfig module\n')
fp.write('build_time_vars = ')
pprint.pprint(vars, stream=fp)
fp.close()
# Add symlinks in /usr/local/bin, using relative links
usr_local_bin = os.path.join(rootDir, 'usr', 'local', 'bin')
to_framework = os.path.join('..', '..', '..', 'Library', 'Frameworks',
'Python.framework', 'Versions', version, 'bin')
if os.path.exists(usr_local_bin):
shutil.rmtree(usr_local_bin)
os.makedirs(usr_local_bin)
for fn in os.listdir(
os.path.join(frmDir, 'Versions', version, 'bin')):
os.symlink(os.path.join(to_framework, fn),
os.path.join(usr_local_bin, fn))
os.chdir(curdir)