build_ext.py (18893B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\carbon\common\stdlib\distutils\command\build_ext.py 2 __revision__ = '$Id: build_ext.py 87602 2011-01-01 04:24:26Z richard.tew $' 3 import sys, os, string, re 4 from types import * 5 from site import USER_BASE, USER_SITE 6 from distutils.core import Command 7 from distutils.errors import * 8 from distutils.sysconfig import customize_compiler, get_python_version 9 from distutils.dep_util import newer_group 10 from distutils.extension import Extension 11 from distutils.util import get_platform 12 from distutils import log 13 if os.name == 'nt': 14 from distutils.msvccompiler import get_build_version 15 MSVC_VERSION = int(get_build_version()) 16 extension_name_re = re.compile('^[a-zA-Z_][a-zA-Z_0-9]*(\\.[a-zA-Z_][a-zA-Z_0-9]*)*$') 17 18 def show_compilers(): 19 from distutils.ccompiler import show_compilers 20 show_compilers() 21 22 23 class build_ext(Command): 24 description = 'build C/C++ extensions (compile/link to build directory)' 25 sep_by = " (separated by '%s')" % os.pathsep 26 user_options = [('build-lib=', 'b', 'directory for compiled extension modules'), 27 ('build-temp=', 't', 'directory for temporary files (build by-products)'), 28 ('plat-name=', 'p', 'platform name to cross-compile for, if supported (default: %s)' % get_platform()), 29 ('inplace', 'i', 'ignore build-lib and put compiled extensions into the source ' + 'directory alongside your pure Python modules'), 30 ('include-dirs=', 'I', 'list of directories to search for header files' + sep_by), 31 ('define=', 'D', 'C preprocessor macros to define'), 32 ('undef=', 'U', 'C preprocessor macros to undefine'), 33 ('libraries=', 'l', 'external C libraries to link with'), 34 ('library-dirs=', 'L', 'directories to search for external C libraries' + sep_by), 35 ('rpath=', 'R', 'directories to search for shared C libraries at runtime'), 36 ('link-objects=', 'O', 'extra explicit link objects to include in the link'), 37 ('debug', 'g', 'compile/link with debugging information'), 38 ('force', 'f', 'forcibly build everything (ignore file timestamps)'), 39 ('compiler=', 'c', 'specify the compiler type'), 40 ('swig-cpp', None, 'make SWIG create C++ files (default is C)'), 41 ('swig-opts=', None, 'list of SWIG command line options'), 42 ('swig=', None, 'path to the SWIG executable'), 43 ('user', None, 'add user include, library and rpath')] 44 boolean_options = ['inplace', 45 'debug', 46 'force', 47 'swig-cpp', 48 'user'] 49 help_options = [('help-compiler', 50 None, 51 'list available compilers', 52 show_compilers)] 53 54 def initialize_options(self): 55 self.extensions = None 56 self.build_lib = None 57 self.plat_name = None 58 self.build_temp = None 59 self.inplace = 0 60 self.package = None 61 self.include_dirs = None 62 self.define = None 63 self.undef = None 64 self.libraries = None 65 self.library_dirs = None 66 self.rpath = None 67 self.link_objects = None 68 self.debug = None 69 self.force = None 70 self.compiler = None 71 self.swig = None 72 self.swig_cpp = None 73 self.swig_opts = None 74 self.user = None 75 76 def finalize_options(self): 77 from distutils import sysconfig 78 self.set_undefined_options('build', ('build_lib', 'build_lib'), ('build_temp', 'build_temp'), ('compiler', 'compiler'), ('debug', 'debug'), ('force', 'force'), ('plat_name', 'plat_name')) 79 if self.package is None: 80 self.package = self.distribution.ext_package 81 self.extensions = self.distribution.ext_modules 82 py_include = sysconfig.get_python_inc() 83 plat_py_include = sysconfig.get_python_inc(plat_specific=1) 84 if self.include_dirs is None: 85 self.include_dirs = self.distribution.include_dirs or [] 86 if isinstance(self.include_dirs, str): 87 self.include_dirs = self.include_dirs.split(os.pathsep) 88 self.include_dirs.append(py_include) 89 if plat_py_include != py_include: 90 self.include_dirs.append(plat_py_include) 91 slpy_include = os.path.join(sysconfig.PREFIX, 'Stackless') 92 if os.path.exists(slpy_include): 93 self.include_dirs.append(slpy_include) 94 else: 95 slpy_include = os.path.join(py_include, 'Stackless') 96 if os.path.exists(slpy_include): 97 self.include_dirs.append(slpy_include) 98 if isinstance(self.libraries, str): 99 self.libraries = [self.libraries] 100 if self.libraries is None: 101 self.libraries = [] 102 if self.library_dirs is None: 103 self.library_dirs = [] 104 elif type(self.library_dirs) is StringType: 105 self.library_dirs = string.split(self.library_dirs, os.pathsep) 106 if self.rpath is None: 107 self.rpath = [] 108 elif type(self.rpath) is StringType: 109 self.rpath = string.split(self.rpath, os.pathsep) 110 if os.name == 'nt': 111 self.library_dirs.append(os.path.join(sys.exec_prefix, 'libs')) 112 if self.debug: 113 self.build_temp = os.path.join(self.build_temp, 'Debug') 114 else: 115 self.build_temp = os.path.join(self.build_temp, 'Release') 116 self.include_dirs.append(os.path.join(sys.exec_prefix, 'PC')) 117 if MSVC_VERSION == 9: 118 if self.plat_name == 'win32': 119 suffix = '' 120 else: 121 suffix = self.plat_name[4:] 122 new_lib = os.path.join(sys.exec_prefix, 'PCbuild') 123 if suffix: 124 new_lib = os.path.join(new_lib, suffix) 125 self.library_dirs.append(new_lib) 126 elif MSVC_VERSION == 8: 127 self.library_dirs.append(os.path.join(sys.exec_prefix, 'PC', 'VS8.0', 'win32release')) 128 elif MSVC_VERSION == 7: 129 self.library_dirs.append(os.path.join(sys.exec_prefix, 'PC', 'VS7.1')) 130 else: 131 self.library_dirs.append(os.path.join(sys.exec_prefix, 'PC', 'VC6')) 132 if os.name == 'os2': 133 self.library_dirs.append(os.path.join(sys.exec_prefix, 'Config')) 134 if sys.platform[:6] == 'cygwin' or sys.platform[:6] == 'atheos': 135 if sys.executable.startswith(os.path.join(sys.exec_prefix, 'bin')): 136 self.library_dirs.append(os.path.join(sys.prefix, 'lib', 'python' + get_python_version(), 'config')) 137 else: 138 self.library_dirs.append('.') 139 sysconfig.get_config_var('Py_ENABLE_SHARED') 140 if (sys.platform.startswith('linux') or sys.platform.startswith('gnu') or sys.platform.startswith('sunos')) and sysconfig.get_config_var('Py_ENABLE_SHARED'): 141 if sys.executable.startswith(os.path.join(sys.exec_prefix, 'bin')): 142 self.library_dirs.append(sysconfig.get_config_var('LIBDIR')) 143 else: 144 self.library_dirs.append('.') 145 if self.define: 146 defines = self.define.split(',') 147 self.define = map(lambda symbol: (symbol, '1'), defines) 148 if self.undef: 149 self.undef = self.undef.split(',') 150 if self.swig_opts is None: 151 self.swig_opts = [] 152 else: 153 self.swig_opts = self.swig_opts.split(' ') 154 if self.user: 155 user_include = os.path.join(USER_BASE, 'include') 156 user_lib = os.path.join(USER_BASE, 'lib') 157 if os.path.isdir(user_include): 158 self.include_dirs.append(user_include) 159 if os.path.isdir(user_lib): 160 self.library_dirs.append(user_lib) 161 self.rpath.append(user_lib) 162 163 def run(self): 164 from distutils.ccompiler import new_compiler 165 if not self.extensions: 166 return 167 if self.distribution.has_c_libraries(): 168 build_clib = self.get_finalized_command('build_clib') 169 self.libraries.extend(build_clib.get_library_names() or []) 170 self.library_dirs.append(build_clib.build_clib) 171 self.compiler = new_compiler(compiler=self.compiler, verbose=self.verbose, dry_run=self.dry_run, force=self.force) 172 customize_compiler(self.compiler) 173 if os.name == 'nt' and self.plat_name != get_platform(): 174 self.compiler.initialize(self.plat_name) 175 if self.include_dirs is not None: 176 self.compiler.set_include_dirs(self.include_dirs) 177 if self.define is not None: 178 for name, value in self.define: 179 self.compiler.define_macro(name, value) 180 181 if self.undef is not None: 182 for macro in self.undef: 183 self.compiler.undefine_macro(macro) 184 185 if self.libraries is not None: 186 self.compiler.set_libraries(self.libraries) 187 if self.library_dirs is not None: 188 self.compiler.set_library_dirs(self.library_dirs) 189 if self.rpath is not None: 190 self.compiler.set_runtime_library_dirs(self.rpath) 191 if self.link_objects is not None: 192 self.compiler.set_link_objects(self.link_objects) 193 self.build_extensions() 194 195 def check_extensions_list(self, extensions): 196 if not isinstance(extensions, list): 197 raise DistutilsSetupError, "'ext_modules' option must be a list of Extension instances" 198 for i, ext in enumerate(extensions): 199 if isinstance(ext, Extension): 200 continue 201 if not isinstance(ext, tuple) or len(ext) != 2: 202 raise DistutilsSetupError, "each element of 'ext_modules' option must be an Extension instance or 2-tuple" 203 ext_name, build_info = ext 204 log.warn("old-style (ext_name, build_info) tuple found in ext_modules for extension '%s'-- please convert to Extension instance" % ext_name) 205 if not (isinstance(ext_name, str) and extension_name_re.match(ext_name)): 206 raise DistutilsSetupError, "first element of each tuple in 'ext_modules' must be the extension name (a string)" 207 if not isinstance(build_info, dict): 208 raise DistutilsSetupError, "second element of each tuple in 'ext_modules' must be a dictionary (build info)" 209 ext = Extension(ext_name, build_info['sources']) 210 for key in ('include_dirs', 'library_dirs', 'libraries', 'extra_objects', 'extra_compile_args', 'extra_link_args'): 211 val = build_info.get(key) 212 if val is not None: 213 setattr(ext, key, val) 214 215 ext.runtime_library_dirs = build_info.get('rpath') 216 if 'def_file' in build_info: 217 log.warn("'def_file' element of build info dict no longer supported") 218 macros = build_info.get('macros') 219 if macros: 220 ext.define_macros = [] 221 ext.undef_macros = [] 222 for macro in macros: 223 if not (isinstance(macro, tuple) and len(macro) in (1, 2)): 224 raise DistutilsSetupError, "'macros' element of build info dict must be 1- or 2-tuple" 225 if len(macro) == 1: 226 ext.undef_macros.append(macro[0]) 227 elif len(macro) == 2: 228 ext.define_macros.append(macro) 229 230 extensions[i] = ext 231 232 def get_source_files(self): 233 self.check_extensions_list(self.extensions) 234 filenames = [] 235 for ext in self.extensions: 236 filenames.extend(ext.sources) 237 238 return filenames 239 240 def get_outputs(self): 241 self.check_extensions_list(self.extensions) 242 outputs = [] 243 for ext in self.extensions: 244 outputs.append(self.get_ext_fullpath(ext.name)) 245 246 return outputs 247 248 def build_extensions(self): 249 self.check_extensions_list(self.extensions) 250 for ext in self.extensions: 251 self.build_extension(ext) 252 253 def build_extension(self, ext): 254 sources = ext.sources 255 if sources is None or type(sources) not in (ListType, TupleType): 256 raise DistutilsSetupError, ("in 'ext_modules' option (extension '%s'), " + "'sources' must be present and must be " + 'a list of source filenames') % ext.name 257 sources = list(sources) 258 ext_path = self.get_ext_fullpath(ext.name) 259 depends = sources + ext.depends 260 if not (self.force or newer_group(depends, ext_path, 'newer')): 261 log.debug("skipping '%s' extension (up-to-date)", ext.name) 262 return 263 log.info("building '%s' extension", ext.name) 264 sources = self.swig_sources(sources, ext) 265 extra_args = ext.extra_compile_args or [] 266 macros = ext.define_macros[:] 267 for undef in ext.undef_macros: 268 macros.append((undef,)) 269 270 objects = self.compiler.compile(sources, output_dir=self.build_temp, macros=macros, include_dirs=ext.include_dirs, debug=self.debug, extra_postargs=extra_args, depends=ext.depends) 271 self._built_objects = objects[:] 272 if ext.extra_objects: 273 objects.extend(ext.extra_objects) 274 extra_args = ext.extra_link_args or [] 275 language = ext.language or self.compiler.detect_language(sources) 276 self.compiler.link_shared_object(objects, ext_path, libraries=self.get_libraries(ext), library_dirs=ext.library_dirs, runtime_library_dirs=ext.runtime_library_dirs, extra_postargs=extra_args, export_symbols=self.get_export_symbols(ext), debug=self.debug, build_temp=self.build_temp, target_lang=language) 277 278 def swig_sources(self, sources, extension): 279 new_sources = [] 280 swig_sources = [] 281 swig_targets = {} 282 if self.swig_cpp: 283 log.warn('--swig-cpp is deprecated - use --swig-opts=-c++') 284 if self.swig_cpp or '-c++' in self.swig_opts or '-c++' in extension.swig_opts: 285 target_ext = '.cpp' 286 else: 287 target_ext = '.c' 288 for source in sources: 289 base, ext = os.path.splitext(source) 290 if ext == '.i': 291 new_sources.append(base + '_wrap' + target_ext) 292 swig_sources.append(source) 293 swig_targets[source] = new_sources[-1] 294 else: 295 new_sources.append(source) 296 297 if not swig_sources: 298 return new_sources 299 swig = self.swig or self.find_swig() 300 swig_cmd = [swig, '-python'] 301 swig_cmd.extend(self.swig_opts) 302 if self.swig_cpp: 303 swig_cmd.append('-c++') 304 if not self.swig_opts: 305 for o in extension.swig_opts: 306 swig_cmd.append(o) 307 308 for source in swig_sources: 309 target = swig_targets[source] 310 log.info('swigging %s to %s', source, target) 311 self.spawn(swig_cmd + ['-o', target, source]) 312 313 return new_sources 314 315 def find_swig(self): 316 if os.name == 'posix': 317 return 'swig' 318 if os.name == 'nt': 319 for vers in ('1.3', '1.2', '1.1'): 320 fn = os.path.join('c:\\swig%s' % vers, 'swig.exe') 321 if os.path.isfile(fn): 322 return fn 323 else: 324 return 'swig.exe' 325 326 else: 327 if os.name == 'os2': 328 return 'swig.exe' 329 raise DistutilsPlatformError, "I don't know how to find (much less run) SWIG on platform '%s'" % os.name 330 331 def get_ext_fullpath(self, ext_name): 332 all_dots = string.maketrans('/' + os.sep, '..') 333 ext_name = ext_name.translate(all_dots) 334 fullname = self.get_ext_fullname(ext_name) 335 modpath = fullname.split('.') 336 filename = self.get_ext_filename(ext_name) 337 filename = os.path.split(filename)[-1] 338 if not self.inplace: 339 filename = os.path.join(*(modpath[:-1] + [filename])) 340 return os.path.join(self.build_lib, filename) 341 package = '.'.join(modpath[0:-1]) 342 build_py = self.get_finalized_command('build_py') 343 package_dir = os.path.abspath(build_py.get_package_dir(package)) 344 return os.path.join(package_dir, filename) 345 346 def get_ext_fullname(self, ext_name): 347 if self.package is None: 348 return ext_name 349 else: 350 return self.package + '.' + ext_name 351 352 def get_ext_filename(self, ext_name): 353 from distutils.sysconfig import get_config_var 354 ext_path = string.split(ext_name, '.') 355 if os.name == 'os2': 356 ext_path[len(ext_path) - 1] = ext_path[len(ext_path) - 1][:8] 357 so_ext = get_config_var('SO') 358 if os.name == 'nt' and self.debug: 359 return os.path.join(*ext_path) + '_d' + so_ext 360 return os.path.join(*ext_path) + so_ext 361 362 def get_export_symbols(self, ext): 363 initfunc_name = 'init' + ext.name.split('.')[-1] 364 if initfunc_name not in ext.export_symbols: 365 ext.export_symbols.append(initfunc_name) 366 return ext.export_symbols 367 368 def get_libraries(self, ext): 369 if sys.platform == 'win32': 370 from distutils.msvccompiler import MSVCCompiler 371 if not isinstance(self.compiler, MSVCCompiler): 372 template = 'python%d%d' 373 if self.debug: 374 template = template + '_d' 375 pythonlib = template % (sys.hexversion >> 24, sys.hexversion >> 16 & 255) 376 return ext.libraries + [pythonlib] 377 else: 378 return ext.libraries 379 else: 380 if sys.platform == 'os2emx': 381 template = 'python%d%d' 382 pythonlib = template % (sys.hexversion >> 24, sys.hexversion >> 16 & 255) 383 return ext.libraries + [pythonlib] 384 if sys.platform[:6] == 'cygwin': 385 template = 'python%d.%d' 386 pythonlib = template % (sys.hexversion >> 24, sys.hexversion >> 16 & 255) 387 return ext.libraries + [pythonlib] 388 if sys.platform[:6] == 'atheos': 389 from distutils import sysconfig 390 template = 'python%d.%d' 391 pythonlib = template % (sys.hexversion >> 24, sys.hexversion >> 16 & 255) 392 extra = [] 393 for lib in sysconfig.get_config_var('SHLIBS').split(): 394 if lib.startswith('-l'): 395 extra.append(lib[2:]) 396 else: 397 extra.append(lib) 398 399 return ext.libraries + [pythonlib, 'm'] + extra 400 if sys.platform == 'darwin': 401 return ext.libraries 402 if sys.platform[:3] == 'aix': 403 return ext.libraries 404 from distutils import sysconfig 405 if sysconfig.get_config_var('Py_ENABLE_SHARED'): 406 template = 'python%d.%d' 407 pythonlib = template % (sys.hexversion >> 24, sys.hexversion >> 16 & 255) 408 return ext.libraries + [pythonlib] 409 return ext.libraries