Fix for issue #7724: make it possible to build using

the OSX 10.4u SDK on MacOSX 10.6 by honoring the specified
SDK when looking for files.
This commit is contained in:
Ronald Oussoren 2010-05-08 08:44:37 +00:00
parent 22ff664ff7
commit d875d3c36e
3 changed files with 133 additions and 22 deletions

View File

@ -15,7 +15,7 @@ the "typical" Unix-style command-line C compiler:
__revision__ = "$Id$" __revision__ = "$Id$"
import os, sys import os, sys, re
from types import StringType, NoneType from types import StringType, NoneType
from distutils import sysconfig from distutils import sysconfig
@ -305,10 +305,29 @@ class UnixCCompiler(CCompiler):
dylib_f = self.library_filename(lib, lib_type='dylib') dylib_f = self.library_filename(lib, lib_type='dylib')
static_f = self.library_filename(lib, lib_type='static') static_f = self.library_filename(lib, lib_type='static')
if sys.platform == 'darwin':
# On OSX users can specify an alternate SDK using
# '-isysroot', calculate the SDK root if it is specified
# (and use it further on)
cflags = sysconfig.get_config_var('CFLAGS')
m = re.search(r'-isysroot\s+(\S+)', cflags)
if m is None:
sysroot = '/'
else:
sysroot = m.group(1)
for dir in dirs: for dir in dirs:
shared = os.path.join(dir, shared_f) shared = os.path.join(dir, shared_f)
dylib = os.path.join(dir, dylib_f) dylib = os.path.join(dir, dylib_f)
static = os.path.join(dir, static_f) static = os.path.join(dir, static_f)
if sys.platform == 'darwin' and (dir.startswith('/System/') or dir.startswith('/usr/')):
shared = os.path.join(sysroot, dir[1:], shared_f)
dylib = os.path.join(sysroot, dir[1:], dylib_f)
static = os.path.join(sysroot, dir[1:], static_f)
# We're second-guessing the linker here, with not much hard # We're second-guessing the linker here, with not much hard
# data to go on: GCC seems to prefer the shared library, so I'm # data to go on: GCC seems to prefer the shared library, so I'm
# assuming that *all* Unix C compilers do. And of course I'm # assuming that *all* Unix C compilers do. And of course I'm

View File

@ -212,6 +212,9 @@ Build
- Issue #3646: It is now easily possible to install a Python framework into - Issue #3646: It is now easily possible to install a Python framework into
your home directory on MacOSX, see Mac/README for more information. your home directory on MacOSX, see Mac/README for more information.
- Issue #7724: Building now full honors an MacOSX SDK when specified, which
makes it possible do a working build with the OSX 10.4 SDK on MacOSX 10.6.
Misc Misc
---- ----

109
setup.py
View File

