diff options
author | Travis Oliphant <oliphant@enthought.com> | 2006-01-04 17:26:31 +0000 |
---|---|---|
committer | Travis Oliphant <oliphant@enthought.com> | 2006-01-04 17:26:31 +0000 |
commit | 8e2654541c6eae0f308908f501cccbc86b2f9101 (patch) | |
tree | bfcfe3b282c8fb659832bf86a841ce76852094ad /numpy/distutils/command/build_ext.py | |
parent | ddaed649c23bbd0ad36cdafdfe9cd92397ce69e3 (diff) | |
download | numpy-8e2654541c6eae0f308908f501cccbc86b2f9101.tar.gz |
Moved scipy directory to numpy
Diffstat (limited to 'numpy/distutils/command/build_ext.py')
-rw-r--r-- | numpy/distutils/command/build_ext.py | 349 |
1 files changed, 349 insertions, 0 deletions
diff --git a/numpy/distutils/command/build_ext.py b/numpy/distutils/command/build_ext.py new file mode 100644 index 000000000..7a2318b70 --- /dev/null +++ b/numpy/distutils/command/build_ext.py @@ -0,0 +1,349 @@ +""" Modified version of build_ext that handles fortran source files. +""" + +import os +import string +import sys +from glob import glob +from types import * + +from distutils.dep_util import newer_group, newer +from distutils.command.build_ext import build_ext as old_build_ext + +from scipy.distutils import log +from scipy.distutils.misc_util import filter_sources, has_f_sources, \ + has_cxx_sources, get_ext_source_files, all_strings, \ + get_scipy_include_dirs +from distutils.errors import DistutilsFileError + +class build_ext (old_build_ext): + + description = "build C/C++/F extensions (compile/link to build directory)" + + user_options = old_build_ext.user_options + [ + ('fcompiler=', None, + "specify the Fortran compiler type"), + ] + + def initialize_options(self): + old_build_ext.initialize_options(self) + self.fcompiler = None + return + + def finalize_options(self): + old_build_ext.finalize_options(self) + self.set_undefined_options('config_fc', + ('fcompiler', 'fcompiler')) + return + + def run(self): + if not self.extensions: + return + + # Make sure that extension sources are complete. + for ext in self.extensions: + if not all_strings(ext.sources): + self.run_command('build_src') + + if self.distribution.has_c_libraries(): + build_clib = self.get_finalized_command('build_clib') + self.library_dirs.append(build_clib.build_clib) + else: + build_clib = None + + # Not including C libraries to the list of + # extension libraries automatically to prevent + # bogus linking commands. Extensions must + # explicitly specify the C libraries that they use. + + # Determine if Fortran compiler is needed. + if build_clib and build_clib.fcompiler is not None: + need_f_compiler = 1 + else: + need_f_compiler = 0 + for ext in self.extensions: + if has_f_sources(ext.sources): + need_f_compiler = 1 + break + if getattr(ext,'language','c') in ['f77','f90']: + need_f_compiler = 1 + break + + # Determine if C++ compiler is needed. + need_cxx_compiler = 0 + for ext in self.extensions: + if has_cxx_sources(ext.sources): + need_cxx_compiler = 1 + break + if getattr(ext,'language','c')=='c++': + need_cxx_compiler = 1 + break + + from distutils.ccompiler import new_compiler + self.compiler = new_compiler(compiler=self.compiler, + verbose=self.verbose, + dry_run=self.dry_run, + force=self.force) + self.compiler.customize(self.distribution,need_cxx=need_cxx_compiler) + self.compiler.customize_cmd(self) + self.compiler.show_customization() + + # Initialize Fortran/C++ compilers if needed. + if need_f_compiler: + from scipy.distutils.fcompiler import new_fcompiler + self.fcompiler = new_fcompiler(compiler=self.fcompiler, + verbose=self.verbose, + dry_run=self.dry_run, + force=self.force) + if self.fcompiler.get_version(): + self.fcompiler.customize(self.distribution) + self.fcompiler.customize_cmd(self) + self.fcompiler.show_customization() + else: + self.warn('fcompiler=%s is not available.' % (self.fcompiler.compiler_type)) + self.fcompiler = None + + # Build extensions + self.build_extensions() + return + + def swig_sources(self, sources): + # Do nothing. Swig sources have beed handled in build_src command. + return 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,)) + + clib_libraries = [] + clib_library_dirs = [] + if self.distribution.libraries: + for libname,build_info in self.distribution.libraries: + if libname in ext.libraries: + macros.extend(build_info.get('macros',[])) + clib_libraries.extend(build_info.get('libraries',[])) + clib_library_dirs.extend(build_info.get('library_dirs',[])) + + 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 = [] + + + kws = {'depends':ext.depends} + output_dir = self.build_temp + + include_dirs = ext.include_dirs + get_scipy_include_dirs() + + 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=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=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 = [] + 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'] \ + and self.fcompiler is not None + 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 + clib_libraries, + library_dirs=ext.library_dirs + c_library_dirs + clib_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 + + def get_source_files (self): + self.check_extensions_list(self.extensions) + filenames = [] + for ext in self.extensions: + filenames.extend(get_ext_source_files(ext)) + return filenames + + def get_outputs (self): + self.check_extensions_list(self.extensions) + + outputs = [] + for ext in self.extensions: + if not ext.sources: + continue + fullname = self.get_ext_fullname(ext.name) + outputs.append(os.path.join(self.build_lib, + self.get_ext_filename(fullname))) + return outputs + |