def build_extensions(self): # Detect which modules should be compiled self.detect_modules() # Remove modules that are present on the disabled list self.extensions = [ ext for ext in self.extensions if ext.name not in disabled_module_list ] # Fix up the autodetected modules, prefixing all the source files # with Modules/ and adding Python's include directory to the path. (srcdir, ) = sysconfig.get_config_vars('srcdir') # Figure out the location of the source code for extension modules moddir = os.path.join(os.getcwd(), srcdir, 'Modules') moddir = os.path.normpath(moddir) srcdir, tail = os.path.split(moddir) srcdir = os.path.normpath(srcdir) moddir = os.path.normpath(moddir) # Fix up the paths for scripts, too self.distribution.scripts = [ os.path.join(srcdir, filename) for filename in self.distribution.scripts ] for ext in self.extensions[:]: ext.sources = [ os.path.join(moddir, filename) for filename in ext.sources ] ext.include_dirs.append('.') # to get config.h ext.include_dirs.append(os.path.join(srcdir, './Include')) # If a module has already been built statically, # don't build it here if ext.name in sys.builtin_module_names: self.extensions.remove(ext) # Parse Modules/Setup to figure out which modules are turned # on in the file. input = text_file.TextFile('Modules/Setup', join_lines=1) remove_modules = [] while 1: line = input.readline() if not line: break line = line.split() remove_modules.append(line[0]) input.close() for ext in self.extensions[:]: if ext.name in remove_modules: self.extensions.remove(ext) # When you run "make CC=altcc" or something similar, you really want # those environment variables passed into the setup.py phase. Here's # a small set of useful ones. compiler = os.environ.get('CC') linker_so = os.environ.get('LDSHARED') args = {} # unfortunately, distutils doesn't let us provide separate C and C++ # compilers if compiler is not None: args['compiler_so'] = compiler if linker_so is not None: args['linker_so'] = linker_so + ' -shared' self.compiler.set_executables(**args) build_ext.build_extensions(self)
# Autodetecting setup.py script for building the Python extensions
def build_extensions(self): # Detect which modules should be compiled old_so = self.compiler.shared_lib_extension # Workaround PEP 3149 stuff self.compiler.shared_lib_extension = os.environ.get("SO", ".so") try: missing = self.detect_modules() finally: self.compiler.shared_lib_extension = old_so # Remove modules that are present on the disabled list extensions = [ ext for ext in self.extensions if ext.name not in disabled_module_list ] # move ctypes to the end, it depends on other modules ext_map = dict((ext.name, i) for i, ext in enumerate(extensions)) if "_ctypes" in ext_map: ctypes = extensions.pop(ext_map["_ctypes"]) extensions.append(ctypes) self.extensions = extensions # Fix up the autodetected modules, prefixing all the source files # with Modules/. srcdir = sysconfig.get_config_var('srcdir') if not srcdir: # Maybe running on Windows but not using CYGWIN? raise ValueError("No source directory; cannot proceed.") srcdir = os.path.abspath(srcdir) moddirlist = [os.path.join(srcdir, 'Modules')] # Fix up the paths for scripts, too self.distribution.scripts = [ os.path.join(srcdir, filename) for filename in self.distribution.scripts ] # Python header files headers = [sysconfig.get_config_h_filename()] headers += glob(os.path.join(sysconfig.get_path('include'), "*.h")) for ext in self.extensions[:]: ext.sources = [ find_module_file(filename, moddirlist) for filename in ext.sources ] if ext.depends is not None: ext.depends = [ find_module_file(filename, moddirlist) for filename in ext.depends ] else: ext.depends = [] # re-compile extensions if a header file has been changed ext.depends.extend(headers) # If a module has already been built statically, # don't build it here if ext.name in sys.builtin_module_names: self.extensions.remove(ext) # Parse Modules/Setup to figure out which # modules are turned on in the file. remove_modules = [] for filename in ('Modules/Setup', ): input = text_file.TextFile(filename, join_lines=1) while 1: line = input.readline() if not line: break line = line.split() remove_modules.append(line[0]) input.close() for ext in self.extensions[:]: if ext.name in remove_modules: self.extensions.remove(ext) # When you run "make CC=altcc" or something similar, you really want # those environment variables passed into the setup.py phase. Here's # a small set of useful ones. compiler = os.environ.get('CC') args = {} # unfortunately, distutils doesn't let us provide separate C and C++ # compilers if compiler is not None: (ccshared, cppflags, cflags) = \ sysconfig.get_config_vars('CCSHARED', 'CPPFLAGS', 'CFLAGS') cppflags = ' '.join( [f for f in cppflags.split() if not f.startswith('-I')]) args[ 'compiler_so'] = compiler + ' ' + ccshared + ' ' + cppflags + ' ' + cflags self.compiler.set_executables(**args) build_ext.build_extensions(self) longest = max([len(e.name) for e in self.extensions]) if self.failed: longest = max(longest, max([len(name) for name in self.failed])) def print_three_column(lst): lst.sort(key=str.lower) # guarantee zip() doesn't drop anything while len(lst) % 3: lst.append("") for e, f, g in zip(lst[::3], lst[1::3], lst[2::3]): print("%-*s %-*s %-*s" % (longest, e, longest, f, longest, g)) if missing: print() print("Python build finished, but the necessary bits to build " "these modules were not found:") print_three_column(missing) print("To find the necessary bits, look in setup.py in" " detect_modules() for the module's name.") print() if self.failed: failed = self.failed[:] print() print("Failed to build these modules:") print_three_column(failed) print()