Commit fbe73769 authored by Andrew M. Kuchling's avatar Andrew M. Kuchling

Sizable reorganization of how header and library files are found

Check additional include directories for SSL
Don't build modules that are linked into the Python binary statically
Factored out the detection of Tkinter out into a method, since it's
    the most complicated module to set up
Simplify the logic for detecting Tkinter
parent bc0b260a
# To be fixed: # To be fixed:
# Implement --disable-modules setting # Implement --disable-modules setting
# Don't install to site-packages, but to lib-dynload
import sys, os, string, getopt import sys, os, string, getopt
from distutils import sysconfig from distutils import sysconfig
...@@ -10,13 +9,41 @@ from distutils.command.build_ext import build_ext ...@@ -10,13 +9,41 @@ from distutils.command.build_ext import build_ext
# This global variable is used to hold the list of modules to be disabled. # This global variable is used to hold the list of modules to be disabled.
disabled_module_list = [] disabled_module_list = []
def find_file(path, filename): def find_file(filename, std_dirs, paths):
for p in path: """Searches for the directory where a given file is located,
fullpath = p + os.sep + filename and returns a possibly-empty list of additional directories, or None
if os.path.exists(fullpath): if the file couldn't be found at all.
return fullpath
'filename' is the name of a file, such as readline.h or libcrypto.a.
'std_dirs' is the list of standard system directories; if the
file is found in one of them, no additional directives are needed.
'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.
"""
# Check the standard locations
for dir in std_dirs:
f = os.path.join(dir, filename)
if os.path.exists(f): return []
# Check the additional directories
for dir in paths:
f = os.path.join(dir, filename)
if os.path.exists(f):
return [dir]
# Not found anywhere
return None return None
def find_library_file(compiler, libname, std_dirs, paths):
filename = compiler.library_filename(libname, lib_type='shared')
result = find_file(filename, std_dirs, paths)
if result is not None: return result
filename = compiler.library_filename(libname, lib_type='static')
result = find_file(filename, std_dirs, paths)
return result
def module_enabled(extlist, modname): def module_enabled(extlist, modname):
"""Returns whether the module 'modname' is present in the list """Returns whether the module 'modname' is present in the list
of extensions 'extlist'.""" of extensions 'extlist'."""
...@@ -47,20 +74,34 @@ class PyBuildExt(build_ext): ...@@ -47,20 +74,34 @@ class PyBuildExt(build_ext):
srcdir = os.path.normpath(srcdir) srcdir = os.path.normpath(srcdir)
moddir = os.path.normpath(moddir) moddir = os.path.normpath(moddir)
for ext in self.extensions: for ext in self.extensions[:]:
ext.sources = [ os.path.join(moddir, filename) ext.sources = [ os.path.join(moddir, filename)
for filename in ext.sources ] for filename in ext.sources ]
ext.include_dirs.append( '.' ) # to get config.h ext.include_dirs.append( '.' ) # to get config.h
ext.include_dirs.append( os.path.join(srcdir, './Include') )
# Try importing a module; if it's already been built statically,
# don't build it here
try:
__import__(ext.name)
except ImportError:
pass # Not built, so this is what we expect
else:
self.extensions.remove(ext)
build_ext.build_extensions(self) build_ext.build_extensions(self)
def detect_modules(self): def detect_modules(self):
# XXX this always gets an empty list -- hardwiring to # Ensure that /usr/local is always used
# a fixed list if '/usr/local/lib' not in self.compiler.library_dirs:
lib_dirs = self.compiler.library_dirs[:] self.compiler.library_dirs.append('/usr/local/lib')
lib_dirs += ['/lib', '/usr/lib', '/usr/local/lib'] if '/usr/local/include' not in self.compiler.include_dirs:
inc_dirs = ['/usr/include', '/usr/local/include'] + self.include_dirs self.compiler.include_dirs.append( '/usr/local/include' )
# lib_dirs and inc_dirs are used to search for files;
# if a file is found in one of those directories, it can
# be assumed that no additional -I,-L directives are needed.
lib_dirs = self.compiler.library_dirs + ['/lib', '/usr/lib']
inc_dirs = ['/usr/include'] + self.compiler.include_dirs
exts = [] exts = []
# XXX Omitted modules: gl, pure, dl, SGI-specific modules # XXX Omitted modules: gl, pure, dl, SGI-specific modules
...@@ -180,9 +221,17 @@ class PyBuildExt(build_ext): ...@@ -180,9 +221,17 @@ class PyBuildExt(build_ext):
# socket(2) # socket(2)
# Detect SSL support for the socket module # Detect SSL support for the socket module
if (self.compiler.find_library_file(lib_dirs, 'ssl') and ssl_incs = find_file('openssl/ssl.h', inc_dirs,
self.compiler.find_library_file(lib_dirs, 'crypto') ): ['/usr/local/ssl/include']
)
ssl_libs = find_library_file(self.compiler, 'ssl',lib_dirs,
['/usr/local/ssl/lib'] )
if (ssl_incs is not None and
ssl_libs is not None):
exts.append( Extension('_socket', ['socketmodule.c'], exts.append( Extension('_socket', ['socketmodule.c'],
include_dirs = ssl_incs,
library_dirs = ssl_libs,
libraries = ['ssl', 'crypto'], libraries = ['ssl', 'crypto'],
define_macros = [('USE_SSL',1)] ) ) define_macros = [('USE_SSL',1)] ) )
else: else:
...@@ -223,9 +272,11 @@ class PyBuildExt(build_ext): ...@@ -223,9 +272,11 @@ class PyBuildExt(build_ext):
# if it is not automatically enabled there; check the generated # if it is not automatically enabled there; check the generated
# Setup.config before enabling it here. # Setup.config before enabling it here.
if (self.compiler.find_library_file(lib_dirs, 'db') and db_incs = find_file('db_185.h', inc_dirs, [])
find_file(inc_dirs, 'db_185.h') ): if (db_incs is not None and
self.compiler.find_library_file(lib_dirs, 'db') ):
exts.append( Extension('bsddb', ['bsddbmodule.c'], exts.append( Extension('bsddb', ['bsddbmodule.c'],
include_dirs = db_incs,
libraries = ['db'] ) ) libraries = ['db'] ) )
# The mpz module interfaces to the GNU Multiple Precision library. # The mpz module interfaces to the GNU Multiple Precision library.
...@@ -293,7 +344,7 @@ class PyBuildExt(build_ext): ...@@ -293,7 +344,7 @@ class PyBuildExt(build_ext):
# For SGI IRIX (tested on 5.3): # For SGI IRIX (tested on 5.3):
exts.append( Extension('fpectl', ['fpectlmodule.c'], exts.append( Extension('fpectl', ['fpectlmodule.c'],
libraries=['fpe']) ) libraries=['fpe']) )
elif 0: # XXX elif 0: # XXX how to detect SunPro?
# For Solaris with SunPro compiler (tested on Solaris 2.5 with SunPro C 4.2): # For Solaris with SunPro compiler (tested on Solaris 2.5 with SunPro C 4.2):
# (Without the compiler you don't have -lsunmath.) # (Without the compiler you don't have -lsunmath.)
#fpectl fpectlmodule.c -R/opt/SUNWspro/lib -lsunmath -lm #fpectl fpectlmodule.c -R/opt/SUNWspro/lib -lsunmath -lm
...@@ -330,15 +381,18 @@ class PyBuildExt(build_ext): ...@@ -330,15 +381,18 @@ class PyBuildExt(build_ext):
# #
# ar cr libexpat.a xmltok/*.o xmlparse/*.o # ar cr libexpat.a xmltok/*.o xmlparse/*.o
# #
if (self.compiler.find_library_file(lib_dirs, 'expat')): expat_defs = []
defs = None expat_incs = find_file('expat.h', inc_dirs, [])
if find_file(inc_dirs, 'expat.h'): if expat_incs is not None:
defs = [('HAVE_EXPAT_H', 1)] # expat.h was found
elif find_file(inc_dirs, 'xmlparse.h'): expat_defs = [('HAVE_EXPAT_H', 1)]
defs = [] else:
if defs is not None: expat_incs = find_file('xmlparse.h', inc_dirs, [])
if (expat_incs and
self.compiler.find_library_file(lib_dirs, 'expat')):
exts.append( Extension('pyexpat', ['pyexpat.c'], exts.append( Extension('pyexpat', ['pyexpat.c'],
define_macros = defs, define_macros = expat_defs,
libraries = ['expat']) ) libraries = ['expat']) )
# Platform-specific libraries # Platform-specific libraries
...@@ -351,6 +405,13 @@ class PyBuildExt(build_ext): ...@@ -351,6 +405,13 @@ class PyBuildExt(build_ext):
# SunOS specific modules # SunOS specific modules
exts.append( Extension('sunaudiodev', ['sunaudiodev.c']) ) exts.append( Extension('sunaudiodev', ['sunaudiodev.c']) )
self.extensions.extend(exts)
# Call the method for detecting whether _tkinter can be compiled
self.detect_tkinter(inc_dirs, lib_dirs)
def detect_tkinter(self, inc_dirs, lib_dirs):
# The _tkinter module. # The _tkinter module.
# #
# The command for _tkinter is long and site specific. Please # The command for _tkinter is long and site specific. Please
...@@ -362,6 +423,8 @@ class PyBuildExt(build_ext): ...@@ -362,6 +423,8 @@ class PyBuildExt(build_ext):
# done by the shell's "read" command and it may not be implemented on # done by the shell's "read" command and it may not be implemented on
# every system. # every system.
# Assume we haven't found any of the libraries or include files
tcllib = tklib = tcl_includes = tk_includes = None
for version in ['8.4', '8.3', '8.2', '8.1', '8.0']: for version in ['8.4', '8.3', '8.2', '8.1', '8.0']:
tklib = self.compiler.find_library_file(lib_dirs, tklib = self.compiler.find_library_file(lib_dirs,
'tk' + version ) 'tk' + version )
...@@ -371,30 +434,30 @@ class PyBuildExt(build_ext): ...@@ -371,30 +434,30 @@ class PyBuildExt(build_ext):
# Exit the loop when we've found the Tcl/Tk libraries # Exit the loop when we've found the Tcl/Tk libraries
break break
if (tcllib and tklib): # Now check for the header files
include_dirs = [] ; libs = [] ; defs = [] ; added_lib_dirs = [] if tklib and tcllib:
# Check for the include files on Debian, where
# they're put in /usr/include/{tcl,tk}X.Y
debian_tcl_include = ( '/usr/include/tcl' + version )
debian_tk_include = ( '/usr/include/tk' + version )
tcl_includes = find_file('tcl.h', inc_dirs,
[debian_tcl_include]
)
tk_includes = find_file('tk.h', inc_dirs,
[debian_tk_include]
)
# Determine the prefix where Tcl/Tk is installed by if (tcllib is None or tklib is None and
# chopping off the 'lib' suffix. tcl_includes is None or tk_includes is None):
prefix = os.path.dirname(tcllib) # Something's missing, so give up
L = string.split(prefix, os.sep) return
if L[-1] == 'lib': del L[-1]
prefix = string.join(L, os.sep)
if prefix + os.sep + 'lib' not in lib_dirs: # OK... everything seems to be present for Tcl/Tk.
added_lib_dirs.append( prefix + os.sep + 'lib')
# Check for the include files on Debian, where include_dirs = [] ; libs = [] ; defs = [] ; added_lib_dirs = []
# they're put in /usr/include/{tcl,tk}X.Y for dir in tcl_includes + tk_includes:
debian_tcl_include = ( prefix + os.sep + 'include/tcl' + if dir not in include_dirs:
version ) include_dirs.append(dir)
debian_tk_include = ( prefix + os.sep + 'include/tk' +
version )
if os.path.exists(debian_tcl_include):
include_dirs = [debian_tcl_include, debian_tk_include]
else:
# Fallback for non-Debian systems
include_dirs = [prefix + os.sep + 'include']
# Check for various platform-specific directories # Check for various platform-specific directories
if sys.platform == 'sunos5': if sys.platform == 'sunos5':
...@@ -407,39 +470,39 @@ class PyBuildExt(build_ext): ...@@ -407,39 +470,39 @@ class PyBuildExt(build_ext):
include_dirs.append('/usr/X11R5/include') include_dirs.append('/usr/X11R5/include')
added_lib_dirs.append('/usr/X11R5/lib') added_lib_dirs.append('/usr/X11R5/lib')
else: else:
# Assume default form # Assume default location for X11
include_dirs.append('/usr/X11/include') include_dirs.append('/usr/X11/include')
added_lib_dirs.append('/usr/X11/lib') added_lib_dirs.append('/usr/X11/lib')
# Check for Tix extension
if self.compiler.find_library_file(lib_dirs + added_lib_dirs, 'tix4.1.8.0'): if self.compiler.find_library_file(lib_dirs + added_lib_dirs, 'tix4.1.8.0'):
defs.append( ('WITH_TIX', 1) ) defs.append( ('WITH_TIX', 1) )
libs.append('tix4.1.8.0') libs.append('tix4.1.8.0')
# Check for BLT extension
if self.compiler.find_library_file(lib_dirs + added_lib_dirs, 'BLT8.0'): if self.compiler.find_library_file(lib_dirs + added_lib_dirs, 'BLT8.0'):
defs.append( ('WITH_BLT', 1) ) defs.append( ('WITH_BLT', 1) )
libs.append('BLT8.0') libs.append('BLT8.0')
# Add the Tcl/Tk libraries
libs.append('tk'+version)
libs.append('tcl'+version)
if sys.platform in ['aix3', 'aix4']: if sys.platform in ['aix3', 'aix4']:
libs.append('ld') libs.append('ld')
# X11 libraries to link with: # Finally, link with the X11 libraries
libs.append('X11') libs.append('X11')
tklib, ext = os.path.splitext(tklib) ext = Extension('_tkinter', ['_tkinter.c', 'tkappinit.c'],
tcllib, ext = os.path.splitext(tcllib)
tklib = os.path.basename(tklib)
tcllib = os.path.basename(tcllib)
libs.append( tklib[3:] ) # Chop off 'lib' prefix
libs.append( tcllib[3:] )
exts.append( Extension('_tkinter', ['_tkinter.c', 'tkappinit.c'],
define_macros=[('WITH_APPINIT', 1)] + defs, define_macros=[('WITH_APPINIT', 1)] + defs,
include_dirs = include_dirs, include_dirs = include_dirs,
libraries = libs, libraries = libs,
library_dirs = added_lib_dirs, library_dirs = added_lib_dirs,
) )
) self.extensions.append(ext)
# XXX handle these
# XXX handle these, but how to detect?
# *** Uncomment and edit for PIL (TkImaging) extension only: # *** Uncomment and edit for PIL (TkImaging) extension only:
# -DWITH_PIL -I../Extensions/Imaging/libImaging tkImaging.c \ # -DWITH_PIL -I../Extensions/Imaging/libImaging tkImaging.c \
# *** Uncomment and edit for TOGL extension only: # *** Uncomment and edit for TOGL extension only:
...@@ -447,8 +510,6 @@ class PyBuildExt(build_ext): ...@@ -447,8 +510,6 @@ class PyBuildExt(build_ext):
# *** Uncomment these for TOGL extension only: # *** Uncomment these for TOGL extension only:
# -lGL -lGLU -lXext -lXmu \ # -lGL -lGLU -lXext -lXmu \
self.extensions.extend(exts)
def main(): def main():
setup(name = 'Python standard library', setup(name = 'Python standard library',
version = '%d.%d' % sys.version_info[:2], version = '%d.%d' % sys.version_info[:2],
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment