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 | |
| parent | ddaed649c23bbd0ad36cdafdfe9cd92397ce69e3 (diff) | |
| download | numpy-8e2654541c6eae0f308908f501cccbc86b2f9101.tar.gz | |
Moved scipy directory to numpy
Diffstat (limited to 'numpy/distutils/command')
| -rw-r--r-- | numpy/distutils/command/__init__.py | 31 | ||||
| -rw-r--r-- | numpy/distutils/command/bdist_rpm.py | 17 | ||||
| -rw-r--r-- | numpy/distutils/command/build.py | 8 | ||||
| -rw-r--r-- | numpy/distutils/command/build_clib.py | 185 | ||||
| -rw-r--r-- | numpy/distutils/command/build_ext.py | 349 | ||||
| -rw-r--r-- | numpy/distutils/command/build_py.py | 13 | ||||
| -rw-r--r-- | numpy/distutils/command/build_scripts.py | 44 | ||||
| -rw-r--r-- | numpy/distutils/command/build_src.py | 542 | ||||
| -rw-r--r-- | numpy/distutils/command/config.py | 63 | ||||
| -rw-r--r-- | numpy/distutils/command/config_compiler.py | 56 | ||||
| -rw-r--r-- | numpy/distutils/command/install.py | 9 | ||||
| -rw-r--r-- | numpy/distutils/command/install_data.py | 14 | ||||
| -rw-r--r-- | numpy/distutils/command/install_headers.py | 26 | ||||
| -rw-r--r-- | numpy/distutils/command/sdist.py | 26 |
14 files changed, 1383 insertions, 0 deletions
diff --git a/numpy/distutils/command/__init__.py b/numpy/distutils/command/__init__.py new file mode 100644 index 000000000..5ec3e370a --- /dev/null +++ b/numpy/distutils/command/__init__.py @@ -0,0 +1,31 @@ +"""distutils.command + +Package containing implementation of all the standard Distutils +commands.""" + +__revision__ = "$Id: __init__.py,v 1.3 2005/05/16 11:08:49 pearu Exp $" + +distutils_all = [ 'build_py', + 'clean', + 'install_lib', + 'install_scripts', + 'bdist', + 'bdist_dumb', + 'bdist_wininst', + ] + +__import__('distutils.command',globals(),locals(),distutils_all) + +__all__ = ['build', + 'config_compiler', + 'config', + 'build_src', + 'build_ext', + 'build_clib', + 'build_scripts', + 'install', + 'install_data', + 'install_headers', + 'bdist_rpm', + 'sdist', + ] + distutils_all diff --git a/numpy/distutils/command/bdist_rpm.py b/numpy/distutils/command/bdist_rpm.py new file mode 100644 index 000000000..04aaea33b --- /dev/null +++ b/numpy/distutils/command/bdist_rpm.py @@ -0,0 +1,17 @@ + +import os +from distutils.command.bdist_rpm import * +from distutils.command.bdist_rpm import bdist_rpm as old_bdist_rpm + +class bdist_rpm(old_bdist_rpm): + + def _make_spec_file(self): + spec_file = old_bdist_rpm._make_spec_file(self) + setup_py = os.path.basename(sys.argv[0]) + if setup_py == 'setup.py': + return spec_file + new_spec_file = [] + for line in spec_file: + line = line.replace('setup.py',setup_py) + new_spec_file.append(line) + return new_spec_file diff --git a/numpy/distutils/command/build.py b/numpy/distutils/command/build.py new file mode 100644 index 000000000..c7872b6ff --- /dev/null +++ b/numpy/distutils/command/build.py @@ -0,0 +1,8 @@ + +from distutils.command.build import build as old_build + +class build(old_build): + + sub_commands = [('config_fc', lambda *args: 1), + ('build_src', old_build.has_ext_modules), + ] + old_build.sub_commands diff --git a/numpy/distutils/command/build_clib.py b/numpy/distutils/command/build_clib.py new file mode 100644 index 000000000..7f7c54d8d --- /dev/null +++ b/numpy/distutils/command/build_clib.py @@ -0,0 +1,185 @@ +""" Modified version of build_clib that handles fortran source files. +""" + +import os +import string +import sys +import re +from glob import glob +from types import * +from distutils.command.build_clib import build_clib as old_build_clib +from distutils.command.build_clib import show_compilers + +from scipy.distutils import log +from distutils.dep_util import newer_group +from scipy.distutils.misc_util import filter_sources, has_f_sources,\ + has_cxx_sources, all_strings, get_lib_source_files + +class build_clib(old_build_clib): + + description = "build C/C++/F libraries used by Python extensions" + + user_options = old_build_clib.user_options + [ + ('fcompiler=', None, + "specify the Fortran compiler type"), + ] + + def initialize_options(self): + old_build_clib.initialize_options(self) + self.fcompiler = None + return + + def finalize_options(self): + old_build_clib.finalize_options(self) + self.set_undefined_options('build_ext', + ('fcompiler', 'fcompiler')) + return + + def have_f_sources(self): + for (lib_name, build_info) in self.libraries: + if has_f_sources(build_info.get('sources',[])): + return True + return False + + def have_cxx_sources(self): + for (lib_name, build_info) in self.libraries: + if has_cxx_sources(build_info.get('sources',[])): + return True + return False + + def run(self): + if not self.libraries: + return + + # Make sure that library sources are complete. + for (lib_name, build_info) in self.libraries: + if not all_strings(build_info.get('sources',[])): + self.run_command('build_src') + + from distutils.ccompiler import new_compiler + self.compiler = new_compiler(compiler=self.compiler, + dry_run=self.dry_run, + force=self.force) + self.compiler.customize(self.distribution, + need_cxx=self.have_cxx_sources()) + + libraries = self.libraries + self.libraries = None + self.compiler.customize_cmd(self) + self.libraries = libraries + + self.compiler.show_customization() + + if self.have_f_sources(): + 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) + self.fcompiler.customize(self.distribution) + + libraries = self.libraries + self.libraries = None + self.fcompiler.customize_cmd(self) + self.libraries = libraries + + self.fcompiler.show_customization() + + self.build_libraries(self.libraries) + return + + def get_source_files(self): + self.check_library_list(self.libraries) + filenames = [] + for lib in self.libraries: + filenames.extend(get_lib_source_files(lib)) + return filenames + + 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) + + clib_libraries = build_info.get('libraries',[]) + for lname,binfo in libraries: + if lname in clib_libraries: + clib_libraries.extend(binfo[1].get('libraries',[])) + if clib_libraries: + build_info['libraries'] = clib_libraries + + return 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 + diff --git a/numpy/distutils/command/build_py.py b/numpy/distutils/command/build_py.py new file mode 100644 index 000000000..ab5bd8531 --- /dev/null +++ b/numpy/distutils/command/build_py.py @@ -0,0 +1,13 @@ + +from distutils.command.build_py import build_py as old_build_py + +class build_py(old_build_py): + + def find_package_modules(self, package, package_dir): + modules = old_build_py.find_package_modules(self, package, package_dir) + + # Find build_src generated *.py files. + build_src = self.get_finalized_command('build_src') + modules += build_src.py_modules.get(package,[]) + + return modules diff --git a/numpy/distutils/command/build_scripts.py b/numpy/distutils/command/build_scripts.py new file mode 100644 index 000000000..a2dabfa6a --- /dev/null +++ b/numpy/distutils/command/build_scripts.py @@ -0,0 +1,44 @@ +""" Modified version of build_scripts that handles building scripts from functions. +""" + +from distutils.command.build_scripts import build_scripts as old_build_scripts +from scipy.distutils import log + +class build_scripts(old_build_scripts): + + def generate_scripts(self, scripts): + new_scripts = [] + func_scripts = [] + for script in scripts: + if type(script) is type(''): + new_scripts.append(script) + else: + func_scripts.append(script) + if not func_scripts: + return new_scripts + + build_dir = self.build_dir + self.mkpath(build_dir) + for func in func_scripts: + script = func(build_dir) + if not script: + continue + if type(script) is type([]): + [log.info(" adding '%s' to scripts" % (s)) for s in script] + new_scripts.extend(script) + else: + log.info(" adding '%s' to scripts" % (script)) + new_scripts.append(script) + return new_scripts + + def run (self): + if not self.scripts: + return + + self.scripts = self.generate_scripts(self.scripts) + + return old_build_scripts.run(self) + + def get_source_files(self): + from scipy.distutils.misc_util import get_script_files + return get_script_files(self.scripts) diff --git a/numpy/distutils/command/build_src.py b/numpy/distutils/command/build_src.py new file mode 100644 index 000000000..65b46d173 --- /dev/null +++ b/numpy/distutils/command/build_src.py @@ -0,0 +1,542 @@ +""" Build swig, f2py, weave, sources. +""" + +import os +import re +import copy + +from distutils.cmd import Command +from distutils.command import build_ext, build_py +from distutils.util import convert_path +from distutils.dep_util import newer_group, newer + +from scipy.distutils import log +from scipy.distutils.misc_util import fortran_ext_match, all_strings, dot_join,\ + appendpath +from scipy.distutils.from_template import process_file as process_f_file +from scipy.distutils.conv_template import process_file as process_c_file +from scipy.distutils.extension import Extension +from scipy.distutils.system_info import get_info, dict_append + +class build_src(build_ext.build_ext): + + description = "build sources from SWIG, F2PY files or a function" + + user_options = [ + ('build-src=', 'd', "directory to \"build\" sources to"), + ('f2pyflags=', None, "additonal flags to f2py"), + ('swigflags=', None, "additional flags to swig"), + ('force', 'f', "forcibly build everything (ignore file timestamps)"), + ('inplace', 'i', + "ignore build-lib and put compiled extensions into the source " + + "directory alongside your pure Python modules"), + ] + + boolean_options = ['force','inplace'] + + help_options = [] + + def initialize_options(self): + self.extensions = None + self.package = None + self.py_modules = None + self.build_src = None + self.build_lib = None + self.build_base = None + self.force = None + self.inplace = None + self.package_dir = None + self.f2pyflags = None + self.swigflags = None + return + + def finalize_options(self): + self.set_undefined_options('build', + ('build_base', 'build_base'), + ('build_lib', 'build_lib'), + ('force', 'force')) + if self.package is None: + self.package = self.distribution.ext_package + self.extensions = self.distribution.ext_modules + self.libraries = self.distribution.libraries or [] + self.py_modules = self.distribution.py_modules + if self.build_src is None: + self.build_src = os.path.join(self.build_base, 'src') + if self.inplace is None: + build_ext = self.get_finalized_command('build_ext') + self.inplace = build_ext.inplace + + # py_modules is used in build_py.find_package_modules + self.py_modules = {} + + if self.f2pyflags is None: + self.f2pyflags = [] + else: + self.f2pyflags = self.f2pyflags.split() # XXX spaces?? + + if self.swigflags is None: + self.swigflags = [] + else: + self.swigflags = self.swigflags.split() # XXX spaces?? + return + + def run(self): + if not (self.extensions or self.libraries): + return + self.build_sources() + + return + + def build_sources(self): + + for libname_info in self.libraries: + self.build_library_sources(*libname_info) + + if self.extensions: + self.check_extensions_list(self.extensions) + + for ext in self.extensions: + self.build_extension_sources(ext) + + return + + def build_library_sources(self, lib_name, build_info): + sources = list(build_info.get('sources',[])) + + if not sources: + return + + log.info('building library "%s" sources' % (lib_name)) + + sources = self.generate_sources(sources, (lib_name, build_info)) + + sources = self.template_sources(sources, (lib_name, build_info)) + + sources, h_files = self.filter_h_files(sources) + + if h_files: + print self.package,'- nothing done with h_files=',h_files + + #for f in h_files: + # self.distribution.headers.append((lib_name,f)) + + build_info['sources'] = sources + return + + def build_extension_sources(self, ext): + + sources = list(ext.sources) + + log.info('building extension "%s" sources' % (ext.name)) + + fullname = self.get_ext_fullname(ext.name) + + modpath = fullname.split('.') + package = '.'.join(modpath[0:-1]) + + + if self.inplace: + build_py = self.get_finalized_command('build_py') + self.ext_target_dir = build_py.get_package_dir(package) + + + sources = self.generate_sources(sources, ext) + + sources = self.template_sources(sources, ext) + + sources = self.swig_sources(sources, ext) + + sources = self.f2py_sources(sources, ext) + + sources, py_files = self.filter_py_files(sources) + + if not self.py_modules.has_key(package): + self.py_modules[package] = [] + modules = [] + for f in py_files: + module = os.path.splitext(os.path.basename(f))[0] + modules.append((package, module, f)) + self.py_modules[package] += modules + + sources, h_files = self.filter_h_files(sources) + + if h_files: + print package,'- nothing done with h_files=',h_files + #for f in h_files: + # self.distribution.headers.append((package,f)) + + ext.sources = sources + + return + + def generate_sources(self, sources, extension): + new_sources = [] + func_sources = [] + for source in sources: + if type(source) is type(''): + new_sources.append(source) + else: + func_sources.append(source) + if not func_sources: + return new_sources + if self.inplace: + build_dir = self.ext_target_dir + else: + if type(extension) is type(()): + name = extension[0] + # if not extension[1].has_key('include_dirs'): + # extension[1]['include_dirs'] = [] + # incl_dirs = extension[1]['include_dirs'] + else: + name = extension.name + # incl_dirs = extension.include_dirs + #if self.build_src not in incl_dirs: + # incl_dirs.append(self.build_src) + build_dir = os.path.join(*([self.build_src]\ + +name.split('.')[:-1])) + self.mkpath(build_dir) + for func in func_sources: + source = func(extension, build_dir) + if not source: + continue + if type(source) is type([]): + [log.info(" adding '%s' to sources." % (s)) for s in source] + new_sources.extend(source) + else: + log.info(" adding '%s' to sources." % (source)) + new_sources.append(source) + + return new_sources + + def filter_py_files(self, sources): + return self.filter_files(sources,['.py']) + + def filter_h_files(self, sources): + return self.filter_files(sources,['.h','.hpp','.inc']) + + def filter_files(self, sources, exts = []): + new_sources = [] + files = [] + for source in sources: + (base, ext) = os.path.splitext(source) + if ext in exts: + files.append(source) + else: + new_sources.append(source) + return new_sources, files + + def template_sources(self, sources, extension): + new_sources = [] + if type(extension) is type(()): + depends = extension[1].get('depends') + include_dirs = extension[1].get('include_dirs') + else: + depends = extension.depends + include_dirs = extension.include_dirs + for source in sources: + (base, ext) = os.path.splitext(source) + if ext == '.src': # Template file + if self.inplace: + target_dir = os.path.dirname(base) + else: + target_dir = appendpath(self.build_src, os.path.dirname(base)) + self.mkpath(target_dir) + target_file = os.path.join(target_dir,os.path.basename(base)) + if (self.force or newer_group([source] + depends, target_file)): + if _f_pyf_ext_match(base): + log.info("from_template:> %s" % (target_file)) + outstr = process_f_file(source) + else: + log.info("conv_template:> %s" % (target_file)) + outstr = process_c_file(source) + fid = open(target_file,'w') + fid.write(outstr) + fid.close() + if _header_ext_match(target_file): + d = os.path.dirname(target_file) + if d not in include_dirs: + log.info(" adding '%s' to include_dirs." % (d)) + include_dirs.append(d) + new_sources.append(target_file) + else: + new_sources.append(source) + return new_sources + + 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 self.distribution.libraries: + for name,build_info in self.distribution.libraries: + if name in extension.libraries: + f2py_options.extend(build_info.get('f2py_options',[])) + + log.info("f2py options: %s" % (f2py_options)) + + 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 scipy.f2py as 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 scipy.f2py as 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 scipy.f2py as 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 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 + +_f_pyf_ext_match = re.compile(r'.*[.](f90|f95|f77|for|ftn|f|pyf)\Z',re.I).match +_header_ext_match = re.compile(r'.*[.](inc|h|hpp)\Z',re.I).match + +#### SWIG related auxiliary functions #### +_swig_module_name_match = re.compile(r'\s*%module\s*(?P<name>[\w_]+)', + re.I).match +_has_c_header = re.compile(r'-[*]-\s*c\s*-[*]-',re.I).search +_has_cpp_header = re.compile(r'-[*]-\s*c[+][+]\s*-[*]-',re.I).search + +def get_swig_target(source): + f = open(source,'r') + result = 'c' + line = f.readline() + if _has_cpp_header(line): + result = 'c++' + if _has_c_header(line): + result = 'c' + f.close() + return result + +def get_swig_modulename(source): + f = open(source,'r') + f_readlines = getattr(f,'xreadlines',f.readlines) + for line in f_readlines(): + m = _swig_module_name_match(line) + if m: + name = m.group('name') + break + f.close() + return name + +def _find_swig_target(target_dir,name): + for ext in ['.cpp','.c']: + target = os.path.join(target_dir,'%s_wrap%s' % (name, ext)) + if os.path.isfile(target): + break + return target + +#### F2PY related auxiliary functions #### + +_f2py_module_name_match = re.compile(r'\s*python\s*module\s*(?P<name>[\w_]+)', + re.I).match +_f2py_user_module_name_match = re.compile(r'\s*python\s*module\s*(?P<name>[\w_]*?'\ + '__user__[\w_]*)',re.I).match + +def get_f2py_modulename(source): + name = None + f = open(source) + f_readlines = getattr(f,'xreadlines',f.readlines) + for line in f_readlines(): + m = _f2py_module_name_match(line) + if m: + if _f2py_user_module_name_match(line): # skip *__user__* names + continue + name = m.group('name') + break + f.close() + return name + +########################################## diff --git a/numpy/distutils/command/config.py b/numpy/distutils/command/config.py new file mode 100644 index 000000000..aff79067e --- /dev/null +++ b/numpy/distutils/command/config.py @@ -0,0 +1,63 @@ +# Added Fortran compiler support to config. Currently useful only for +# try_compile call. try_run works but is untested for most of Fortran +# compilers (they must define linker_exe first). +# Pearu Peterson + +from distutils.command.config import config as old_config +from distutils.command.config import LANG_EXT +LANG_EXT['f77'] = '.f' +LANG_EXT['f90'] = '.f90' + +class config(old_config): + old_config.user_options += [ + ('fcompiler=', None, + "specify the Fortran compiler type"), + ] + + def initialize_options(self): + self.fcompiler = None + old_config.initialize_options(self) + return + + def finalize_options(self): + old_config.finalize_options(self) + f = self.distribution.get_command_obj('config_fc') + self.set_undefined_options('config_fc', + ('fcompiler', 'fcompiler')) + return + + def _check_compiler (self): + old_config._check_compiler(self) + from scipy.distutils.fcompiler import FCompiler, new_fcompiler + if not isinstance(self.fcompiler, FCompiler): + self.fcompiler = new_fcompiler(compiler=self.fcompiler, + dry_run=self.dry_run, force=1) + self.fcompiler.customize(self.distribution) + self.fcompiler.customize_cmd(self) + self.fcompiler.show_customization() + return + + def _wrap_method(self,mth,lang,args): + from distutils.ccompiler import CompileError + from distutils.errors import DistutilsExecError + save_compiler = self.compiler + if lang in ['f77','f90']: + self.compiler = self.fcompiler + try: + ret = mth(*((self,)+args)) + except (DistutilsExecError,CompileError),msg: + self.compiler = save_compiler + raise CompileError + self.compiler = save_compiler + return ret + + def _compile (self, body, headers, include_dirs, lang): + return self._wrap_method(old_config._compile,lang, + (body, headers, include_dirs, lang)) + + def _link (self, body, + headers, include_dirs, + libraries, library_dirs, lang): + return self._wrap_method(old_config._link,lang, + (body, headers, include_dirs, + libraries, library_dirs, lang)) diff --git a/numpy/distutils/command/config_compiler.py b/numpy/distutils/command/config_compiler.py new file mode 100644 index 000000000..0db601fc6 --- /dev/null +++ b/numpy/distutils/command/config_compiler.py @@ -0,0 +1,56 @@ + +import sys +from distutils.core import Command + +#XXX: Implement confic_cc for enhancing C/C++ compiler options. +#XXX: Linker flags + +class config_fc(Command): + """ Distutils command to hold user specified options + to Fortran compilers. + + config_fc command is used by the FCompiler.customize() method. + """ + + user_options = [ + ('fcompiler=',None,"specify Fortran compiler type"), + ('f77exec=', None, "specify F77 compiler command"), + ('f90exec=', None, "specify F90 compiler command"), + ('f77flags=',None,"specify F77 compiler flags"), + ('f90flags=',None,"specify F90 compiler flags"), + ('opt=',None,"specify optimization flags"), + ('arch=',None,"specify architecture specific optimization flags"), + ('debug','g',"compile with debugging information"), + ('noopt',None,"compile without optimization"), + ('noarch',None,"compile without arch-dependent optimization"), + ('help-fcompiler',None,"list available Fortran compilers"), + ] + + boolean_options = ['debug','noopt','noarch','help-fcompiler'] + + def initialize_options(self): + self.fcompiler = None + self.f77exec = None + self.f90exec = None + self.f77flags = None + self.f90flags = None + self.opt = None + self.arch = None + self.debug = None + self.noopt = None + self.noarch = None + self.help_fcompiler = None + return + + def finalize_options(self): + if self.help_fcompiler: + from scipy.distutils.fcompiler import show_fcompilers + show_fcompilers(self.distribution) + sys.exit() + return + + def run(self): + # Do nothing. + return + + diff --git a/numpy/distutils/command/install.py b/numpy/distutils/command/install.py new file mode 100644 index 000000000..64d613569 --- /dev/null +++ b/numpy/distutils/command/install.py @@ -0,0 +1,9 @@ + +from distutils.command.install import * +from distutils.command.install import install as old_install + +class install(old_install): + + def finalize_options (self): + old_install.finalize_options(self) + self.install_lib = self.install_libbase diff --git a/numpy/distutils/command/install_data.py b/numpy/distutils/command/install_data.py new file mode 100644 index 000000000..e170ba4d8 --- /dev/null +++ b/numpy/distutils/command/install_data.py @@ -0,0 +1,14 @@ +from distutils.command.install_data import * +from distutils.command.install_data import install_data as old_install_data + +#data installer with improved intelligence over distutils +#data files are copied into the project directory instead +#of willy-nilly +class install_data (old_install_data): + + def finalize_options (self): + self.set_undefined_options('install', + ('install_lib', 'install_dir'), + ('root', 'root'), + ('force', 'force'), + ) diff --git a/numpy/distutils/command/install_headers.py b/numpy/distutils/command/install_headers.py new file mode 100644 index 000000000..043f024f5 --- /dev/null +++ b/numpy/distutils/command/install_headers.py @@ -0,0 +1,26 @@ +import os +from distutils.command.install import * +from distutils.command.install_headers import install_headers as old_install_headers + +class install_headers (old_install_headers): + + def run (self): + headers = self.distribution.headers + if not headers: + return + + prefix = os.path.dirname(self.install_dir) + for header in headers: + if isinstance(header,tuple): + # Kind of a hack, but I don't know where else to change this... + if header[0] == 'scipy.base': + header = ('scipy', header[1]) + if os.path.splitext(header[1])[1] == '.inc': + continue + d = os.path.join(*([prefix]+header[0].split('.'))) + header = header[1] + else: + d = self.install_dir + self.mkpath(d) + (out, _) = self.copy_file(header, d) + self.outfiles.append(out) diff --git a/numpy/distutils/command/sdist.py b/numpy/distutils/command/sdist.py new file mode 100644 index 000000000..289bd0357 --- /dev/null +++ b/numpy/distutils/command/sdist.py @@ -0,0 +1,26 @@ + +from distutils.command.sdist import * +from distutils.command.sdist import sdist as old_sdist +from scipy.distutils.misc_util import get_data_files + +class sdist(old_sdist): + + def add_defaults (self): + old_sdist.add_defaults(self) + + dist = self.distribution + + if dist.has_data_files(): + for data in dist.data_files: + self.filelist.extend(get_data_files(data)) + + if dist.has_headers(): + headers = [] + for h in dist.headers: + if isinstance(h,str): headers.append(h) + else: headers.append(h[1]) + self.filelist.extend(headers) + + return + + |