@ -29,6 +29,27 @@ def add_dir_to_list(dirlist, dir):
if dir is not None and os.path.isdir(dir) and dir not in dirlist: if dir is not None and os.path.isdir(dir) and dir not in dirlist:
dirlist.insert(0, dir) dirlist.insert(0, dir)
def macosx_sdk_root():
"""
Return the directory of the current OSX SDK,
or '/' if no SDK was specified.
"""
cflags = sysconfig.get_config_var('CFLAGS')
m = re.search(r'-isysroot\s+(\S+)', cflags)
if m is None:
sysroot = '/'
else:
sysroot = m.group(1)
return sysroot
def is_macosx_sdk_path(path):
"""
Returns True if 'path' can be located in an OSX SDK
"""
return path.startswith('/usr/') or path.startswith('/System/')
def find_file(filename, std_dirs, paths): def find_file(filename, std_dirs, paths):
"""Searches for the directory where a given file is located, """Searches for the directory where a given file is located,
and returns a possibly-empty list of additional directories, or None and returns a possibly-empty list of additional directories, or None
@ -40,15 +61,28 @@ def find_file(filename, std_dirs, paths):
'paths' is a list of additional locations to check; if the file is 'paths' is a list of additional locations to check; if the file is
found in one of them, the resulting list will contain the directory. found in one of them, the resulting list will contain the directory.
""" """
if sys.platform == 'darwin':
# Honor the MacOSX SDK setting when one was specified.
# An SDK is a directory with the same structure as a real
# system, but with only header files and libraries.
sysroot = macosx_sdk_root()
# Check the standard locations # Check the standard locations
for dir in std_dirs: for dir in std_dirs:
f = os.path.join(dir, filename) f = os.path.join(dir, filename)
if sys.platform == 'darwin' and is_macosx_sdk_path(dir):
f = os.path.join(sysroot, dir[1:], filename)
if os.path.exists(f): return [] if os.path.exists(f): return []
# Check the additional directories # Check the additional directories
for dir in paths: for dir in paths:
f = os.path.join(dir, filename) f = os.path.join(dir, filename)
if sys.platform == 'darwin' and dir.startswith('/System') or dir.startswith('/usr'):
f = os.path.join(sysroot, dir[1:], filename)
if os.path.exists(f): if os.path.exists(f):
return [dir] return [dir]
@ -60,11 +94,19 @@ def find_library_file(compiler, libname, std_dirs, paths):
if result is None: if result is None:
return None return None
if sys.platform == 'darwin':
sysroot = macosx_sdk_root()
# Check whether the found file is in one of the standard directories # Check whether the found file is in one of the standard directories
dirname = os.path.dirname(result) dirname = os.path.dirname(result)
for p in std_dirs: for p in std_dirs:
# Ensure path doesn't end with path separator # Ensure path doesn't end with path separator
p = p.rstrip(os.sep) p = p.rstrip(os.sep)
if sys.platform == 'darwin' and is_macosx_sdk_path(p):
if os.path.join(sysroot, p[1:]) == dirname:
return [ ]
if p == dirname: if p == dirname:
return [ ] return [ ]
@ -73,6 +115,11 @@ def find_library_file(compiler, libname, std_dirs, paths):
for p in paths: for p in paths:
# Ensure path doesn't end with path separator # Ensure path doesn't end with path separator
p = p.rstrip(os.sep) p = p.rstrip(os.sep)
if sys.platform == 'darwin' and is_macosx_sdk_path(p):
if os.path.join(sysroot, p[1:]) == dirname:
return [ p ]
if p == dirname: if p == dirname:
return [p] return [p]
else: else:
@ -560,7 +607,7 @@ class PyBuildExt(build_ext):
# library and then a static library, instead of first looking # library and then a static library, instead of first looking
# for dynamic libraries on the entiry path. # for dynamic libraries on the entiry path.
# This way a staticly linked custom readline gets picked up # This way a staticly linked custom readline gets picked up
# before the (broken) dynamic library in /usr/lib. # before the (possibly broken) dynamic library in /usr/lib.
readline_extra_link_args = ('-Wl,-search_paths_first',) readline_extra_link_args = ('-Wl,-search_paths_first',)
else: else:
readline_extra_link_args = () readline_extra_link_args = ()
@ -631,24 +678,20 @@ class PyBuildExt(build_ext):
openssl_ver = 0 openssl_ver = 0
openssl_ver_re = re.compile( openssl_ver_re = re.compile(
'^\s*#\s*define\s+OPENSSL_VERSION_NUMBER\s+(0x[0-9a-fA-F]+)' ) '^\s*#\s*define\s+OPENSSL_VERSION_NUMBER\s+(0x[0-9a-fA-F]+)' )
for ssl_inc_dir in inc_dirs + search_for_ssl_incs_in:
name = os.path.join(ssl_inc_dir, 'openssl', 'opensslv.h') # look for the openssl version header on the compiler search path.
if os.path.isfile(name): opensslv_h = find_file('openssl/opensslv.h', inc_dirs, search_for_ssl_incs_in)
if opensslv_h:
name = opensslv_h[0]
try: try:
incfile = open(name, 'r') incfile = open(name, 'r')
for line in incfile: for line in incfile:
m = openssl_ver_re.match(line) m = openssl_ver_re.match(line)
if m: if m:
openssl_ver = eval(m.group(1)) openssl_ver = eval(m.group(1))
break
except IOError: except IOError:
pass pass
# first version found is what we'll use (as the compiler should)
if openssl_ver:
break
#print 'openssl_ver = 0x%08x' % openssl_ver
min_openssl_ver = 0x00907000 min_openssl_ver = 0x00907000
have_any_openssl = ssl_incs is not None and ssl_libs is not None have_any_openssl = ssl_incs is not None and ssl_libs is not None
have_usable_openssl = (have_any_openssl and have_usable_openssl = (have_any_openssl and
@ -781,12 +824,19 @@ class PyBuildExt(build_ext):
db_ver_inc_map = {} db_ver_inc_map = {}
if sys.platform == 'darwin':
sysroot = macosx_sdk_root()
class db_found(Exception): pass class db_found(Exception): pass
try: try:
# See whether there is a Sleepycat header in the standard # See whether there is a Sleepycat header in the standard
# search path. # search path.
for d in inc_dirs + db_inc_paths: for d in inc_dirs + db_inc_paths:
f = os.path.join(d, "db.h") f = os.path.join(d, "db.h")
if sys.platform == 'darwin' and is_macosx_sdk_path(d):
f = os.path.join(sysroot, d[1:], "db.h")
if db_setup_debug: print "db: looking for db.h in", f if db_setup_debug: print "db: looking for db.h in", f
if os.path.exists(f): if os.path.exists(f):
f = open(f).read() f = open(f).read()
@ -833,8 +883,21 @@ class PyBuildExt(build_ext):
db_incdir.replace("include", 'lib64'), db_incdir.replace("include", 'lib64'),
db_incdir.replace("include", 'lib'), db_incdir.replace("include", 'lib'),
] ]
if sys.platform != 'darwin':
db_dirs_to_check = filter(os.path.isdir, db_dirs_to_check) db_dirs_to_check = filter(os.path.isdir, db_dirs_to_check)
else:
# Same as other branch, but takes OSX SDK into account
tmp = []
for dn in db_dirs_to_check:
if is_macosx_sdk_path(dn):
if os.path.isdir(os.path.join(sysroot, dn[1:])):
tmp.append(dn)
else:
if os.path.isdir(dn):
tmp.append(dn)
# Look for a version specific db-X.Y before an ambiguoius dbX # Look for a version specific db-X.Y before an ambiguoius dbX
# XXX should we -ever- look for a dbX name? Do any # XXX should we -ever- look for a dbX name? Do any
# systems really not name their library by version and # systems really not name their library by version and
@ -895,8 +958,15 @@ class PyBuildExt(build_ext):
# Scan the default include directories before the SQLite specific # Scan the default include directories before the SQLite specific
# ones. This allows one to override the copy of sqlite on OSX, # ones. This allows one to override the copy of sqlite on OSX,
# where /usr/include contains an old version of sqlite. # where /usr/include contains an old version of sqlite.
if sys.platform == 'darwin':
sysroot = macosx_sdk_root()
for d in inc_dirs + sqlite_inc_paths: for d in inc_dirs + sqlite_inc_paths:
f = os.path.join(d, "sqlite3.h") f = os.path.join(d, "sqlite3.h")
if sys.platform == 'darwin' and is_macosx_sdk_path(d):
f = os.path.join(sysroot, d[1:], "sqlite3.h")
if os.path.exists(f): if os.path.exists(f):
if sqlite_setup_debug: print "sqlite: found %s"%f if sqlite_setup_debug: print "sqlite: found %s"%f
incf = open(f).read() incf = open(f).read()
@ -984,6 +1054,12 @@ class PyBuildExt(build_ext):
# the more recent berkeleydb's db.h file first in the include path # the more recent berkeleydb's db.h file first in the include path
# when attempting to compile and it will fail. # when attempting to compile and it will fail.
f = "/usr/include/db.h" f = "/usr/include/db.h"
if sys.platform == 'darwin':
if is_macosx_sdk_path(f):
sysroot = macosx_sdk_root()
f = os.path.join(sysroot, f[1:])
if os.path.exists(f) and not db_incs: if os.path.exists(f) and not db_incs:
data = open(f).read() data = open(f).read()
m = re.search(r"#s*define\s+HASHVERSION\s+2\s*", data) m = re.search(r"#s*define\s+HASHVERSION\s+2\s*", data)
@ -1490,12 +1566,20 @@ class PyBuildExt(build_ext):
join(os.getenv('HOME'), '/Library/Frameworks') join(os.getenv('HOME'), '/Library/Frameworks')
] ]
sysroot = macosx_sdk_root()
# Find the directory that contains the Tcl.framework and Tk.framework # Find the directory that contains the Tcl.framework and Tk.framework
# bundles. # bundles.
# XXX distutils should support -F! # XXX distutils should support -F!
for F in framework_dirs: for F in framework_dirs:
# both Tcl.framework and Tk.framework should be present # both Tcl.framework and Tk.framework should be present
for fw in 'Tcl', 'Tk': for fw in 'Tcl', 'Tk':
if is_macosx_sdk_path(F):
if not exists(join(sysroot, F[1:], fw + '.framework')):
break
else:
if not exists(join(F, fw + '.framework')): if not exists(join(F, fw + '.framework')):
break break
else: else:
@ -1527,7 +1611,12 @@ class PyBuildExt(build_ext):
# architectures. # architectures.
cflags = sysconfig.get_config_vars('CFLAGS')[0] cflags = sysconfig.get_config_vars('CFLAGS')[0]
archs = re.findall('-arch\s+(\w+)', cflags) archs = re.findall('-arch\s+(\w+)', cflags)
if is_macosx_sdk_path(F):
fp = os.popen("file %s/Tk.framework/Tk | grep 'for architecture'"%(os.path.join(sysroot, F[1:]),))
else:
fp = os.popen("file %s/Tk.framework/Tk | grep 'for architecture'"%(F,)) fp = os.popen("file %s/Tk.framework/Tk | grep 'for architecture'"%(F,))
detected_archs = [] detected_archs = []
for ln in fp: for ln in fp:
a = ln.split()[-1] a = ln.split()[-1]