setup.py revision 37471dc6f9911b0f36aafdf4c130ce608e0443d1
1# Autodetecting setup.py script for building the Python extensions
2#
3
4__version__ = "$Revision$"
5
6import sys, os, imp, re, optparse
7from glob import glob
8from platform import machine as platform_machine
9import sysconfig
10
11from distutils import log
12from distutils import text_file
13from distutils.errors import *
14from distutils.core import Extension, setup
15from distutils.command.build_ext import build_ext
16from distutils.command.install import install
17from distutils.command.install_lib import install_lib
18from distutils.spawn import find_executable
19
20cross_compiling = "_PYTHON_HOST_PLATFORM" in os.environ
21
22def get_platform():
23    # cross build
24    if "_PYTHON_HOST_PLATFORM" in os.environ:
25        return os.environ["_PYTHON_HOST_PLATFORM"]
26    # Get value of sys.platform
27    if sys.platform.startswith('osf1'):
28        return 'osf1'
29    return sys.platform
30host_platform = get_platform()
31
32# Were we compiled --with-pydebug or with #define Py_DEBUG?
33COMPILED_WITH_PYDEBUG = ('--with-pydebug' in sysconfig.get_config_var("CONFIG_ARGS"))
34
35# This global variable is used to hold the list of modules to be disabled.
36disabled_module_list = []
37
38def add_dir_to_list(dirlist, dir):
39    """Add the directory 'dir' to the list 'dirlist' (at the front) if
40    1) 'dir' is not already in 'dirlist'
41    2) 'dir' actually exists, and is a directory."""
42    if dir is not None and os.path.isdir(dir) and dir not in dirlist:
43        dirlist.insert(0, dir)
44
45def macosx_sdk_root():
46    """
47    Return the directory of the current OSX SDK,
48    or '/' if no SDK was specified.
49    """
50    cflags = sysconfig.get_config_var('CFLAGS')
51    m = re.search(r'-isysroot\s+(\S+)', cflags)
52    if m is None:
53        sysroot = '/'
54    else:
55        sysroot = m.group(1)
56    return sysroot
57
58def is_macosx_sdk_path(path):
59    """
60    Returns True if 'path' can be located in an OSX SDK
61    """
62    return ( (path.startswith('/usr/') and not path.startswith('/usr/local'))
63                or path.startswith('/System/')
64                or path.startswith('/Library/') )
65
66def find_file(filename, std_dirs, paths):
67    """Searches for the directory where a given file is located,
68    and returns a possibly-empty list of additional directories, or None
69    if the file couldn't be found at all.
70
71    'filename' is the name of a file, such as readline.h or libcrypto.a.
72    'std_dirs' is the list of standard system directories; if the
73        file is found in one of them, no additional directives are needed.
74    'paths' is a list of additional locations to check; if the file is
75        found in one of them, the resulting list will contain the directory.
76    """
77    if host_platform == 'darwin':
78        # Honor the MacOSX SDK setting when one was specified.
79        # An SDK is a directory with the same structure as a real
80        # system, but with only header files and libraries.
81        sysroot = macosx_sdk_root()
82
83    # Check the standard locations
84    for dir in std_dirs:
85        f = os.path.join(dir, filename)
86
87        if host_platform == 'darwin' and is_macosx_sdk_path(dir):
88            f = os.path.join(sysroot, dir[1:], filename)
89
90        if os.path.exists(f): return []
91
92    # Check the additional directories
93    for dir in paths:
94        f = os.path.join(dir, filename)
95
96        if host_platform == 'darwin' and is_macosx_sdk_path(dir):
97            f = os.path.join(sysroot, dir[1:], filename)
98
99        if os.path.exists(f):
100            return [dir]
101
102    # Not found anywhere
103    return None
104
105def find_library_file(compiler, libname, std_dirs, paths):
106    result = compiler.find_library_file(std_dirs + paths, libname)
107    if result is None:
108        return None
109
110    if host_platform == 'darwin':
111        sysroot = macosx_sdk_root()
112
113    # Check whether the found file is in one of the standard directories
114    dirname = os.path.dirname(result)
115    for p in std_dirs:
116        # Ensure path doesn't end with path separator
117        p = p.rstrip(os.sep)
118
119        if host_platform == 'darwin' and is_macosx_sdk_path(p):
120            # Note that, as of Xcode 7, Apple SDKs may contain textual stub
121            # libraries with .tbd extensions rather than the normal .dylib
122            # shared libraries installed in /.  The Apple compiler tool
123            # chain handles this transparently but it can cause problems
124            # for programs that are being built with an SDK and searching
125            # for specific libraries.  Distutils find_library_file() now
126            # knows to also search for and return .tbd files.  But callers
127            # of find_library_file need to keep in mind that the base filename
128            # of the returned SDK library file might have a different extension
129            # from that of the library file installed on the running system,
130            # for example:
131            #   /Applications/Xcode.app/Contents/Developer/Platforms/
132            #       MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/
133            #       usr/lib/libedit.tbd
134            # vs
135            #   /usr/lib/libedit.dylib
136            if os.path.join(sysroot, p[1:]) == dirname:
137                return [ ]
138
139        if p == dirname:
140            return [ ]
141
142    # Otherwise, it must have been in one of the additional directories,
143    # so we have to figure out which one.
144    for p in paths:
145        # Ensure path doesn't end with path separator
146        p = p.rstrip(os.sep)
147
148        if host_platform == 'darwin' and is_macosx_sdk_path(p):
149            if os.path.join(sysroot, p[1:]) == dirname:
150                return [ p ]
151
152        if p == dirname:
153            return [p]
154    else:
155        assert False, "Internal error: Path not found in std_dirs or paths"
156
157def module_enabled(extlist, modname):
158    """Returns whether the module 'modname' is present in the list
159    of extensions 'extlist'."""
160    extlist = [ext for ext in extlist if ext.name == modname]
161    return len(extlist)
162
163def find_module_file(module, dirlist):
164    """Find a module in a set of possible folders. If it is not found
165    return the unadorned filename"""
166    list = find_file(module, [], dirlist)
167    if not list:
168        return module
169    if len(list) > 1:
170        log.info("WARNING: multiple copies of %s found"%module)
171    return os.path.join(list[0], module)
172
173class PyBuildExt(build_ext):
174
175    def __init__(self, dist):
176        build_ext.__init__(self, dist)
177        self.failed = []
178
179    def build_extensions(self):
180
181        # Detect which modules should be compiled
182        missing = self.detect_modules()
183
184        # Remove modules that are present on the disabled list
185        extensions = [ext for ext in self.extensions
186                      if ext.name not in disabled_module_list]
187        # move ctypes to the end, it depends on other modules
188        ext_map = dict((ext.name, i) for i, ext in enumerate(extensions))
189        if "_ctypes" in ext_map:
190            ctypes = extensions.pop(ext_map["_ctypes"])
191            extensions.append(ctypes)
192        self.extensions = extensions
193
194        # Fix up the autodetected modules, prefixing all the source files
195        # with Modules/ and adding Python's include directory to the path.
196        (srcdir,) = sysconfig.get_config_vars('srcdir')
197        if not srcdir:
198            # Maybe running on Windows but not using CYGWIN?
199            raise ValueError("No source directory; cannot proceed.")
200        srcdir = os.path.abspath(srcdir)
201        moddirlist = [os.path.join(srcdir, 'Modules')]
202
203        # Platform-dependent module source and include directories
204        incdirlist = []
205
206        if host_platform == 'darwin' and ("--disable-toolbox-glue" not in
207            sysconfig.get_config_var("CONFIG_ARGS")):
208            # Mac OS X also includes some mac-specific modules
209            macmoddir = os.path.join(srcdir, 'Mac/Modules')
210            moddirlist.append(macmoddir)
211            incdirlist.append(os.path.join(srcdir, 'Mac/Include'))
212
213        # Fix up the paths for scripts, too
214        self.distribution.scripts = [os.path.join(srcdir, filename)
215                                     for filename in self.distribution.scripts]
216
217        # Python header files
218        headers = [sysconfig.get_config_h_filename()]
219        headers += glob(os.path.join(sysconfig.get_path('include'), "*.h"))
220        for ext in self.extensions[:]:
221            ext.sources = [ find_module_file(filename, moddirlist)
222                            for filename in ext.sources ]
223            if ext.depends is not None:
224                ext.depends = [find_module_file(filename, moddirlist)
225                               for filename in ext.depends]
226            else:
227                ext.depends = []
228            # re-compile extensions if a header file has been changed
229            ext.depends.extend(headers)
230
231            # platform specific include directories
232            ext.include_dirs.extend(incdirlist)
233
234            # If a module has already been built statically,
235            # don't build it here
236            if ext.name in sys.builtin_module_names:
237                self.extensions.remove(ext)
238
239        # Parse Modules/Setup and Modules/Setup.local to figure out which
240        # modules are turned on in the file.
241        remove_modules = []
242        for filename in ('Modules/Setup', 'Modules/Setup.local'):
243            input = text_file.TextFile(filename, join_lines=1)
244            while 1:
245                line = input.readline()
246                if not line: break
247                line = line.split()
248                remove_modules.append(line[0])
249            input.close()
250
251        for ext in self.extensions[:]:
252            if ext.name in remove_modules:
253                self.extensions.remove(ext)
254
255        # When you run "make CC=altcc" or something similar, you really want
256        # those environment variables passed into the setup.py phase.  Here's
257        # a small set of useful ones.
258        compiler = os.environ.get('CC')
259        args = {}
260        # unfortunately, distutils doesn't let us provide separate C and C++
261        # compilers
262        if compiler is not None:
263            (ccshared,cflags) = sysconfig.get_config_vars('CCSHARED','CFLAGS')
264            args['compiler_so'] = compiler + ' ' + ccshared + ' ' + cflags
265        self.compiler.set_executables(**args)
266
267        build_ext.build_extensions(self)
268
269        longest = 0
270        if self.extensions:
271            longest = max([len(e.name) for e in self.extensions])
272        if self.failed:
273            longest = max(longest, max([len(name) for name in self.failed]))
274
275        def print_three_column(lst):
276            lst.sort(key=str.lower)
277            # guarantee zip() doesn't drop anything
278            while len(lst) % 3:
279                lst.append("")
280            for e, f, g in zip(lst[::3], lst[1::3], lst[2::3]):
281                print "%-*s   %-*s   %-*s" % (longest, e, longest, f,
282                                              longest, g)
283
284        if missing:
285            print
286            print ("Python build finished, but the necessary bits to build "
287                   "these modules were not found:")
288            print_three_column(missing)
289            print ("To find the necessary bits, look in setup.py in"
290                   " detect_modules() for the module's name.")
291            print
292
293        if self.failed:
294            failed = self.failed[:]
295            print
296            print "Failed to build these modules:"
297            print_three_column(failed)
298            print
299
300    def build_extension(self, ext):
301
302        if ext.name == '_ctypes':
303            if not self.configure_ctypes(ext):
304                return
305
306        try:
307            build_ext.build_extension(self, ext)
308        except (CCompilerError, DistutilsError), why:
309            self.announce('WARNING: building of extension "%s" failed: %s' %
310                          (ext.name, sys.exc_info()[1]))
311            self.failed.append(ext.name)
312            return
313        # Workaround for Mac OS X: The Carbon-based modules cannot be
314        # reliably imported into a command-line Python
315        if 'Carbon' in ext.extra_link_args:
316            self.announce(
317                'WARNING: skipping import check for Carbon-based "%s"' %
318                ext.name)
319            return
320
321        if host_platform == 'darwin' and (
322                sys.maxint > 2**32 and '-arch' in ext.extra_link_args):
323            # Don't bother doing an import check when an extension was
324            # build with an explicit '-arch' flag on OSX. That's currently
325            # only used to build 32-bit only extensions in a 4-way
326            # universal build and loading 32-bit code into a 64-bit
327            # process will fail.
328            self.announce(
329                'WARNING: skipping import check for "%s"' %
330                ext.name)
331            return
332
333        # Workaround for Cygwin: Cygwin currently has fork issues when many
334        # modules have been imported
335        if host_platform == 'cygwin':
336            self.announce('WARNING: skipping import check for Cygwin-based "%s"'
337                % ext.name)
338            return
339        ext_filename = os.path.join(
340            self.build_lib,
341            self.get_ext_filename(self.get_ext_fullname(ext.name)))
342
343        # Don't try to load extensions for cross builds
344        if cross_compiling:
345            return
346
347        try:
348            imp.load_dynamic(ext.name, ext_filename)
349        except ImportError, why:
350            self.failed.append(ext.name)
351            self.announce('*** WARNING: renaming "%s" since importing it'
352                          ' failed: %s' % (ext.name, why), level=3)
353            assert not self.inplace
354            basename, tail = os.path.splitext(ext_filename)
355            newname = basename + "_failed" + tail
356            if os.path.exists(newname):
357                os.remove(newname)
358            os.rename(ext_filename, newname)
359
360            # XXX -- This relies on a Vile HACK in
361            # distutils.command.build_ext.build_extension().  The
362            # _built_objects attribute is stored there strictly for
363            # use here.
364            # If there is a failure, _built_objects may not be there,
365            # so catch the AttributeError and move on.
366            try:
367                for filename in self._built_objects:
368                    os.remove(filename)
369            except AttributeError:
370                self.announce('unable to remove files (ignored)')
371        except:
372            exc_type, why, tb = sys.exc_info()
373            self.announce('*** WARNING: importing extension "%s" '
374                          'failed with %s: %s' % (ext.name, exc_type, why),
375                          level=3)
376            self.failed.append(ext.name)
377
378    def add_multiarch_paths(self):
379        # Debian/Ubuntu multiarch support.
380        # https://wiki.ubuntu.com/MultiarchSpec
381        cc = sysconfig.get_config_var('CC')
382        tmpfile = os.path.join(self.build_temp, 'multiarch')
383        if not os.path.exists(self.build_temp):
384            os.makedirs(self.build_temp)
385        ret = os.system(
386            '%s -print-multiarch > %s 2> /dev/null' % (cc, tmpfile))
387        multiarch_path_component = ''
388        try:
389            if ret >> 8 == 0:
390                with open(tmpfile) as fp:
391                    multiarch_path_component = fp.readline().strip()
392        finally:
393            os.unlink(tmpfile)
394
395        if multiarch_path_component != '':
396            add_dir_to_list(self.compiler.library_dirs,
397                            '/usr/lib/' + multiarch_path_component)
398            add_dir_to_list(self.compiler.include_dirs,
399                            '/usr/include/' + multiarch_path_component)
400            return
401
402        if not find_executable('dpkg-architecture'):
403            return
404        opt = ''
405        if cross_compiling:
406            opt = '-t' + sysconfig.get_config_var('HOST_GNU_TYPE')
407        tmpfile = os.path.join(self.build_temp, 'multiarch')
408        if not os.path.exists(self.build_temp):
409            os.makedirs(self.build_temp)
410        ret = os.system(
411            'dpkg-architecture %s -qDEB_HOST_MULTIARCH > %s 2> /dev/null' %
412            (opt, tmpfile))
413        try:
414            if ret >> 8 == 0:
415                with open(tmpfile) as fp:
416                    multiarch_path_component = fp.readline().strip()
417                add_dir_to_list(self.compiler.library_dirs,
418                                '/usr/lib/' + multiarch_path_component)
419                add_dir_to_list(self.compiler.include_dirs,
420                                '/usr/include/' + multiarch_path_component)
421        finally:
422            os.unlink(tmpfile)
423
424    def add_gcc_paths(self):
425        gcc = sysconfig.get_config_var('CC')
426        tmpfile = os.path.join(self.build_temp, 'gccpaths')
427        if not os.path.exists(self.build_temp):
428            os.makedirs(self.build_temp)
429        ret = os.system('%s -E -v - </dev/null 2>%s 1>/dev/null' % (gcc, tmpfile))
430        is_gcc = False
431        in_incdirs = False
432        inc_dirs = []
433        lib_dirs = []
434        try:
435            if ret >> 8 == 0:
436                with open(tmpfile) as fp:
437                    for line in fp.readlines():
438                        if line.startswith("gcc version"):
439                            is_gcc = True
440                        elif line.startswith("#include <...>"):
441                            in_incdirs = True
442                        elif line.startswith("End of search list"):
443                            in_incdirs = False
444                        elif is_gcc and line.startswith("LIBRARY_PATH"):
445                            for d in line.strip().split("=")[1].split(":"):
446                                d = os.path.normpath(d)
447                                if '/gcc/' not in d:
448                                    add_dir_to_list(self.compiler.library_dirs,
449                                                    d)
450                        elif is_gcc and in_incdirs and '/gcc/' not in line:
451                            add_dir_to_list(self.compiler.include_dirs,
452                                            line.strip())
453        finally:
454            os.unlink(tmpfile)
455
456    def detect_modules(self):
457        # Ensure that /usr/local is always used
458        if not cross_compiling:
459            add_dir_to_list(self.compiler.library_dirs, '/usr/local/lib')
460            add_dir_to_list(self.compiler.include_dirs, '/usr/local/include')
461        if cross_compiling:
462            self.add_gcc_paths()
463        self.add_multiarch_paths()
464
465        # Add paths specified in the environment variables LDFLAGS and
466        # CPPFLAGS for header and library files.
467        # We must get the values from the Makefile and not the environment
468        # directly since an inconsistently reproducible issue comes up where
469        # the environment variable is not set even though the value were passed
470        # into configure and stored in the Makefile (issue found on OS X 10.3).
471        for env_var, arg_name, dir_list in (
472                ('LDFLAGS', '-R', self.compiler.runtime_library_dirs),
473                ('LDFLAGS', '-L', self.compiler.library_dirs),
474                ('CPPFLAGS', '-I', self.compiler.include_dirs)):
475            env_val = sysconfig.get_config_var(env_var)
476            if env_val:
477                # To prevent optparse from raising an exception about any
478                # options in env_val that it doesn't know about we strip out
479                # all double dashes and any dashes followed by a character
480                # that is not for the option we are dealing with.
481                #
482                # Please note that order of the regex is important!  We must
483                # strip out double-dashes first so that we don't end up with
484                # substituting "--Long" to "-Long" and thus lead to "ong" being
485                # used for a library directory.
486                env_val = re.sub(r'(^|\s+)-(-|(?!%s))' % arg_name[1],
487                                 ' ', env_val)
488                parser = optparse.OptionParser()
489                # Make sure that allowing args interspersed with options is
490                # allowed
491                parser.allow_interspersed_args = True
492                parser.error = lambda msg: None
493                parser.add_option(arg_name, dest="dirs", action="append")
494                options = parser.parse_args(env_val.split())[0]
495                if options.dirs:
496                    for directory in reversed(options.dirs):
497                        add_dir_to_list(dir_list, directory)
498
499        if os.path.normpath(sys.prefix) != '/usr' \
500                and not sysconfig.get_config_var('PYTHONFRAMEWORK'):
501            # OSX note: Don't add LIBDIR and INCLUDEDIR to building a framework
502            # (PYTHONFRAMEWORK is set) to avoid # linking problems when
503            # building a framework with different architectures than
504            # the one that is currently installed (issue #7473)
505            add_dir_to_list(self.compiler.library_dirs,
506                            sysconfig.get_config_var("LIBDIR"))
507            add_dir_to_list(self.compiler.include_dirs,
508                            sysconfig.get_config_var("INCLUDEDIR"))
509
510        try:
511            have_unicode = unicode
512        except NameError:
513            have_unicode = 0
514
515        # lib_dirs and inc_dirs are used to search for files;
516        # if a file is found in one of those directories, it can
517        # be assumed that no additional -I,-L directives are needed.
518        inc_dirs = self.compiler.include_dirs[:]
519        lib_dirs = self.compiler.library_dirs[:]
520        if not cross_compiling:
521            for d in (
522                '/usr/include',
523                ):
524                add_dir_to_list(inc_dirs, d)
525            for d in (
526                '/lib64', '/usr/lib64',
527                '/lib', '/usr/lib',
528                ):
529                add_dir_to_list(lib_dirs, d)
530        exts = []
531        missing = []
532
533        config_h = sysconfig.get_config_h_filename()
534        config_h_vars = sysconfig.parse_config_h(open(config_h))
535
536        srcdir = sysconfig.get_config_var('srcdir')
537
538        # Check for AtheOS which has libraries in non-standard locations
539        if host_platform == 'atheos':
540            lib_dirs += ['/system/libs', '/atheos/autolnk/lib']
541            lib_dirs += os.getenv('LIBRARY_PATH', '').split(os.pathsep)
542            inc_dirs += ['/system/include', '/atheos/autolnk/include']
543            inc_dirs += os.getenv('C_INCLUDE_PATH', '').split(os.pathsep)
544
545        # OSF/1 and Unixware have some stuff in /usr/ccs/lib (like -ldb)
546        if host_platform in ['osf1', 'unixware7', 'openunix8']:
547            lib_dirs += ['/usr/ccs/lib']
548
549        # HP-UX11iv3 keeps files in lib/hpux folders.
550        if host_platform == 'hp-ux11':
551            lib_dirs += ['/usr/lib/hpux64', '/usr/lib/hpux32']
552
553        if host_platform == 'darwin':
554            # This should work on any unixy platform ;-)
555            # If the user has bothered specifying additional -I and -L flags
556            # in OPT and LDFLAGS we might as well use them here.
557            #   NOTE: using shlex.split would technically be more correct, but
558            # also gives a bootstrap problem. Let's hope nobody uses directories
559            # with whitespace in the name to store libraries.
560            cflags, ldflags = sysconfig.get_config_vars(
561                    'CFLAGS', 'LDFLAGS')
562            for item in cflags.split():
563                if item.startswith('-I'):
564                    inc_dirs.append(item[2:])
565
566            for item in ldflags.split():
567                if item.startswith('-L'):
568                    lib_dirs.append(item[2:])
569
570        # Check for MacOS X, which doesn't need libm.a at all
571        math_libs = ['m']
572        if host_platform in ['darwin', 'beos']:
573            math_libs = []
574
575        # XXX Omitted modules: gl, pure, dl, SGI-specific modules
576
577        #
578        # The following modules are all pretty straightforward, and compile
579        # on pretty much any POSIXish platform.
580        #
581
582        # Some modules that are normally always on:
583        #exts.append( Extension('_weakref', ['_weakref.c']) )
584
585        # array objects
586        exts.append( Extension('array', ['arraymodule.c']) )
587
588        shared_math = 'Modules/_math.o'
589        # complex math library functions
590        exts.append( Extension('cmath', ['cmathmodule.c'],
591                               extra_objects=[shared_math],
592                               depends=['_math.h', shared_math],
593                               libraries=math_libs) )
594        # math library functions, e.g. sin()
595        exts.append( Extension('math',  ['mathmodule.c'],
596                               extra_objects=[shared_math],
597                               depends=['_math.h', shared_math],
598                               libraries=math_libs) )
599        # fast string operations implemented in C
600        exts.append( Extension('strop', ['stropmodule.c']) )
601        # time operations and variables
602        exts.append( Extension('time', ['timemodule.c'],
603                               libraries=math_libs) )
604        exts.append( Extension('datetime', ['datetimemodule.c', 'timemodule.c'],
605                               libraries=math_libs) )
606        # fast iterator tools implemented in C
607        exts.append( Extension("itertools", ["itertoolsmodule.c"]) )
608        # code that will be builtins in the future, but conflict with the
609        #  current builtins
610        exts.append( Extension('future_builtins', ['future_builtins.c']) )
611        # random number generator implemented in C
612        exts.append( Extension("_random", ["_randommodule.c"]) )
613        # high-performance collections
614        exts.append( Extension("_collections", ["_collectionsmodule.c"]) )
615        # bisect
616        exts.append( Extension("_bisect", ["_bisectmodule.c"]) )
617        # heapq
618        exts.append( Extension("_heapq", ["_heapqmodule.c"]) )
619        # operator.add() and similar goodies
620        exts.append( Extension('operator', ['operator.c']) )
621        # Python 3.1 _io library
622        exts.append( Extension("_io",
623            ["_io/bufferedio.c", "_io/bytesio.c", "_io/fileio.c",
624             "_io/iobase.c", "_io/_iomodule.c", "_io/stringio.c", "_io/textio.c"],
625             depends=["_io/_iomodule.h"], include_dirs=["Modules/_io"]))
626        # _functools
627        exts.append( Extension("_functools", ["_functoolsmodule.c"]) )
628        # _json speedups
629        exts.append( Extension("_json", ["_json.c"]) )
630        # Python C API test module
631        exts.append( Extension('_testcapi', ['_testcapimodule.c'],
632                               depends=['testcapi_long.h']) )
633        # profilers (_lsprof is for cProfile.py)
634        exts.append( Extension('_hotshot', ['_hotshot.c']) )
635        exts.append( Extension('_lsprof', ['_lsprof.c', 'rotatingtree.c']) )
636        # static Unicode character database
637        if have_unicode:
638            exts.append( Extension('unicodedata', ['unicodedata.c']) )
639        else:
640            missing.append('unicodedata')
641        # access to ISO C locale support
642        data = open('pyconfig.h').read()
643        m = re.search(r"#s*define\s+WITH_LIBINTL\s+1\s*", data)
644        if m is not None:
645            locale_libs = ['intl']
646        else:
647            locale_libs = []
648        if host_platform == 'darwin':
649            locale_extra_link_args = ['-framework', 'CoreFoundation']
650        else:
651            locale_extra_link_args = []
652
653
654        exts.append( Extension('_locale', ['_localemodule.c'],
655                               libraries=locale_libs,
656                               extra_link_args=locale_extra_link_args) )
657
658        # Modules with some UNIX dependencies -- on by default:
659        # (If you have a really backward UNIX, select and socket may not be
660        # supported...)
661
662        # fcntl(2) and ioctl(2)
663        libs = []
664        if (config_h_vars.get('FLOCK_NEEDS_LIBBSD', False)):
665            # May be necessary on AIX for flock function
666            libs = ['bsd']
667        exts.append( Extension('fcntl', ['fcntlmodule.c'], libraries=libs) )
668        # pwd(3)
669        exts.append( Extension('pwd', ['pwdmodule.c']) )
670        # grp(3)
671        exts.append( Extension('grp', ['grpmodule.c']) )
672        # spwd, shadow passwords
673        if (config_h_vars.get('HAVE_GETSPNAM', False) or
674                config_h_vars.get('HAVE_GETSPENT', False)):
675            exts.append( Extension('spwd', ['spwdmodule.c']) )
676        else:
677            missing.append('spwd')
678
679        # select(2); not on ancient System V
680        exts.append( Extension('select', ['selectmodule.c']) )
681
682        # Fred Drake's interface to the Python parser
683        exts.append( Extension('parser', ['parsermodule.c']) )
684
685        # cStringIO and cPickle
686        exts.append( Extension('cStringIO', ['cStringIO.c']) )
687        exts.append( Extension('cPickle', ['cPickle.c']) )
688
689        # Memory-mapped files (also works on Win32).
690        if host_platform not in ['atheos']:
691            exts.append( Extension('mmap', ['mmapmodule.c']) )
692        else:
693            missing.append('mmap')
694
695        # Lance Ellinghaus's syslog module
696        # syslog daemon interface
697        exts.append( Extension('syslog', ['syslogmodule.c']) )
698
699        # George Neville-Neil's timing module:
700        # Deprecated in PEP 4 http://www.python.org/peps/pep-0004.html
701        # http://mail.python.org/pipermail/python-dev/2006-January/060023.html
702        #exts.append( Extension('timing', ['timingmodule.c']) )
703
704        #
705        # Here ends the simple stuff.  From here on, modules need certain
706        # libraries, are platform-specific, or present other surprises.
707        #
708
709        # Multimedia modules
710        # These don't work for 64-bit platforms!!!
711        # These represent audio samples or images as strings:
712
713        # Operations on audio samples
714        # According to #993173, this one should actually work fine on
715        # 64-bit platforms.
716        exts.append( Extension('audioop', ['audioop.c']) )
717
718        # Disabled on 64-bit platforms
719        if sys.maxsize != 9223372036854775807L:
720            # Operations on images
721            exts.append( Extension('imageop', ['imageop.c']) )
722        else:
723            missing.extend(['imageop'])
724
725        # readline
726        do_readline = self.compiler.find_library_file(lib_dirs, 'readline')
727        readline_termcap_library = ""
728        curses_library = ""
729        # Determine if readline is already linked against curses or tinfo.
730        if do_readline and find_executable('ldd'):
731            fp = os.popen("ldd %s" % do_readline)
732            ldd_output = fp.readlines()
733            ret = fp.close()
734            if ret is None or ret >> 8 == 0:
735                for ln in ldd_output:
736                    if 'curses' in ln:
737                        readline_termcap_library = re.sub(
738                            r'.*lib(n?cursesw?)\.so.*', r'\1', ln
739                        ).rstrip()
740                        break
741                    if 'tinfo' in ln: # termcap interface split out from ncurses
742                        readline_termcap_library = 'tinfo'
743                        break
744        # Issue 7384: If readline is already linked against curses,
745        # use the same library for the readline and curses modules.
746        if 'curses' in readline_termcap_library:
747            curses_library = readline_termcap_library
748        elif self.compiler.find_library_file(lib_dirs, 'ncursesw'):
749            curses_library = 'ncursesw'
750        elif self.compiler.find_library_file(lib_dirs, 'ncurses'):
751            curses_library = 'ncurses'
752        elif self.compiler.find_library_file(lib_dirs, 'curses'):
753            curses_library = 'curses'
754
755        if host_platform == 'darwin':
756            os_release = int(os.uname()[2].split('.')[0])
757            dep_target = sysconfig.get_config_var('MACOSX_DEPLOYMENT_TARGET')
758            if (dep_target and
759                    (tuple(int(n) for n in dep_target.split('.')[0:2])
760                        < (10, 5) ) ):
761                os_release = 8
762            if os_release < 9:
763                # MacOSX 10.4 has a broken readline. Don't try to build
764                # the readline module unless the user has installed a fixed
765                # readline package
766                if find_file('readline/rlconf.h', inc_dirs, []) is None:
767                    do_readline = False
768        if do_readline:
769            if host_platform == 'darwin' and os_release < 9:
770                # In every directory on the search path search for a dynamic
771                # library and then a static library, instead of first looking
772                # for dynamic libraries on the entire path.
773                # This way a statically linked custom readline gets picked up
774                # before the (possibly broken) dynamic library in /usr/lib.
775                readline_extra_link_args = ('-Wl,-search_paths_first',)
776            else:
777                readline_extra_link_args = ()
778
779            readline_libs = ['readline']
780            if readline_termcap_library:
781                pass # Issue 7384: Already linked against curses or tinfo.
782            elif curses_library:
783                readline_libs.append(curses_library)
784            elif self.compiler.find_library_file(lib_dirs +
785                                                     ['/usr/lib/termcap'],
786                                                     'termcap'):
787                readline_libs.append('termcap')
788            exts.append( Extension('readline', ['readline.c'],
789                                   library_dirs=['/usr/lib/termcap'],
790                                   extra_link_args=readline_extra_link_args,
791                                   libraries=readline_libs) )
792        else:
793            missing.append('readline')
794
795        # crypt module.
796
797        if self.compiler.find_library_file(lib_dirs, 'crypt'):
798            libs = ['crypt']
799        else:
800            libs = []
801        exts.append( Extension('crypt', ['cryptmodule.c'], libraries=libs) )
802
803        # CSV files
804        exts.append( Extension('_csv', ['_csv.c']) )
805
806        # socket(2)
807        exts.append( Extension('_socket', ['socketmodule.c', 'timemodule.c'],
808                               depends=['socketmodule.h'],
809                               libraries=math_libs) )
810        # Detect SSL support for the socket module (via _ssl)
811        search_for_ssl_incs_in = [
812                              '/usr/local/ssl/include',
813                              '/usr/contrib/ssl/include/'
814                             ]
815        ssl_incs = find_file('openssl/ssl.h', inc_dirs,
816                             search_for_ssl_incs_in
817                             )
818        if ssl_incs is not None:
819            krb5_h = find_file('krb5.h', inc_dirs,
820                               ['/usr/kerberos/include'])
821            if krb5_h:
822                ssl_incs += krb5_h
823        ssl_libs = find_library_file(self.compiler, 'ssl',lib_dirs,
824                                     ['/usr/local/ssl/lib',
825                                      '/usr/contrib/ssl/lib/'
826                                     ] )
827
828        if (ssl_incs is not None and
829            ssl_libs is not None):
830            exts.append( Extension('_ssl', ['_ssl.c'],
831                                   include_dirs = ssl_incs,
832                                   library_dirs = ssl_libs,
833                                   libraries = ['ssl', 'crypto'],
834                                   depends = ['socketmodule.h']), )
835        else:
836            missing.append('_ssl')
837
838        # find out which version of OpenSSL we have
839        openssl_ver = 0
840        openssl_ver_re = re.compile(
841            '^\s*#\s*define\s+OPENSSL_VERSION_NUMBER\s+(0x[0-9a-fA-F]+)' )
842
843        # look for the openssl version header on the compiler search path.
844        opensslv_h = find_file('openssl/opensslv.h', [],
845                inc_dirs + search_for_ssl_incs_in)
846        if opensslv_h:
847            name = os.path.join(opensslv_h[0], 'openssl/opensslv.h')
848            if host_platform == 'darwin' and is_macosx_sdk_path(name):
849                name = os.path.join(macosx_sdk_root(), name[1:])
850            try:
851                incfile = open(name, 'r')
852                for line in incfile:
853                    m = openssl_ver_re.match(line)
854                    if m:
855                        openssl_ver = eval(m.group(1))
856            except IOError, msg:
857                print "IOError while reading opensshv.h:", msg
858                pass
859
860        min_openssl_ver = 0x00907000
861        have_any_openssl = ssl_incs is not None and ssl_libs is not None
862        have_usable_openssl = (have_any_openssl and
863                               openssl_ver >= min_openssl_ver)
864
865        if have_any_openssl:
866            if have_usable_openssl:
867                # The _hashlib module wraps optimized implementations
868                # of hash functions from the OpenSSL library.
869                exts.append( Extension('_hashlib', ['_hashopenssl.c'],
870                                       include_dirs = ssl_incs,
871                                       library_dirs = ssl_libs,
872                                       libraries = ['ssl', 'crypto']) )
873            else:
874                print ("warning: openssl 0x%08x is too old for _hashlib" %
875                       openssl_ver)
876                missing.append('_hashlib')
877        if COMPILED_WITH_PYDEBUG or not have_usable_openssl:
878            # The _sha module implements the SHA1 hash algorithm.
879            exts.append( Extension('_sha', ['shamodule.c']) )
880            # The _md5 module implements the RSA Data Security, Inc. MD5
881            # Message-Digest Algorithm, described in RFC 1321.  The
882            # necessary files md5.c and md5.h are included here.
883            exts.append( Extension('_md5',
884                            sources = ['md5module.c', 'md5.c'],
885                            depends = ['md5.h']) )
886
887        min_sha2_openssl_ver = 0x00908000
888        if COMPILED_WITH_PYDEBUG or openssl_ver < min_sha2_openssl_ver:
889            # OpenSSL doesn't do these until 0.9.8 so we'll bring our own hash
890            exts.append( Extension('_sha256', ['sha256module.c']) )
891            exts.append( Extension('_sha512', ['sha512module.c']) )
892
893        # Modules that provide persistent dictionary-like semantics.  You will
894        # probably want to arrange for at least one of them to be available on
895        # your machine, though none are defined by default because of library
896        # dependencies.  The Python module anydbm.py provides an
897        # implementation independent wrapper for these; dumbdbm.py provides
898        # similar functionality (but slower of course) implemented in Python.
899
900        # Sleepycat^WOracle Berkeley DB interface.
901        #  http://www.oracle.com/database/berkeley-db/db/index.html
902        #
903        # This requires the Sleepycat^WOracle DB code. The supported versions
904        # are set below.  Visit the URL above to download
905        # a release.  Most open source OSes come with one or more
906        # versions of BerkeleyDB already installed.
907
908        max_db_ver = (5, 3)
909        min_db_ver = (4, 3)
910        db_setup_debug = False   # verbose debug prints from this script?
911
912        def allow_db_ver(db_ver):
913            """Returns a boolean if the given BerkeleyDB version is acceptable.
914
915            Args:
916              db_ver: A tuple of the version to verify.
917            """
918            if not (min_db_ver <= db_ver <= max_db_ver):
919                return False
920            # Use this function to filter out known bad configurations.
921            if (4, 6) == db_ver[:2]:
922                # BerkeleyDB 4.6.x is not stable on many architectures.
923                arch = platform_machine()
924                if arch not in ('i386', 'i486', 'i586', 'i686',
925                                'x86_64', 'ia64'):
926                    return False
927            return True
928
929        def gen_db_minor_ver_nums(major):
930            if major == 5:
931                for x in range(max_db_ver[1]+1):
932                    if allow_db_ver((5, x)):
933                        yield x
934            elif major == 4:
935                for x in range(9):
936                    if allow_db_ver((4, x)):
937                        yield x
938            elif major == 3:
939                for x in (3,):
940                    if allow_db_ver((3, x)):
941                        yield x
942            else:
943                raise ValueError("unknown major BerkeleyDB version", major)
944
945        # construct a list of paths to look for the header file in on
946        # top of the normal inc_dirs.
947        db_inc_paths = [
948            '/usr/include/db4',
949            '/usr/local/include/db4',
950            '/opt/sfw/include/db4',
951            '/usr/include/db3',
952            '/usr/local/include/db3',
953            '/opt/sfw/include/db3',
954            # Fink defaults (http://fink.sourceforge.net/)
955            '/sw/include/db4',
956            '/sw/include/db3',
957        ]
958        # 4.x minor number specific paths
959        for x in gen_db_minor_ver_nums(4):
960            db_inc_paths.append('/usr/include/db4%d' % x)
961            db_inc_paths.append('/usr/include/db4.%d' % x)
962            db_inc_paths.append('/usr/local/BerkeleyDB.4.%d/include' % x)
963            db_inc_paths.append('/usr/local/include/db4%d' % x)
964            db_inc_paths.append('/pkg/db-4.%d/include' % x)
965            db_inc_paths.append('/opt/db-4.%d/include' % x)
966            # MacPorts default (http://www.macports.org/)
967            db_inc_paths.append('/opt/local/include/db4%d' % x)
968        # 3.x minor number specific paths
969        for x in gen_db_minor_ver_nums(3):
970            db_inc_paths.append('/usr/include/db3%d' % x)
971            db_inc_paths.append('/usr/local/BerkeleyDB.3.%d/include' % x)
972            db_inc_paths.append('/usr/local/include/db3%d' % x)
973            db_inc_paths.append('/pkg/db-3.%d/include' % x)
974            db_inc_paths.append('/opt/db-3.%d/include' % x)
975
976        if cross_compiling:
977            db_inc_paths = []
978
979        # Add some common subdirectories for Sleepycat DB to the list,
980        # based on the standard include directories. This way DB3/4 gets
981        # picked up when it is installed in a non-standard prefix and
982        # the user has added that prefix into inc_dirs.
983        std_variants = []
984        for dn in inc_dirs:
985            std_variants.append(os.path.join(dn, 'db3'))
986            std_variants.append(os.path.join(dn, 'db4'))
987            for x in gen_db_minor_ver_nums(4):
988                std_variants.append(os.path.join(dn, "db4%d"%x))
989                std_variants.append(os.path.join(dn, "db4.%d"%x))
990            for x in gen_db_minor_ver_nums(3):
991                std_variants.append(os.path.join(dn, "db3%d"%x))
992                std_variants.append(os.path.join(dn, "db3.%d"%x))
993
994        db_inc_paths = std_variants + db_inc_paths
995        db_inc_paths = [p for p in db_inc_paths if os.path.exists(p)]
996
997        db_ver_inc_map = {}
998
999        if host_platform == 'darwin':
1000            sysroot = macosx_sdk_root()
1001
1002        class db_found(Exception): pass
1003        try:
1004            # See whether there is a Sleepycat header in the standard
1005            # search path.
1006            for d in inc_dirs + db_inc_paths:
1007                f = os.path.join(d, "db.h")
1008
1009                if host_platform == 'darwin' and is_macosx_sdk_path(d):
1010                    f = os.path.join(sysroot, d[1:], "db.h")
1011
1012                if db_setup_debug: print "db: looking for db.h in", f
1013                if os.path.exists(f):
1014                    f = open(f).read()
1015                    m = re.search(r"#define\WDB_VERSION_MAJOR\W(\d+)", f)
1016                    if m:
1017                        db_major = int(m.group(1))
1018                        m = re.search(r"#define\WDB_VERSION_MINOR\W(\d+)", f)
1019                        db_minor = int(m.group(1))
1020                        db_ver = (db_major, db_minor)
1021
1022                        # Avoid 4.6 prior to 4.6.21 due to a BerkeleyDB bug
1023                        if db_ver == (4, 6):
1024                            m = re.search(r"#define\WDB_VERSION_PATCH\W(\d+)", f)
1025                            db_patch = int(m.group(1))
1026                            if db_patch < 21:
1027                                print "db.h:", db_ver, "patch", db_patch,
1028                                print "being ignored (4.6.x must be >= 4.6.21)"
1029                                continue
1030
1031                        if ( (db_ver not in db_ver_inc_map) and
1032                            allow_db_ver(db_ver) ):
1033                            # save the include directory with the db.h version
1034                            # (first occurrence only)
1035                            db_ver_inc_map[db_ver] = d
1036                            if db_setup_debug:
1037                                print "db.h: found", db_ver, "in", d
1038                        else:
1039                            # we already found a header for this library version
1040                            if db_setup_debug: print "db.h: ignoring", d
1041                    else:
1042                        # ignore this header, it didn't contain a version number
1043                        if db_setup_debug:
1044                            print "db.h: no version number version in", d
1045
1046            db_found_vers = db_ver_inc_map.keys()
1047            db_found_vers.sort()
1048
1049            while db_found_vers:
1050                db_ver = db_found_vers.pop()
1051                db_incdir = db_ver_inc_map[db_ver]
1052
1053                # check lib directories parallel to the location of the header
1054                db_dirs_to_check = [
1055                    db_incdir.replace("include", 'lib64'),
1056                    db_incdir.replace("include", 'lib'),
1057                ]
1058
1059                if host_platform != 'darwin':
1060                    db_dirs_to_check = filter(os.path.isdir, db_dirs_to_check)
1061
1062                else:
1063                    # Same as other branch, but takes OSX SDK into account
1064                    tmp = []
1065                    for dn in db_dirs_to_check:
1066                        if is_macosx_sdk_path(dn):
1067                            if os.path.isdir(os.path.join(sysroot, dn[1:])):
1068                                tmp.append(dn)
1069                        else:
1070                            if os.path.isdir(dn):
1071                                tmp.append(dn)
1072                    db_dirs_to_check = tmp
1073
1074                # Look for a version specific db-X.Y before an ambiguous dbX
1075                # XXX should we -ever- look for a dbX name?  Do any
1076                # systems really not name their library by version and
1077                # symlink to more general names?
1078                for dblib in (('db-%d.%d' % db_ver),
1079                              ('db%d%d' % db_ver),
1080                              ('db%d' % db_ver[0])):
1081                    dblib_file = self.compiler.find_library_file(
1082                                    db_dirs_to_check + lib_dirs, dblib )
1083                    if dblib_file:
1084                        dblib_dir = [ os.path.abspath(os.path.dirname(dblib_file)) ]
1085                        raise db_found
1086                    else:
1087                        if db_setup_debug: print "db lib: ", dblib, "not found"
1088
1089        except db_found:
1090            if db_setup_debug:
1091                print "bsddb using BerkeleyDB lib:", db_ver, dblib
1092                print "bsddb lib dir:", dblib_dir, " inc dir:", db_incdir
1093            db_incs = [db_incdir]
1094            dblibs = [dblib]
1095            # We add the runtime_library_dirs argument because the
1096            # BerkeleyDB lib we're linking against often isn't in the
1097            # system dynamic library search path.  This is usually
1098            # correct and most trouble free, but may cause problems in
1099            # some unusual system configurations (e.g. the directory
1100            # is on an NFS server that goes away).
1101            exts.append(Extension('_bsddb', ['_bsddb.c'],
1102                                  depends = ['bsddb.h'],
1103                                  library_dirs=dblib_dir,
1104                                  runtime_library_dirs=dblib_dir,
1105                                  include_dirs=db_incs,
1106                                  libraries=dblibs))
1107        else:
1108            if db_setup_debug: print "db: no appropriate library found"
1109            db_incs = None
1110            dblibs = []
1111            dblib_dir = None
1112            missing.append('_bsddb')
1113
1114        # The sqlite interface
1115        sqlite_setup_debug = False   # verbose debug prints from this script?
1116
1117        # We hunt for #define SQLITE_VERSION "n.n.n"
1118        # We need to find >= sqlite version 3.0.8
1119        sqlite_incdir = sqlite_libdir = None
1120        sqlite_inc_paths = [ '/usr/include',
1121                             '/usr/include/sqlite',
1122                             '/usr/include/sqlite3',
1123                             '/usr/local/include',
1124                             '/usr/local/include/sqlite',
1125                             '/usr/local/include/sqlite3',
1126                           ]
1127        if cross_compiling:
1128            sqlite_inc_paths = []
1129        MIN_SQLITE_VERSION_NUMBER = (3, 0, 8)
1130        MIN_SQLITE_VERSION = ".".join([str(x)
1131                                    for x in MIN_SQLITE_VERSION_NUMBER])
1132
1133        # Scan the default include directories before the SQLite specific
1134        # ones. This allows one to override the copy of sqlite on OSX,
1135        # where /usr/include contains an old version of sqlite.
1136        if host_platform == 'darwin':
1137            sysroot = macosx_sdk_root()
1138
1139        for d_ in inc_dirs + sqlite_inc_paths:
1140            d = d_
1141            if host_platform == 'darwin' and is_macosx_sdk_path(d):
1142                d = os.path.join(sysroot, d[1:])
1143
1144            f = os.path.join(d, "sqlite3.h")
1145            if os.path.exists(f):
1146                if sqlite_setup_debug: print "sqlite: found %s"%f
1147                incf = open(f).read()
1148                m = re.search(
1149                    r'\s*.*#\s*.*define\s.*SQLITE_VERSION\W*"([\d\.]*)"', incf)
1150                if m:
1151                    sqlite_version = m.group(1)
1152                    sqlite_version_tuple = tuple([int(x)
1153                                        for x in sqlite_version.split(".")])
1154                    if sqlite_version_tuple >= MIN_SQLITE_VERSION_NUMBER:
1155                        # we win!
1156                        if sqlite_setup_debug:
1157                            print "%s/sqlite3.h: version %s"%(d, sqlite_version)
1158                        sqlite_incdir = d
1159                        break
1160                    else:
1161                        if sqlite_setup_debug:
1162                            print "%s: version %d is too old, need >= %s"%(d,
1163                                        sqlite_version, MIN_SQLITE_VERSION)
1164                elif sqlite_setup_debug:
1165                    print "sqlite: %s had no SQLITE_VERSION"%(f,)
1166
1167        if sqlite_incdir:
1168            sqlite_dirs_to_check = [
1169                os.path.join(sqlite_incdir, '..', 'lib64'),
1170                os.path.join(sqlite_incdir, '..', 'lib'),
1171                os.path.join(sqlite_incdir, '..', '..', 'lib64'),
1172                os.path.join(sqlite_incdir, '..', '..', 'lib'),
1173            ]
1174            sqlite_libfile = self.compiler.find_library_file(
1175                                sqlite_dirs_to_check + lib_dirs, 'sqlite3')
1176            if sqlite_libfile:
1177                sqlite_libdir = [os.path.abspath(os.path.dirname(sqlite_libfile))]
1178
1179        if sqlite_incdir and sqlite_libdir:
1180            sqlite_srcs = ['_sqlite/cache.c',
1181                '_sqlite/connection.c',
1182                '_sqlite/cursor.c',
1183                '_sqlite/microprotocols.c',
1184                '_sqlite/module.c',
1185                '_sqlite/prepare_protocol.c',
1186                '_sqlite/row.c',
1187                '_sqlite/statement.c',
1188                '_sqlite/util.c', ]
1189
1190            sqlite_defines = []
1191            if host_platform != "win32":
1192                sqlite_defines.append(('MODULE_NAME', '"sqlite3"'))
1193            else:
1194                sqlite_defines.append(('MODULE_NAME', '\\"sqlite3\\"'))
1195
1196            # Comment this out if you want the sqlite3 module to be able to load extensions.
1197            sqlite_defines.append(("SQLITE_OMIT_LOAD_EXTENSION", "1"))
1198
1199            if host_platform == 'darwin':
1200                # In every directory on the search path search for a dynamic
1201                # library and then a static library, instead of first looking
1202                # for dynamic libraries on the entire path.
1203                # This way a statically linked custom sqlite gets picked up
1204                # before the dynamic library in /usr/lib.
1205                sqlite_extra_link_args = ('-Wl,-search_paths_first',)
1206            else:
1207                sqlite_extra_link_args = ()
1208
1209            exts.append(Extension('_sqlite3', sqlite_srcs,
1210                                  define_macros=sqlite_defines,
1211                                  include_dirs=["Modules/_sqlite",
1212                                                sqlite_incdir],
1213                                  library_dirs=sqlite_libdir,
1214                                  extra_link_args=sqlite_extra_link_args,
1215                                  libraries=["sqlite3",]))
1216        else:
1217            missing.append('_sqlite3')
1218
1219        # Look for Berkeley db 1.85.   Note that it is built as a different
1220        # module name so it can be included even when later versions are
1221        # available.  A very restrictive search is performed to avoid
1222        # accidentally building this module with a later version of the
1223        # underlying db library.  May BSD-ish Unixes incorporate db 1.85
1224        # symbols into libc and place the include file in /usr/include.
1225        #
1226        # If the better bsddb library can be built (db_incs is defined)
1227        # we do not build this one.  Otherwise this build will pick up
1228        # the more recent berkeleydb's db.h file first in the include path
1229        # when attempting to compile and it will fail.
1230        f = "/usr/include/db.h"
1231
1232        if host_platform == 'darwin':
1233            if is_macosx_sdk_path(f):
1234                sysroot = macosx_sdk_root()
1235                f = os.path.join(sysroot, f[1:])
1236
1237        if os.path.exists(f) and not db_incs:
1238            data = open(f).read()
1239            m = re.search(r"#s*define\s+HASHVERSION\s+2\s*", data)
1240            if m is not None:
1241                # bingo - old version used hash file format version 2
1242                ### XXX this should be fixed to not be platform-dependent
1243                ### but I don't have direct access to an osf1 platform and
1244                ### seemed to be muffing the search somehow
1245                libraries = host_platform == "osf1" and ['db'] or None
1246                if libraries is not None:
1247                    exts.append(Extension('bsddb185', ['bsddbmodule.c'],
1248                                          libraries=libraries))
1249                else:
1250                    exts.append(Extension('bsddb185', ['bsddbmodule.c']))
1251            else:
1252                missing.append('bsddb185')
1253        else:
1254            missing.append('bsddb185')
1255
1256        dbm_order = ['gdbm']
1257        # The standard Unix dbm module:
1258        if host_platform not in ['cygwin']:
1259            config_args = [arg.strip("'")
1260                           for arg in sysconfig.get_config_var("CONFIG_ARGS").split()]
1261            dbm_args = [arg for arg in config_args
1262                        if arg.startswith('--with-dbmliborder=')]
1263            if dbm_args:
1264                dbm_order = [arg.split('=')[-1] for arg in dbm_args][-1].split(":")
1265            else:
1266                dbm_order = "ndbm:gdbm:bdb".split(":")
1267            dbmext = None
1268            for cand in dbm_order:
1269                if cand == "ndbm":
1270                    if find_file("ndbm.h", inc_dirs, []) is not None:
1271                        # Some systems have -lndbm, others have -lgdbm_compat,
1272                        # others don't have either
1273                        if self.compiler.find_library_file(lib_dirs,
1274                                                               'ndbm'):
1275                            ndbm_libs = ['ndbm']
1276                        elif self.compiler.find_library_file(lib_dirs,
1277                                                             'gdbm_compat'):
1278                            ndbm_libs = ['gdbm_compat']
1279                        else:
1280                            ndbm_libs = []
1281                        print "building dbm using ndbm"
1282                        dbmext = Extension('dbm', ['dbmmodule.c'],
1283                                           define_macros=[
1284                                               ('HAVE_NDBM_H',None),
1285                                               ],
1286                                           libraries=ndbm_libs)
1287                        break
1288
1289                elif cand == "gdbm":
1290                    if self.compiler.find_library_file(lib_dirs, 'gdbm'):
1291                        gdbm_libs = ['gdbm']
1292                        if self.compiler.find_library_file(lib_dirs,
1293                                                               'gdbm_compat'):
1294                            gdbm_libs.append('gdbm_compat')
1295                        if find_file("gdbm/ndbm.h", inc_dirs, []) is not None:
1296                            print "building dbm using gdbm"
1297                            dbmext = Extension(
1298                                'dbm', ['dbmmodule.c'],
1299                                define_macros=[
1300                                    ('HAVE_GDBM_NDBM_H', None),
1301                                    ],
1302                                libraries = gdbm_libs)
1303                            break
1304                        if find_file("gdbm-ndbm.h", inc_dirs, []) is not None:
1305                            print "building dbm using gdbm"
1306                            dbmext = Extension(
1307                                'dbm', ['dbmmodule.c'],
1308                                define_macros=[
1309                                    ('HAVE_GDBM_DASH_NDBM_H', None),
1310                                    ],
1311                                libraries = gdbm_libs)
1312                            break
1313                elif cand == "bdb":
1314                    if db_incs is not None:
1315                        print "building dbm using bdb"
1316                        dbmext = Extension('dbm', ['dbmmodule.c'],
1317                                           library_dirs=dblib_dir,
1318                                           runtime_library_dirs=dblib_dir,
1319                                           include_dirs=db_incs,
1320                                           define_macros=[
1321                                               ('HAVE_BERKDB_H', None),
1322                                               ('DB_DBM_HSEARCH', None),
1323                                               ],
1324                                           libraries=dblibs)
1325                        break
1326            if dbmext is not None:
1327                exts.append(dbmext)
1328            else:
1329                missing.append('dbm')
1330
1331        # Anthony Baxter's gdbm module.  GNU dbm(3) will require -lgdbm:
1332        if ('gdbm' in dbm_order and
1333            self.compiler.find_library_file(lib_dirs, 'gdbm')):
1334            exts.append( Extension('gdbm', ['gdbmmodule.c'],
1335                                   libraries = ['gdbm'] ) )
1336        else:
1337            missing.append('gdbm')
1338
1339        # Unix-only modules
1340        if host_platform not in ['win32']:
1341            # Steen Lumholt's termios module
1342            exts.append( Extension('termios', ['termios.c']) )
1343            # Jeremy Hylton's rlimit interface
1344            if host_platform not in ['atheos']:
1345                exts.append( Extension('resource', ['resource.c']) )
1346            else:
1347                missing.append('resource')
1348
1349            # Sun yellow pages. Some systems have the functions in libc.
1350            if (host_platform not in ['cygwin', 'atheos', 'qnx6'] and
1351                find_file('rpcsvc/yp_prot.h', inc_dirs, []) is not None):
1352                if (self.compiler.find_library_file(lib_dirs, 'nsl')):
1353                    libs = ['nsl']
1354                else:
1355                    libs = []
1356                exts.append( Extension('nis', ['nismodule.c'],
1357                                       libraries = libs) )
1358            else:
1359                missing.append('nis')
1360        else:
1361            missing.extend(['nis', 'resource', 'termios'])
1362
1363        # Curses support, requiring the System V version of curses, often
1364        # provided by the ncurses library.
1365        panel_library = 'panel'
1366        curses_incs = None
1367        if curses_library.startswith('ncurses'):
1368            if curses_library == 'ncursesw':
1369                # Bug 1464056: If _curses.so links with ncursesw,
1370                # _curses_panel.so must link with panelw.
1371                panel_library = 'panelw'
1372            curses_libs = [curses_library]
1373            curses_incs = find_file('curses.h', inc_dirs,
1374                                    [os.path.join(d, 'ncursesw') for d in inc_dirs])
1375            exts.append( Extension('_curses', ['_cursesmodule.c'],
1376                                   include_dirs = curses_incs,
1377                                   libraries = curses_libs) )
1378        elif curses_library == 'curses' and host_platform != 'darwin':
1379                # OSX has an old Berkeley curses, not good enough for
1380                # the _curses module.
1381            if (self.compiler.find_library_file(lib_dirs, 'terminfo')):
1382                curses_libs = ['curses', 'terminfo']
1383            elif (self.compiler.find_library_file(lib_dirs, 'termcap')):
1384                curses_libs = ['curses', 'termcap']
1385            else:
1386                curses_libs = ['curses']
1387
1388            exts.append( Extension('_curses', ['_cursesmodule.c'],
1389                                   libraries = curses_libs) )
1390        else:
1391            missing.append('_curses')
1392
1393        # If the curses module is enabled, check for the panel module
1394        if (module_enabled(exts, '_curses') and
1395            self.compiler.find_library_file(lib_dirs, panel_library)):
1396            exts.append( Extension('_curses_panel', ['_curses_panel.c'],
1397                                   include_dirs = curses_incs,
1398                                   libraries = [panel_library] + curses_libs) )
1399        else:
1400            missing.append('_curses_panel')
1401
1402        # Andrew Kuchling's zlib module.  Note that some versions of zlib
1403        # 1.1.3 have security problems.  See CERT Advisory CA-2002-07:
1404        # http://www.cert.org/advisories/CA-2002-07.html
1405        #
1406        # zlib 1.1.4 is fixed, but at least one vendor (RedHat) has decided to
1407        # patch its zlib 1.1.3 package instead of upgrading to 1.1.4.  For
1408        # now, we still accept 1.1.3, because we think it's difficult to
1409        # exploit this in Python, and we'd rather make it RedHat's problem
1410        # than our problem <wink>.
1411        #
1412        # You can upgrade zlib to version 1.1.4 yourself by going to
1413        # http://www.gzip.org/zlib/
1414        zlib_inc = find_file('zlib.h', [], inc_dirs)
1415        have_zlib = False
1416        if zlib_inc is not None:
1417            zlib_h = zlib_inc[0] + '/zlib.h'
1418            version = '"0.0.0"'
1419            version_req = '"1.1.3"'
1420            if host_platform == 'darwin' and is_macosx_sdk_path(zlib_h):
1421                zlib_h = os.path.join(macosx_sdk_root(), zlib_h[1:])
1422            fp = open(zlib_h)
1423            while 1:
1424                line = fp.readline()
1425                if not line:
1426                    break
1427                if line.startswith('#define ZLIB_VERSION'):
1428                    version = line.split()[2]
1429                    break
1430            if version >= version_req:
1431                if (self.compiler.find_library_file(lib_dirs, 'z')):
1432                    if host_platform == "darwin":
1433                        zlib_extra_link_args = ('-Wl,-search_paths_first',)
1434                    else:
1435                        zlib_extra_link_args = ()
1436                    exts.append( Extension('zlib', ['zlibmodule.c'],
1437                                           libraries = ['z'],
1438                                           extra_link_args = zlib_extra_link_args))
1439                    have_zlib = True
1440                else:
1441                    missing.append('zlib')
1442            else:
1443                missing.append('zlib')
1444        else:
1445            missing.append('zlib')
1446
1447        # Helper module for various ascii-encoders.  Uses zlib for an optimized
1448        # crc32 if we have it.  Otherwise binascii uses its own.
1449        if have_zlib:
1450            extra_compile_args = ['-DUSE_ZLIB_CRC32']
1451            libraries = ['z']
1452            extra_link_args = zlib_extra_link_args
1453        else:
1454            extra_compile_args = []
1455            libraries = []
1456            extra_link_args = []
1457        exts.append( Extension('binascii', ['binascii.c'],
1458                               extra_compile_args = extra_compile_args,
1459                               libraries = libraries,
1460                               extra_link_args = extra_link_args) )
1461
1462        # Gustavo Niemeyer's bz2 module.
1463        if (self.compiler.find_library_file(lib_dirs, 'bz2')):
1464            if host_platform == "darwin":
1465                bz2_extra_link_args = ('-Wl,-search_paths_first',)
1466            else:
1467                bz2_extra_link_args = ()
1468            exts.append( Extension('bz2', ['bz2module.c'],
1469                                   libraries = ['bz2'],
1470                                   extra_link_args = bz2_extra_link_args) )
1471        else:
1472            missing.append('bz2')
1473
1474        # Interface to the Expat XML parser
1475        #
1476        # Expat was written by James Clark and is now maintained by a group of
1477        # developers on SourceForge; see www.libexpat.org for more information.
1478        # The pyexpat module was written by Paul Prescod after a prototype by
1479        # Jack Jansen.  The Expat source is included in Modules/expat/.  Usage
1480        # of a system shared libexpat.so is possible with --with-system-expat
1481        # configure option.
1482        #
1483        # More information on Expat can be found at www.libexpat.org.
1484        #
1485        if '--with-system-expat' in sysconfig.get_config_var("CONFIG_ARGS"):
1486            expat_inc = []
1487            define_macros = []
1488            expat_lib = ['expat']
1489            expat_sources = []
1490            expat_depends = []
1491        else:
1492            expat_inc = [os.path.join(os.getcwd(), srcdir, 'Modules', 'expat')]
1493            define_macros = [
1494                ('HAVE_EXPAT_CONFIG_H', '1'),
1495            ]
1496            expat_lib = []
1497            expat_sources = ['expat/xmlparse.c',
1498                             'expat/xmlrole.c',
1499                             'expat/xmltok.c']
1500            expat_depends = ['expat/ascii.h',
1501                             'expat/asciitab.h',
1502                             'expat/expat.h',
1503                             'expat/expat_config.h',
1504                             'expat/expat_external.h',
1505                             'expat/internal.h',
1506                             'expat/latin1tab.h',
1507                             'expat/utf8tab.h',
1508                             'expat/xmlrole.h',
1509                             'expat/xmltok.h',
1510                             'expat/xmltok_impl.h'
1511                             ]
1512
1513        exts.append(Extension('pyexpat',
1514                              define_macros = define_macros,
1515                              include_dirs = expat_inc,
1516                              libraries = expat_lib,
1517                              sources = ['pyexpat.c'] + expat_sources,
1518                              depends = expat_depends,
1519                              ))
1520
1521        # Fredrik Lundh's cElementTree module.  Note that this also
1522        # uses expat (via the CAPI hook in pyexpat).
1523
1524        if os.path.isfile(os.path.join(srcdir, 'Modules', '_elementtree.c')):
1525            define_macros.append(('USE_PYEXPAT_CAPI', None))
1526            exts.append(Extension('_elementtree',
1527                                  define_macros = define_macros,
1528                                  include_dirs = expat_inc,
1529                                  libraries = expat_lib,
1530                                  sources = ['_elementtree.c'],
1531                                  depends = ['pyexpat.c'] + expat_sources +
1532                                      expat_depends,
1533                                  ))
1534        else:
1535            missing.append('_elementtree')
1536
1537        # Hye-Shik Chang's CJKCodecs modules.
1538        if have_unicode:
1539            exts.append(Extension('_multibytecodec',
1540                                  ['cjkcodecs/multibytecodec.c']))
1541            for loc in ('kr', 'jp', 'cn', 'tw', 'hk', 'iso2022'):
1542                exts.append(Extension('_codecs_%s' % loc,
1543                                      ['cjkcodecs/_codecs_%s.c' % loc]))
1544        else:
1545            missing.append('_multibytecodec')
1546            for loc in ('kr', 'jp', 'cn', 'tw', 'hk', 'iso2022'):
1547                missing.append('_codecs_%s' % loc)
1548
1549        # Dynamic loading module
1550        if sys.maxint == 0x7fffffff:
1551            # This requires sizeof(int) == sizeof(long) == sizeof(char*)
1552            dl_inc = find_file('dlfcn.h', [], inc_dirs)
1553            if (dl_inc is not None) and (host_platform not in ['atheos']):
1554                exts.append( Extension('dl', ['dlmodule.c']) )
1555            else:
1556                missing.append('dl')
1557        else:
1558            missing.append('dl')
1559
1560        # Thomas Heller's _ctypes module
1561        self.detect_ctypes(inc_dirs, lib_dirs)
1562
1563        # Richard Oudkerk's multiprocessing module
1564        if host_platform == 'win32':             # Windows
1565            macros = dict()
1566            libraries = ['ws2_32']
1567
1568        elif host_platform == 'darwin':          # Mac OSX
1569            macros = dict()
1570            libraries = []
1571
1572        elif host_platform == 'cygwin':          # Cygwin
1573            macros = dict()
1574            libraries = []
1575
1576        elif host_platform in ('freebsd4', 'freebsd5', 'freebsd6', 'freebsd7', 'freebsd8'):
1577            # FreeBSD's P1003.1b semaphore support is very experimental
1578            # and has many known problems. (as of June 2008)
1579            macros = dict()
1580            libraries = []
1581
1582        elif host_platform.startswith('openbsd'):
1583            macros = dict()
1584            libraries = []
1585
1586        elif host_platform.startswith('netbsd'):
1587            macros = dict()
1588            libraries = []
1589
1590        else:                                   # Linux and other unices
1591            macros = dict()
1592            libraries = ['rt']
1593
1594        if host_platform == 'win32':
1595            multiprocessing_srcs = [ '_multiprocessing/multiprocessing.c',
1596                                     '_multiprocessing/semaphore.c',
1597                                     '_multiprocessing/pipe_connection.c',
1598                                     '_multiprocessing/socket_connection.c',
1599                                     '_multiprocessing/win32_functions.c'
1600                                   ]
1601
1602        else:
1603            multiprocessing_srcs = [ '_multiprocessing/multiprocessing.c',
1604                                     '_multiprocessing/socket_connection.c'
1605                                   ]
1606            if (sysconfig.get_config_var('HAVE_SEM_OPEN') and not
1607                sysconfig.get_config_var('POSIX_SEMAPHORES_NOT_ENABLED')):
1608                multiprocessing_srcs.append('_multiprocessing/semaphore.c')
1609
1610        if sysconfig.get_config_var('WITH_THREAD'):
1611            exts.append ( Extension('_multiprocessing', multiprocessing_srcs,
1612                                    define_macros=macros.items(),
1613                                    include_dirs=["Modules/_multiprocessing"]))
1614        else:
1615            missing.append('_multiprocessing')
1616
1617        # End multiprocessing
1618
1619
1620        # Platform-specific libraries
1621        if host_platform == 'linux2':
1622            # Linux-specific modules
1623            exts.append( Extension('linuxaudiodev', ['linuxaudiodev.c']) )
1624        else:
1625            missing.append('linuxaudiodev')
1626
1627        if (host_platform in ('linux2', 'freebsd4', 'freebsd5', 'freebsd6',
1628                        'freebsd7', 'freebsd8')
1629            or host_platform.startswith("gnukfreebsd")):
1630            exts.append( Extension('ossaudiodev', ['ossaudiodev.c']) )
1631        else:
1632            missing.append('ossaudiodev')
1633
1634        if host_platform == 'sunos5':
1635            # SunOS specific modules
1636            exts.append( Extension('sunaudiodev', ['sunaudiodev.c']) )
1637        else:
1638            missing.append('sunaudiodev')
1639
1640        if host_platform == 'darwin':
1641            # _scproxy
1642            exts.append(Extension("_scproxy", [os.path.join(srcdir, "Mac/Modules/_scproxy.c")],
1643                extra_link_args= [
1644                    '-framework', 'SystemConfiguration',
1645                    '-framework', 'CoreFoundation'
1646                ]))
1647
1648
1649        if host_platform == 'darwin' and ("--disable-toolbox-glue" not in
1650                sysconfig.get_config_var("CONFIG_ARGS")):
1651
1652            if int(os.uname()[2].split('.')[0]) >= 8:
1653                # We're on Mac OS X 10.4 or later, the compiler should
1654                # support '-Wno-deprecated-declarations'. This will
1655                # suppress deprecation warnings for the Carbon extensions,
1656                # these extensions wrap the Carbon APIs and even those
1657                # parts that are deprecated.
1658                carbon_extra_compile_args = ['-Wno-deprecated-declarations']
1659            else:
1660                carbon_extra_compile_args = []
1661
1662            # Mac OS X specific modules.
1663            def macSrcExists(name1, name2=''):
1664                if not name1:
1665                    return None
1666                names = (name1,)
1667                if name2:
1668                    names = (name1, name2)
1669                path = os.path.join(srcdir, 'Mac', 'Modules', *names)
1670                return os.path.exists(path)
1671
1672            def addMacExtension(name, kwds, extra_srcs=[]):
1673                dirname = ''
1674                if name[0] == '_':
1675                    dirname = name[1:].lower()
1676                cname = name + '.c'
1677                cmodulename = name + 'module.c'
1678                # Check for NNN.c, NNNmodule.c, _nnn/NNN.c, _nnn/NNNmodule.c
1679                if macSrcExists(cname):
1680                    srcs = [cname]
1681                elif macSrcExists(cmodulename):
1682                    srcs = [cmodulename]
1683                elif macSrcExists(dirname, cname):
1684                    # XXX(nnorwitz): If all the names ended with module, we
1685                    # wouldn't need this condition.  ibcarbon is the only one.
1686                    srcs = [os.path.join(dirname, cname)]
1687                elif macSrcExists(dirname, cmodulename):
1688                    srcs = [os.path.join(dirname, cmodulename)]
1689                else:
1690                    raise RuntimeError("%s not found" % name)
1691
1692                # Here's the whole point:  add the extension with sources
1693                exts.append(Extension(name, srcs + extra_srcs, **kwds))
1694
1695            # Core Foundation
1696            core_kwds = {'extra_compile_args': carbon_extra_compile_args,
1697                         'extra_link_args': ['-framework', 'CoreFoundation'],
1698                        }
1699            addMacExtension('_CF', core_kwds, ['cf/pycfbridge.c'])
1700            addMacExtension('autoGIL', core_kwds)
1701
1702
1703
1704            # Carbon
1705            carbon_kwds = {'extra_compile_args': carbon_extra_compile_args,
1706                           'extra_link_args': ['-framework', 'Carbon'],
1707                          }
1708            CARBON_EXTS = ['ColorPicker', 'gestalt', 'MacOS', 'Nav',
1709                           'OSATerminology', 'icglue',
1710                           # All these are in subdirs
1711                           '_AE', '_AH', '_App', '_CarbonEvt', '_Cm', '_Ctl',
1712                           '_Dlg', '_Drag', '_Evt', '_File', '_Folder', '_Fm',
1713                           '_Help', '_Icn', '_IBCarbon', '_List',
1714                           '_Menu', '_Mlte', '_OSA', '_Res', '_Qd', '_Qdoffs',
1715                           '_Scrap', '_Snd', '_TE',
1716                          ]
1717            for name in CARBON_EXTS:
1718                addMacExtension(name, carbon_kwds)
1719
1720            # Workaround for a bug in the version of gcc shipped with Xcode 3.
1721            # The _Win extension should build just like the other Carbon extensions, but
1722            # this actually results in a hard crash of the linker.
1723            #
1724            if '-arch ppc64' in cflags and '-arch ppc' in cflags:
1725                win_kwds = {'extra_compile_args': carbon_extra_compile_args + ['-arch', 'i386', '-arch', 'ppc'],
1726                               'extra_link_args': ['-framework', 'Carbon', '-arch', 'i386', '-arch', 'ppc'],
1727                           }
1728                addMacExtension('_Win', win_kwds)
1729            else:
1730                addMacExtension('_Win', carbon_kwds)
1731
1732
1733            # Application Services & QuickTime
1734            app_kwds = {'extra_compile_args': carbon_extra_compile_args,
1735                        'extra_link_args': ['-framework','ApplicationServices'],
1736                       }
1737            addMacExtension('_Launch', app_kwds)
1738            addMacExtension('_CG', app_kwds)
1739
1740            exts.append( Extension('_Qt', ['qt/_Qtmodule.c'],
1741                        extra_compile_args=carbon_extra_compile_args,
1742                        extra_link_args=['-framework', 'QuickTime',
1743                                     '-framework', 'Carbon']) )
1744
1745
1746        self.extensions.extend(exts)
1747
1748        # Call the method for detecting whether _tkinter can be compiled
1749        self.detect_tkinter(inc_dirs, lib_dirs)
1750
1751        if '_tkinter' not in [e.name for e in self.extensions]:
1752            missing.append('_tkinter')
1753
1754##         # Uncomment these lines if you want to play with xxmodule.c
1755##         ext = Extension('xx', ['xxmodule.c'])
1756##         self.extensions.append(ext)
1757
1758        return missing
1759
1760    def detect_tkinter_explicitly(self):
1761        # Build _tkinter using explicit locations for Tcl/Tk.
1762        #
1763        # This is enabled when both arguments are given to ./configure:
1764        #
1765        #     --with-tcltk-includes="-I/path/to/tclincludes \
1766        #                            -I/path/to/tkincludes"
1767        #     --with-tcltk-libs="-L/path/to/tcllibs -ltclm.n \
1768        #                        -L/path/to/tklibs -ltkm.n"
1769        #
1770        # These values can also be specified or overridden via make:
1771        #    make TCLTK_INCLUDES="..." TCLTK_LIBS="..."
1772        #
1773        # This can be useful for building and testing tkinter with multiple
1774        # versions of Tcl/Tk.  Note that a build of Tk depends on a particular
1775        # build of Tcl so you need to specify both arguments and use care when
1776        # overriding.
1777
1778        # The _TCLTK variables are created in the Makefile sharedmods target.
1779        tcltk_includes = os.environ.get('_TCLTK_INCLUDES')
1780        tcltk_libs = os.environ.get('_TCLTK_LIBS')
1781        if not (tcltk_includes and tcltk_libs):
1782            # Resume default configuration search.
1783            return 0
1784
1785        extra_compile_args = tcltk_includes.split()
1786        extra_link_args = tcltk_libs.split()
1787        ext = Extension('_tkinter', ['_tkinter.c', 'tkappinit.c'],
1788                        define_macros=[('WITH_APPINIT', 1)],
1789                        extra_compile_args = extra_compile_args,
1790                        extra_link_args = extra_link_args,
1791                        )
1792        self.extensions.append(ext)
1793        return 1
1794
1795    def detect_tkinter_darwin(self, inc_dirs, lib_dirs):
1796        # The _tkinter module, using frameworks. Since frameworks are quite
1797        # different the UNIX search logic is not sharable.
1798        from os.path import join, exists
1799        framework_dirs = [
1800            '/Library/Frameworks',
1801            '/System/Library/Frameworks/',
1802            join(os.getenv('HOME'), '/Library/Frameworks')
1803        ]
1804
1805        sysroot = macosx_sdk_root()
1806
1807        # Find the directory that contains the Tcl.framework and Tk.framework
1808        # bundles.
1809        # XXX distutils should support -F!
1810        for F in framework_dirs:
1811            # both Tcl.framework and Tk.framework should be present
1812
1813
1814            for fw in 'Tcl', 'Tk':
1815                if is_macosx_sdk_path(F):
1816                    if not exists(join(sysroot, F[1:], fw + '.framework')):
1817                        break
1818                else:
1819                    if not exists(join(F, fw + '.framework')):
1820                        break
1821            else:
1822                # ok, F is now directory with both frameworks. Continure
1823                # building
1824                break
1825        else:
1826            # Tk and Tcl frameworks not found. Normal "unix" tkinter search
1827            # will now resume.
1828            return 0
1829
1830        # For 8.4a2, we must add -I options that point inside the Tcl and Tk
1831        # frameworks. In later release we should hopefully be able to pass
1832        # the -F option to gcc, which specifies a framework lookup path.
1833        #
1834        include_dirs = [
1835            join(F, fw + '.framework', H)
1836            for fw in 'Tcl', 'Tk'
1837            for H in 'Headers', 'Versions/Current/PrivateHeaders'
1838        ]
1839
1840        # For 8.4a2, the X11 headers are not included. Rather than include a
1841        # complicated search, this is a hard-coded path. It could bail out
1842        # if X11 libs are not found...
1843        include_dirs.append('/usr/X11R6/include')
1844        frameworks = ['-framework', 'Tcl', '-framework', 'Tk']
1845
1846        # All existing framework builds of Tcl/Tk don't support 64-bit
1847        # architectures.
1848        cflags = sysconfig.get_config_vars('CFLAGS')[0]
1849        archs = re.findall('-arch\s+(\w+)', cflags)
1850
1851        if is_macosx_sdk_path(F):
1852            fp = os.popen("file %s/Tk.framework/Tk | grep 'for architecture'"%(os.path.join(sysroot, F[1:]),))
1853        else:
1854            fp = os.popen("file %s/Tk.framework/Tk | grep 'for architecture'"%(F,))
1855
1856        detected_archs = []
1857        for ln in fp:
1858            a = ln.split()[-1]
1859            if a in archs:
1860                detected_archs.append(ln.split()[-1])
1861        fp.close()
1862
1863        for a in detected_archs:
1864            frameworks.append('-arch')
1865            frameworks.append(a)
1866
1867        ext = Extension('_tkinter', ['_tkinter.c', 'tkappinit.c'],
1868                        define_macros=[('WITH_APPINIT', 1)],
1869                        include_dirs = include_dirs,
1870                        libraries = [],
1871                        extra_compile_args = frameworks[2:],
1872                        extra_link_args = frameworks,
1873                        )
1874        self.extensions.append(ext)
1875        return 1
1876
1877    def detect_tkinter(self, inc_dirs, lib_dirs):
1878        # The _tkinter module.
1879
1880        # Check whether --with-tcltk-includes and --with-tcltk-libs were
1881        # configured or passed into the make target.  If so, use these values
1882        # to build tkinter and bypass the searches for Tcl and TK in standard
1883        # locations.
1884        if self.detect_tkinter_explicitly():
1885            return
1886
1887        # Rather than complicate the code below, detecting and building
1888        # AquaTk is a separate method. Only one Tkinter will be built on
1889        # Darwin - either AquaTk, if it is found, or X11 based Tk.
1890        if (host_platform == 'darwin' and
1891            self.detect_tkinter_darwin(inc_dirs, lib_dirs)):
1892            return
1893
1894        # Assume we haven't found any of the libraries or include files
1895        # The versions with dots are used on Unix, and the versions without
1896        # dots on Windows, for detection by cygwin.
1897        tcllib = tklib = tcl_includes = tk_includes = None
1898        for version in ['8.6', '86', '8.5', '85', '8.4', '84', '8.3', '83',
1899                        '8.2', '82', '8.1', '81', '8.0', '80']:
1900            tklib = self.compiler.find_library_file(lib_dirs,
1901                                                        'tk' + version)
1902            tcllib = self.compiler.find_library_file(lib_dirs,
1903                                                         'tcl' + version)
1904            if tklib and tcllib:
1905                # Exit the loop when we've found the Tcl/Tk libraries
1906                break
1907
1908        # Now check for the header files
1909        if tklib and tcllib:
1910            # Check for the include files on Debian and {Free,Open}BSD, where
1911            # they're put in /usr/include/{tcl,tk}X.Y
1912            dotversion = version
1913            if '.' not in dotversion and "bsd" in host_platform.lower():
1914                # OpenBSD and FreeBSD use Tcl/Tk library names like libtcl83.a,
1915                # but the include subdirs are named like .../include/tcl8.3.
1916                dotversion = dotversion[:-1] + '.' + dotversion[-1]
1917            tcl_include_sub = []
1918            tk_include_sub = []
1919            for dir in inc_dirs:
1920                tcl_include_sub += [dir + os.sep + "tcl" + dotversion]
1921                tk_include_sub += [dir + os.sep + "tk" + dotversion]
1922            tk_include_sub += tcl_include_sub
1923            tcl_includes = find_file('tcl.h', inc_dirs, tcl_include_sub)
1924            tk_includes = find_file('tk.h', inc_dirs, tk_include_sub)
1925
1926        if (tcllib is None or tklib is None or
1927            tcl_includes is None or tk_includes is None):
1928            self.announce("INFO: Can't locate Tcl/Tk libs and/or headers", 2)
1929            return
1930
1931        # OK... everything seems to be present for Tcl/Tk.
1932
1933        include_dirs = [] ; libs = [] ; defs = [] ; added_lib_dirs = []
1934        for dir in tcl_includes + tk_includes:
1935            if dir not in include_dirs:
1936                include_dirs.append(dir)
1937
1938        # Check for various platform-specific directories
1939        if host_platform == 'sunos5':
1940            include_dirs.append('/usr/openwin/include')
1941            added_lib_dirs.append('/usr/openwin/lib')
1942        elif os.path.exists('/usr/X11R6/include'):
1943            include_dirs.append('/usr/X11R6/include')
1944            added_lib_dirs.append('/usr/X11R6/lib64')
1945            added_lib_dirs.append('/usr/X11R6/lib')
1946        elif os.path.exists('/usr/X11R5/include'):
1947            include_dirs.append('/usr/X11R5/include')
1948            added_lib_dirs.append('/usr/X11R5/lib')
1949        else:
1950            # Assume default location for X11
1951            include_dirs.append('/usr/X11/include')
1952            added_lib_dirs.append('/usr/X11/lib')
1953
1954        # If Cygwin, then verify that X is installed before proceeding
1955        if host_platform == 'cygwin':
1956            x11_inc = find_file('X11/Xlib.h', [], include_dirs)
1957            if x11_inc is None:
1958                return
1959
1960        # Check for BLT extension
1961        if self.compiler.find_library_file(lib_dirs + added_lib_dirs,
1962                                               'BLT8.0'):
1963            defs.append( ('WITH_BLT', 1) )
1964            libs.append('BLT8.0')
1965        elif self.compiler.find_library_file(lib_dirs + added_lib_dirs,
1966                                                'BLT'):
1967            defs.append( ('WITH_BLT', 1) )
1968            libs.append('BLT')
1969
1970        # Add the Tcl/Tk libraries
1971        libs.append('tk'+ version)
1972        libs.append('tcl'+ version)
1973
1974        if host_platform in ['aix3', 'aix4']:
1975            libs.append('ld')
1976
1977        # Finally, link with the X11 libraries (not appropriate on cygwin)
1978        if host_platform != "cygwin":
1979            libs.append('X11')
1980
1981        ext = Extension('_tkinter', ['_tkinter.c', 'tkappinit.c'],
1982                        define_macros=[('WITH_APPINIT', 1)] + defs,
1983                        include_dirs = include_dirs,
1984                        libraries = libs,
1985                        library_dirs = added_lib_dirs,
1986                        )
1987        self.extensions.append(ext)
1988
1989        # XXX handle these, but how to detect?
1990        # *** Uncomment and edit for PIL (TkImaging) extension only:
1991        #       -DWITH_PIL -I../Extensions/Imaging/libImaging  tkImaging.c \
1992        # *** Uncomment and edit for TOGL extension only:
1993        #       -DWITH_TOGL togl.c \
1994        # *** Uncomment these for TOGL extension only:
1995        #       -lGL -lGLU -lXext -lXmu \
1996
1997    def configure_ctypes_darwin(self, ext):
1998        # Darwin (OS X) uses preconfigured files, in
1999        # the Modules/_ctypes/libffi_osx directory.
2000        srcdir = sysconfig.get_config_var('srcdir')
2001        ffi_srcdir = os.path.abspath(os.path.join(srcdir, 'Modules',
2002                                                  '_ctypes', 'libffi_osx'))
2003        sources = [os.path.join(ffi_srcdir, p)
2004                   for p in ['ffi.c',
2005                             'x86/darwin64.S',
2006                             'x86/x86-darwin.S',
2007                             'x86/x86-ffi_darwin.c',
2008                             'x86/x86-ffi64.c',
2009                             'powerpc/ppc-darwin.S',
2010                             'powerpc/ppc-darwin_closure.S',
2011                             'powerpc/ppc-ffi_darwin.c',
2012                             'powerpc/ppc64-darwin_closure.S',
2013                             ]]
2014
2015        # Add .S (preprocessed assembly) to C compiler source extensions.
2016        self.compiler.src_extensions.append('.S')
2017
2018        include_dirs = [os.path.join(ffi_srcdir, 'include'),
2019                        os.path.join(ffi_srcdir, 'powerpc')]
2020        ext.include_dirs.extend(include_dirs)
2021        ext.sources.extend(sources)
2022        return True
2023
2024    def configure_ctypes(self, ext):
2025        if not self.use_system_libffi:
2026            if host_platform == 'darwin':
2027                return self.configure_ctypes_darwin(ext)
2028
2029            srcdir = sysconfig.get_config_var('srcdir')
2030            ffi_builddir = os.path.join(self.build_temp, 'libffi')
2031            ffi_srcdir = os.path.abspath(os.path.join(srcdir, 'Modules',
2032                                         '_ctypes', 'libffi'))
2033            ffi_configfile = os.path.join(ffi_builddir, 'fficonfig.py')
2034
2035            from distutils.dep_util import newer_group
2036
2037            config_sources = [os.path.join(ffi_srcdir, fname)
2038                              for fname in os.listdir(ffi_srcdir)
2039                              if os.path.isfile(os.path.join(ffi_srcdir, fname))]
2040            if self.force or newer_group(config_sources,
2041                                         ffi_configfile):
2042                from distutils.dir_util import mkpath
2043                mkpath(ffi_builddir)
2044                config_args = [arg for arg in sysconfig.get_config_var("CONFIG_ARGS").split()
2045                               if (('--host=' in arg) or ('--build=' in arg))]
2046                if not self.verbose:
2047                    config_args.append("-q")
2048
2049                # Pass empty CFLAGS because we'll just append the resulting
2050                # CFLAGS to Python's; -g or -O2 is to be avoided.
2051                cmd = "cd %s && env CFLAGS='' '%s/configure' %s" \
2052                      % (ffi_builddir, ffi_srcdir, " ".join(config_args))
2053
2054                res = os.system(cmd)
2055                if res or not os.path.exists(ffi_configfile):
2056                    print "Failed to configure _ctypes module"
2057                    return False
2058
2059            fficonfig = {}
2060            with open(ffi_configfile) as f:
2061                exec f in fficonfig
2062
2063            # Add .S (preprocessed assembly) to C compiler source extensions.
2064            self.compiler.src_extensions.append('.S')
2065
2066            include_dirs = [os.path.join(ffi_builddir, 'include'),
2067                            ffi_builddir,
2068                            os.path.join(ffi_srcdir, 'src')]
2069            extra_compile_args = fficonfig['ffi_cflags'].split()
2070
2071            ext.sources.extend(os.path.join(ffi_srcdir, f) for f in
2072                               fficonfig['ffi_sources'])
2073            ext.include_dirs.extend(include_dirs)
2074            ext.extra_compile_args.extend(extra_compile_args)
2075        return True
2076
2077    def detect_ctypes(self, inc_dirs, lib_dirs):
2078        self.use_system_libffi = False
2079        include_dirs = []
2080        extra_compile_args = []
2081        extra_link_args = []
2082        sources = ['_ctypes/_ctypes.c',
2083                   '_ctypes/callbacks.c',
2084                   '_ctypes/callproc.c',
2085                   '_ctypes/stgdict.c',
2086                   '_ctypes/cfield.c']
2087        depends = ['_ctypes/ctypes.h']
2088
2089        if host_platform == 'darwin':
2090            sources.append('_ctypes/malloc_closure.c')
2091            sources.append('_ctypes/darwin/dlfcn_simple.c')
2092            extra_compile_args.append('-DMACOSX')
2093            include_dirs.append('_ctypes/darwin')
2094# XXX Is this still needed?
2095##            extra_link_args.extend(['-read_only_relocs', 'warning'])
2096
2097        elif host_platform == 'sunos5':
2098            # XXX This shouldn't be necessary; it appears that some
2099            # of the assembler code is non-PIC (i.e. it has relocations
2100            # when it shouldn't. The proper fix would be to rewrite
2101            # the assembler code to be PIC.
2102            # This only works with GCC; the Sun compiler likely refuses
2103            # this option. If you want to compile ctypes with the Sun
2104            # compiler, please research a proper solution, instead of
2105            # finding some -z option for the Sun compiler.
2106            extra_link_args.append('-mimpure-text')
2107
2108        elif host_platform.startswith('hp-ux'):
2109            extra_link_args.append('-fPIC')
2110
2111        ext = Extension('_ctypes',
2112                        include_dirs=include_dirs,
2113                        extra_compile_args=extra_compile_args,
2114                        extra_link_args=extra_link_args,
2115                        libraries=[],
2116                        sources=sources,
2117                        depends=depends)
2118        ext_test = Extension('_ctypes_test',
2119                             sources=['_ctypes/_ctypes_test.c'])
2120        self.extensions.extend([ext, ext_test])
2121
2122        if not '--with-system-ffi' in sysconfig.get_config_var("CONFIG_ARGS"):
2123            return
2124
2125        if host_platform == 'darwin':
2126            # OS X 10.5 comes with libffi.dylib; the include files are
2127            # in /usr/include/ffi
2128            inc_dirs.append('/usr/include/ffi')
2129
2130        ffi_inc = [sysconfig.get_config_var("LIBFFI_INCLUDEDIR")]
2131        if not ffi_inc or ffi_inc[0] == '':
2132            ffi_inc = find_file('ffi.h', [], inc_dirs)
2133        if ffi_inc is not None:
2134            ffi_h = ffi_inc[0] + '/ffi.h'
2135            with open(ffi_h) as f:
2136                for line in f:
2137                    line = line.strip()
2138                    if line.startswith(('#define LIBFFI_H',
2139                                        '#define ffi_wrapper_h')):
2140                        break
2141                else:
2142                    ffi_inc = None
2143                    print('Header file {} does not define LIBFFI_H or '
2144                          'ffi_wrapper_h'.format(ffi_h))
2145        ffi_lib = None
2146        if ffi_inc is not None:
2147            for lib_name in ('ffi_convenience', 'ffi_pic', 'ffi'):
2148                if (self.compiler.find_library_file(lib_dirs, lib_name)):
2149                    ffi_lib = lib_name
2150                    break
2151
2152        if ffi_inc and ffi_lib:
2153            ext.include_dirs.extend(ffi_inc)
2154            ext.libraries.append(ffi_lib)
2155            self.use_system_libffi = True
2156
2157
2158class PyBuildInstall(install):
2159    # Suppress the warning about installation into the lib_dynload
2160    # directory, which is not in sys.path when running Python during
2161    # installation:
2162    def initialize_options (self):
2163        install.initialize_options(self)
2164        self.warn_dir=0
2165
2166class PyBuildInstallLib(install_lib):
2167    # Do exactly what install_lib does but make sure correct access modes get
2168    # set on installed directories and files. All installed files with get
2169    # mode 644 unless they are a shared library in which case they will get
2170    # mode 755. All installed directories will get mode 755.
2171
2172    so_ext = sysconfig.get_config_var("SO")
2173
2174    def install(self):
2175        outfiles = install_lib.install(self)
2176        self.set_file_modes(outfiles, 0644, 0755)
2177        self.set_dir_modes(self.install_dir, 0755)
2178        return outfiles
2179
2180    def set_file_modes(self, files, defaultMode, sharedLibMode):
2181        if not self.is_chmod_supported(): return
2182        if not files: return
2183
2184        for filename in files:
2185            if os.path.islink(filename): continue
2186            mode = defaultMode
2187            if filename.endswith(self.so_ext): mode = sharedLibMode
2188            log.info("changing mode of %s to %o", filename, mode)
2189            if not self.dry_run: os.chmod(filename, mode)
2190
2191    def set_dir_modes(self, dirname, mode):
2192        if not self.is_chmod_supported(): return
2193        os.path.walk(dirname, self.set_dir_modes_visitor, mode)
2194
2195    def set_dir_modes_visitor(self, mode, dirname, names):
2196        if os.path.islink(dirname): return
2197        log.info("changing mode of %s to %o", dirname, mode)
2198        if not self.dry_run: os.chmod(dirname, mode)
2199
2200    def is_chmod_supported(self):
2201        return hasattr(os, 'chmod')
2202
2203SUMMARY = """
2204Python is an interpreted, interactive, object-oriented programming
2205language. It is often compared to Tcl, Perl, Scheme or Java.
2206
2207Python combines remarkable power with very clear syntax. It has
2208modules, classes, exceptions, very high level dynamic data types, and
2209dynamic typing. There are interfaces to many system calls and
2210libraries, as well as to various windowing systems (X11, Motif, Tk,
2211Mac, MFC). New built-in modules are easily written in C or C++. Python
2212is also usable as an extension language for applications that need a
2213programmable interface.
2214
2215The Python implementation is portable: it runs on many brands of UNIX,
2216on Windows, DOS, OS/2, Mac, Amiga... If your favorite system isn't
2217listed here, it may still be supported, if there's a C compiler for
2218it. Ask around on comp.lang.python -- or just try compiling Python
2219yourself.
2220"""
2221
2222CLASSIFIERS = """
2223Development Status :: 6 - Mature
2224License :: OSI Approved :: Python Software Foundation License
2225Natural Language :: English
2226Programming Language :: C
2227Programming Language :: Python
2228Topic :: Software Development
2229"""
2230
2231def main():
2232    # turn off warnings when deprecated modules are imported
2233    import warnings
2234    warnings.filterwarnings("ignore",category=DeprecationWarning)
2235    setup(# PyPI Metadata (PEP 301)
2236          name = "Python",
2237          version = sys.version.split()[0],
2238          url = "http://www.python.org/%s" % sys.version[:3],
2239          maintainer = "Guido van Rossum and the Python community",
2240          maintainer_email = "python-dev@python.org",
2241          description = "A high-level object-oriented programming language",
2242          long_description = SUMMARY.strip(),
2243          license = "PSF license",
2244          classifiers = filter(None, CLASSIFIERS.split("\n")),
2245          platforms = ["Many"],
2246
2247          # Build info
2248          cmdclass = {'build_ext':PyBuildExt, 'install':PyBuildInstall,
2249                      'install_lib':PyBuildInstallLib},
2250          # The struct module is defined here, because build_ext won't be
2251          # called unless there's at least one extension module defined.
2252          ext_modules=[Extension('_struct', ['_struct.c'])],
2253
2254          # Scripts to install
2255          scripts = ['Tools/scripts/pydoc', 'Tools/scripts/idle',
2256                     'Tools/scripts/2to3',
2257                     'Lib/smtpd.py']
2258        )
2259
2260# --install-platlib
2261if __name__ == '__main__':
2262    main()
2263