def run(self): # Obviously have to build before we can install if not self.skip_build: self.run_command('build') # Run all sub-commands (at least those that need to be run) for cmd_name in self.get_sub_commands(): self.run_command(cmd_name) if self.path_file: self.create_path_file() # write list of installed files, if requested. if self.record: outputs = self.get_outputs() if self.root: # strip any package prefix root_len = len(self.root) for counter in xrange(len(outputs)): outputs[counter] = outputs[counter][root_len:] outputs = map(_quote_name_when_has_spaces, outputs) self.execute( write_file, (self.record, outputs), "writing list of installed files to '%s'" % self.record) sys_path = map(os.path.normpath, sys.path) sys_path = map(os.path.normcase, sys_path) install_lib = os.path.normcase(os.path.normpath(self.install_lib)) if (self.warn_dir and not (self.path_file and self.install_path_file) and install_lib not in sys_path): log.debug(("modules installed to '%s', which is not in " "Python's module search path (sys.path) -- " "you'll have to change the search path yourself"), self.install_lib)
def swig_sources(self, sources, extension): # Assuming SWIG 1.3.14 or later. See compatibility note in # http://www.swig.org/Doc1.3/Python.html#Python_nn6 new_sources = [] swig_sources = [] swig_targets = {} target_dirs = [] py_files = [] # swig generated .py files target_ext = '.c' typ = None is_cpp = 0 skip_swig = 0 ext_name = extension.name.split('.')[-1] for source in sources: (base, ext) = os.path.splitext(source) if ext == '.i': # SWIG interface file if self.inplace: target_dir = os.path.dirname(base) py_target_dir = self.ext_target_dir else: target_dir = appendpath(self.build_src, os.path.dirname(base)) py_target_dir = target_dir if os.path.isfile(source): name = get_swig_modulename(source) assert name==ext_name[1:],'mismatch of extension names: '\ +source+' provides'\ ' '+`name`+' but expected '+`ext_name[1:]` if typ is None: typ = get_swig_target(source) is_cpp = typ == 'c++' if is_cpp: target_ext = '.cpp' else: assert typ == get_swig_target(source), ` typ ` target_file = os.path.join(target_dir,'%s_wrap%s' \ % (name, target_ext)) else: log.debug(' source %s does not exist: skipping swig\'ing.' \ % (source)) name = ext_name[1:] skip_swig = 1 target_file = _find_swig_target(target_dir, name) if not os.path.isfile(target_file): log.debug(' target %s does not exist:\n '\ 'Assuming %s_wrap.{c,cpp} was generated with '\ '"build_src --inplace" command.' \ % (target_file, name)) target_dir = os.path.dirname(base) target_file = _find_swig_target(target_dir, name) assert os.path.isfile( target_file), ` target_file ` + ' missing' log.debug(' Yes! Using %s as up-to-date target.' \ % (target_file)) target_dirs.append(target_dir) new_sources.append(target_file) py_files.append(os.path.join(py_target_dir, name + '.py')) swig_sources.append(source) swig_targets[source] = new_sources[-1] else: new_sources.append(source) if not swig_sources: return new_sources if skip_swig: return new_sources + py_files map(self.mkpath, target_dirs) swig = self.find_swig() swig_cmd = [swig, "-python"] if is_cpp: swig_cmd.append('-c++') for d in extension.include_dirs: swig_cmd.append('-I' + d) for source in swig_sources: target = swig_targets[source] depends = [source] + extension.depends if self.force or newer_group(depends, target, 'newer'): log.info("%s: %s" % (os.path.basename(swig) \ + (is_cpp and '++' or ''), source)) self.spawn(swig_cmd + self.swigflags \ + ["-o", target, '-outdir', py_target_dir, source]) else: log.debug(" skipping '%s' swig interface (up-to-date)" \ % (source)) return new_sources + py_files
def build_libraries(self, libraries): compiler = self.compiler fcompiler = self.fcompiler for (lib_name, build_info) in libraries: sources = build_info.get('sources') if sources is None or type(sources) not in (ListType, TupleType): raise DistutilsSetupError, \ ("in 'libraries' option (library '%s'), " + "'sources' must be present and must be " + "a list of source filenames") % lib_name sources = list(sources) lib_file = compiler.library_filename(lib_name, output_dir=self.build_clib) depends = sources + build_info.get('depends', []) if not (self.force or newer_group(depends, lib_file, 'newer')): log.debug("skipping '%s' library (up-to-date)", lib_name) continue else: log.info("building '%s' library", lib_name) macros = build_info.get('macros') include_dirs = build_info.get('include_dirs') extra_postargs = build_info.get('extra_compiler_args') or [] c_sources, cxx_sources, f_sources, fmodule_sources \ = filter_sources(sources) if self.compiler.compiler_type == 'msvc': # this hack works around the msvc compiler attributes # problem, msvc uses its own convention :( c_sources += cxx_sources cxx_sources = [] if fmodule_sources: print 'XXX: Fortran 90 module support not implemented or tested' f_sources.extend(fmodule_sources) objects = [] if c_sources: log.info("compiling C sources") objects = compiler.compile(c_sources, output_dir=self.build_temp, macros=macros, include_dirs=include_dirs, debug=self.debug, extra_postargs=extra_postargs) if cxx_sources: log.info("compiling C++ sources") old_compiler = self.compiler.compiler_so[0] self.compiler.compiler_so[0] = self.compiler.compiler_cxx[0] cxx_objects = compiler.compile(cxx_sources, output_dir=self.build_temp, macros=macros, include_dirs=include_dirs, debug=self.debug, extra_postargs=extra_postargs) objects.extend(cxx_objects) self.compiler.compiler_so[0] = old_compiler if f_sources: log.info("compiling Fortran sources") f_objects = fcompiler.compile(f_sources, output_dir=self.build_temp, macros=macros, include_dirs=include_dirs, debug=self.debug, extra_postargs=[]) objects.extend(f_objects) self.compiler.create_static_lib(objects, lib_name, output_dir=self.build_clib, debug=self.debug) return
def f2py_sources(self, sources, extension): new_sources = [] f2py_sources = [] f_sources = [] f2py_targets = {} target_dirs = [] ext_name = extension.name.split('.')[-1] skip_f2py = 0 for source in sources: (base, ext) = os.path.splitext(source) if ext == '.pyf': # F2PY interface file if self.inplace: target_dir = os.path.dirname(base) else: target_dir = appendpath(self.build_src, os.path.dirname(base)) if os.path.isfile(source): name = get_f2py_modulename(source) assert name==ext_name,'mismatch of extension names: '\ +source+' provides'\ ' '+`name`+' but expected '+`ext_name` target_file = os.path.join(target_dir, name + 'module.c') else: log.debug(' source %s does not exist: skipping f2py\'ing.' \ % (source)) name = ext_name skip_f2py = 1 target_file = os.path.join(target_dir, name + 'module.c') if not os.path.isfile(target_file): log.debug(' target %s does not exist:\n '\ 'Assuming %smodule.c was generated with '\ '"build_src --inplace" command.' \ % (target_file, name)) target_dir = os.path.dirname(base) target_file = os.path.join(target_dir, name + 'module.c') assert os.path.isfile( target_file), ` target_file ` + ' missing' log.debug(' Yes! Using %s as up-to-date target.' \ % (target_file)) target_dirs.append(target_dir) f2py_sources.append(source) f2py_targets[source] = target_file new_sources.append(target_file) elif fortran_ext_match(ext): f_sources.append(source) else: new_sources.append(source) if not (f2py_sources or f_sources): return new_sources map(self.mkpath, target_dirs) f2py_options = extension.f2py_options + self.f2pyflags if f2py_sources: assert len(f2py_sources)==1,\ 'only one .pyf file is allowed per extension module but got'\ ' more:'+`f2py_sources` source = f2py_sources[0] target_file = f2py_targets[source] target_dir = os.path.dirname(target_file) or '.' depends = [source] + extension.depends if (self.force or newer_group(depends, target_file,'newer')) \ and not skip_f2py: log.info("f2py: %s" % (source)) import f2py2e f2py2e.run_main(f2py_options + ['--build-dir', target_dir, source]) else: log.debug(" skipping '%s' f2py interface (up-to-date)" % (source)) else: #XXX TODO: --inplace support for sdist command if type(extension) is type(()): name = extension[0] else: name = extension.name target_dir = os.path.join(*([self.build_src]\ +name.split('.')[:-1])) target_file = os.path.join(target_dir, ext_name + 'module.c') new_sources.append(target_file) depends = f_sources + extension.depends if (self.force or newer_group(depends, target_file, 'newer')) \ and not skip_f2py: import f2py2e log.info("f2py:> %s" % (target_file)) self.mkpath(target_dir) f2py2e.run_main(f2py_options + ['--lower', '--build-dir',target_dir]+\ ['-m',ext_name]+f_sources) else: log.debug(" skipping f2py fortran files for '%s' (up-to-date)"\ % (target_file)) assert os.path.isfile(target_file), ` target_file ` + ' missing' target_c = os.path.join(self.build_src, 'fortranobject.c') target_h = os.path.join(self.build_src, 'fortranobject.h') log.info(" adding '%s' to sources." % (target_c)) new_sources.append(target_c) if self.build_src not in extension.include_dirs: log.info(" adding '%s' to include_dirs." \ % (self.build_src)) extension.include_dirs.append(self.build_src) if not skip_f2py: import f2py2e d = os.path.dirname(f2py2e.__file__) source_c = os.path.join(d, 'src', 'fortranobject.c') source_h = os.path.join(d, 'src', 'fortranobject.h') if newer(source_c, target_c) or newer(source_h, target_h): self.mkpath(os.path.dirname(target_c)) self.copy_file(source_c, target_c) self.copy_file(source_h, target_h) else: assert os.path.isfile(target_c), ` target_c ` + ' missing' assert os.path.isfile(target_h), ` target_h ` + ' missing' for name_ext in ['-f2pywrappers.f', '-f2pywrappers2.f90']: filename = os.path.join(target_dir, ext_name + name_ext) if os.path.isfile(filename): log.info(" adding '%s' to sources." % (filename)) f_sources.append(filename) return new_sources + f_sources
def build_extension(self, ext): sources = ext.sources if sources is None or type(sources) not in (ListType, TupleType): raise DistutilsSetupError, \ ("in 'ext_modules' option (extension '%s'), " + "'sources' must be present and must be " + "a list of source filenames") % ext.name sources = list(sources) if not sources: return fullname = self.get_ext_fullname(ext.name) if self.inplace: modpath = string.split(fullname, '.') package = string.join(modpath[0:-1], '.') base = modpath[-1] build_py = self.get_finalized_command('build_py') package_dir = build_py.get_package_dir(package) ext_filename = os.path.join(package_dir, self.get_ext_filename(base)) else: ext_filename = os.path.join(self.build_lib, self.get_ext_filename(fullname)) depends = sources + ext.depends if not (self.force or newer_group(depends, ext_filename, 'newer')): log.debug("skipping '%s' extension (up-to-date)", ext.name) return else: log.info("building '%s' extension", ext.name) extra_args = ext.extra_compile_args or [] macros = ext.define_macros[:] for undef in ext.undef_macros: macros.append((undef, )) c_sources, cxx_sources, f_sources, fmodule_sources = \ filter_sources(ext.sources) if self.compiler.compiler_type == 'msvc': if cxx_sources: # Needed to compile kiva.agg._agg extension. extra_args.append('/Zm1000') # this hack works around the msvc compiler attributes # problem, msvc uses its own convention :( c_sources += cxx_sources cxx_sources = [] if sys.version[:3] >= '2.3': kws = {'depends': ext.depends} else: kws = {} backend = getattr(ext, 'backend', None) if backend is not None: output_dir = os.path.join(self.build_temp, '_' + backend) else: output_dir = self.build_temp c_objects = [] if c_sources: log.info("compiling C sources") c_objects = self.compiler.compile(c_sources, output_dir=output_dir, macros=macros, include_dirs=ext.include_dirs, debug=self.debug, extra_postargs=extra_args, **kws) if cxx_sources: log.info("compiling C++ sources") old_compiler = self.compiler.compiler_so[0] self.compiler.compiler_so[0] = self.compiler.compiler_cxx[0] c_objects += self.compiler.compile(cxx_sources, output_dir=output_dir, macros=macros, include_dirs=ext.include_dirs, debug=self.debug, extra_postargs=extra_args, **kws) self.compiler.compiler_so[0] = old_compiler check_for_f90_modules = not not fmodule_sources if f_sources or fmodule_sources: extra_postargs = [] include_dirs = ext.include_dirs[:] module_dirs = ext.module_dirs[:] #if self.fcompiler.compiler_type=='ibm': macros = [] if check_for_f90_modules: module_build_dir = os.path.join(\ self.build_temp,os.path.dirname(\ self.get_ext_filename(fullname))) self.mkpath(module_build_dir) if self.fcompiler.module_dir_switch is None: existing_modules = glob('*.mod') extra_postargs += self.fcompiler.module_options(\ module_dirs,module_build_dir) f_objects = [] if fmodule_sources: log.info("compiling Fortran 90 module sources") f_objects = self.fcompiler.compile( fmodule_sources, output_dir=self.build_temp, macros=macros, include_dirs=include_dirs, debug=self.debug, extra_postargs=extra_postargs, depends=ext.depends) if check_for_f90_modules \ and self.fcompiler.module_dir_switch is None: for f in glob('*.mod'): if f in existing_modules: continue try: self.move_file(f, module_build_dir) except DistutilsFileError: # already exists in destination os.remove(f) if f_sources: log.info("compiling Fortran sources") f_objects += self.fcompiler.compile( f_sources, output_dir=self.build_temp, macros=macros, include_dirs=include_dirs, debug=self.debug, extra_postargs=extra_postargs, depends=ext.depends) else: f_objects = [] objects = c_objects + f_objects if ext.extra_objects: objects.extend(ext.extra_objects) extra_args = ext.extra_link_args or [] try: old_linker_so_0 = self.compiler.linker_so[0] except: pass use_fortran_linker = getattr(ext, 'language', 'c') in ['f77', 'f90'] c_libraries = [] c_library_dirs = [] if use_fortran_linker or f_sources: use_fortran_linker = 1 elif self.distribution.has_c_libraries(): build_clib = self.get_finalized_command('build_clib') f_libs = [] for (lib_name, build_info) in build_clib.libraries: if has_f_sources(build_info.get('sources', [])): f_libs.append(lib_name) if lib_name in ext.libraries: # XXX: how to determine if c_libraries contain # fortran compiled sources? c_libraries.extend(build_info.get('libraries', [])) c_library_dirs.extend(build_info.get('library_dirs', [])) for l in ext.libraries: if l in f_libs: use_fortran_linker = 1 break # Always use system linker when using MSVC compiler. if self.compiler.compiler_type == 'msvc' and use_fortran_linker: c_libraries.extend(self.fcompiler.libraries) c_library_dirs.extend(self.fcompiler.library_dirs) use_fortran_linker = 0 if use_fortran_linker: if cxx_sources: # XXX: Which linker should be used, Fortran or C++? log.warn('mixing Fortran and C++ is untested') link = self.fcompiler.link_shared_object language = ext.language or self.fcompiler.detect_language( f_sources) else: link = self.compiler.link_shared_object if sys.version[:3] >= '2.3': language = ext.language or self.compiler.detect_language( sources) else: language = ext.language if cxx_sources: self.compiler.linker_so[0] = self.compiler.compiler_cxx[0] if sys.version[:3] >= '2.3': kws = {'target_lang': language} else: kws = {} link(objects, ext_filename, libraries=self.get_libraries(ext) + c_libraries, library_dirs=ext.library_dirs + c_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, **kws) try: self.compiler.linker_so[0] = old_linker_so_0 except: pass return