[Numpy-svn] r3795 - in branches/distutils-revamp: . command fcompiler
numpy-svn at scipy.org
numpy-svn at scipy.org
Mon May 21 09:15:52 EDT 2007
Author: cookedm
Date: 2007-05-21 08:15:45 -0500 (Mon, 21 May 2007)
New Revision: 3795
Modified:
branches/distutils-revamp/
branches/distutils-revamp/ccompiler.py
branches/distutils-revamp/command/build.py
branches/distutils-revamp/command/build_clib.py
branches/distutils-revamp/command/build_ext.py
branches/distutils-revamp/command/build_src.py
branches/distutils-revamp/command/config.py
branches/distutils-revamp/command/config_compiler.py
branches/distutils-revamp/core.py
branches/distutils-revamp/fcompiler/__init__.py
branches/distutils-revamp/misc_util.py
branches/distutils-revamp/system_info.py
Log:
[distutils-revamp] Merged revisions 3769-3794 via svnmerge from
http://svn.scipy.org/svn/numpy/trunk/numpy/distutils
........
r3775 | pearu | 2007-05-18 10:32:33 -0400 (Fri, 18 May 2007) | 1 line
build_src: introduced --swig and other related options (as in std distutils build_ext command), use --f2py-opts instead of --f2pyflags, improved error messages.
........
r3776 | pearu | 2007-05-18 12:41:44 -0400 (Fri, 18 May 2007) | 1 line
Extension modules and libraries are built with suitable compilers/linkers. Improved failure handling.
........
r3779 | pearu | 2007-05-18 13:33:15 -0400 (Fri, 18 May 2007) | 1 line
Fixed warnings on language changes.
........
r3780 | pearu | 2007-05-18 16:17:48 -0400 (Fri, 18 May 2007) | 1 line
unify config_fc, build_clib, build_ext commands --fcompiler options so that --fcompiler can be specified only once in a command line
........
r3781 | pearu | 2007-05-18 16:41:10 -0400 (Fri, 18 May 2007) | 1 line
added config to --fcompiler option unification method. introduced config_cc for unifying --compiler options.
........
r3782 | pearu | 2007-05-18 16:49:09 -0400 (Fri, 18 May 2007) | 1 line
Added --help-fcompiler option to build_ext command.
........
r3783 | pearu | 2007-05-18 17:00:17 -0400 (Fri, 18 May 2007) | 1 line
show less messages in --help-fcompiler
........
r3784 | pearu | 2007-05-18 17:25:23 -0400 (Fri, 18 May 2007) | 1 line
Added --fcompiler,--help-fcompiler options to build command parallel to --compiler,--help-compiler options.
........
r3785 | pearu | 2007-05-18 17:33:07 -0400 (Fri, 18 May 2007) | 1 line
Add descriptions to config_fc and config_cc commands.
........
r3786 | pearu | 2007-05-19 05:54:00 -0400 (Sat, 19 May 2007) | 1 line
Fix for win32 platform.
........
r3787 | pearu | 2007-05-19 06:23:16 -0400 (Sat, 19 May 2007) | 1 line
Fix fcompiler/compiler unification warning.
........
r3788 | pearu | 2007-05-19 11:20:48 -0400 (Sat, 19 May 2007) | 1 line
Fix atlas version detection when using MSVC compiler
........
r3789 | pearu | 2007-05-19 11:21:41 -0400 (Sat, 19 May 2007) | 1 line
Fix typo.
........
r3790 | pearu | 2007-05-19 11:24:20 -0400 (Sat, 19 May 2007) | 1 line
More typo fixes.
........
r3791 | pearu | 2007-05-19 13:01:39 -0400 (Sat, 19 May 2007) | 1 line
win32: fix install when build has been carried out earlier.
........
r3792 | pearu | 2007-05-19 15:44:42 -0400 (Sat, 19 May 2007) | 1 line
Clean up and completed (hopefully) MSVC support.
........
r3794 | cookedm | 2007-05-21 09:01:20 -0400 (Mon, 21 May 2007) | 1 line
minor cleanups in numpy.distutils (style mostly)
........
Property changes on: branches/distutils-revamp
___________________________________________________________________
Name: svnmerge-integrated
- /branches/distutils-revamp:1-2756 /trunk/numpy/distutils:1-3768
+ /branches/distutils-revamp:1-2756 /trunk/numpy/distutils:1-3794
Modified: branches/distutils-revamp/ccompiler.py
===================================================================
--- branches/distutils-revamp/ccompiler.py 2007-05-21 13:01:20 UTC (rev 3794)
+++ branches/distutils-revamp/ccompiler.py 2007-05-21 13:15:45 UTC (rev 3795)
@@ -288,6 +288,7 @@
replace_method(CCompiler, 'get_version', CCompiler_get_version)
def CCompiler_cxx_compiler(self):
+ if self.compiler_type=='msvc': return self
cxx = copy(self)
cxx.compiler_so = [cxx.compiler_cxx[0]] + cxx.compiler_so[1:]
if sys.platform.startswith('aix') and 'ld_so_aix' in cxx.linker_so[0]:
Modified: branches/distutils-revamp/command/build.py
===================================================================
--- branches/distutils-revamp/command/build.py 2007-05-21 13:01:20 UTC (rev 3794)
+++ branches/distutils-revamp/command/build.py 2007-05-21 13:15:45 UTC (rev 3795)
@@ -2,13 +2,29 @@
import sys
from distutils.command.build import build as old_build
from distutils.util import get_platform
+from numpy.distutils.command.config_compiler import show_fortran_compilers
class build(old_build):
- sub_commands = [('config_fc', lambda *args: 1),
+ sub_commands = [('config_cc', lambda *args: True),
+ ('config_fc', lambda *args: True),
('build_src', old_build.has_ext_modules),
] + old_build.sub_commands
+ user_options = old_build.user_options + [
+ ('fcompiler=', None,
+ "specify the Fortran compiler type"),
+ ]
+
+ help_options = old_build.help_options + [
+ ('help-fcompiler',None, "list available Fortran compilers",
+ show_fortran_compilers),
+ ]
+
+ def initialize_options(self):
+ old_build.initialize_options(self)
+ self.fcompiler = None
+
def finalize_options(self):
build_scripts = self.build_scripts
old_build.finalize_options(self)
Modified: branches/distutils-revamp/command/build_clib.py
===================================================================
--- branches/distutils-revamp/command/build_clib.py 2007-05-21 13:01:20 UTC (rev 3794)
+++ branches/distutils-revamp/command/build_clib.py 2007-05-21 13:15:45 UTC (rev 3795)
@@ -1,19 +1,15 @@
""" Modified version of build_clib that handles fortran source files.
"""
+import os
from distutils.command.build_clib import build_clib as old_build_clib
-from distutils.errors import DistutilsSetupError
+from distutils.errors import DistutilsSetupError, DistutilsError
from numpy.distutils import log
from distutils.dep_util import newer_group
from numpy.distutils.misc_util import filter_sources, has_f_sources,\
has_cxx_sources, all_strings, get_lib_source_files, is_sequence
-try:
- set
-except NameError:
- from sets import Set as set
-
# Fix Python distutils bug sf #1718574:
_l = old_build_clib.user_options
for _i in range(len(_l)):
@@ -33,46 +29,32 @@
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._languages = None
- self.set_undefined_options('config_fc',
- ('fcompiler', 'fcompiler'))
- # we set this to the appropiate Fortran compiler object
- # (f77 or f90) in the .run() method
- self._fcompiler = None
-
- def languages(self):
- """Return a set of language names used in this library.
- Valid language names are 'c', 'f77', and 'f90'.
- """
- if self._languages is None:
- languages = set()
- for (lib_name, build_info) in self.libraries:
- l = build_info.get('language',None)
- if l:
- languages.add(l)
- self._languages = languages
- return self._languages
-
def have_f_sources(self):
- l = self.languages()
- return 'f90' in l or 'f77' in l
+ 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):
- l = self.languages()
- return 'c++' in l
+ 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.
- self.run_command('build_src')
+ languages = []
+ for (lib_name, build_info) in self.libraries:
+ if not all_strings(build_info.get('sources',[])):
+ self.run_command('build_src')
+ l = build_info.get('language',None)
+ if l and l not in languages: languages.append(l)
- languages = self.languages()
-
from distutils.ccompiler import new_compiler
self.compiler = new_compiler(compiler=self.compiler,
dry_run=self.dry_run,
@@ -88,17 +70,20 @@
self.compiler.show_customization()
if self.have_f_sources():
- if 'f90' in languages:
- fc = self.fcompiler.f90()
- else:
- fc = self.fcompiler.f77()
+ from numpy.distutils.fcompiler import new_fcompiler
+ self.fcompiler = new_fcompiler(compiler=self.fcompiler,
+ verbose=self.verbose,
+ dry_run=self.dry_run,
+ force=self.force,
+ requiref90='f90' in languages)
+ self.fcompiler.customize(self.distribution)
+
libraries = self.libraries
self.libraries = None
- fc.customize_cmd(self)
+ self.fcompiler.customize_cmd(self)
self.libraries = libraries
- fc.show_customization()
- self._fcompiler = fc
+ self.fcompiler.show_customization()
self.build_libraries(self.libraries)
@@ -110,10 +95,10 @@
return filenames
def build_libraries(self, libraries):
- fcompiler = self._fcompiler
- compiler = self.compiler
-
for (lib_name, build_info) in libraries:
+ # default compilers
+ compiler = self.compiler
+ fcompiler = self.fcompiler
sources = build_info.get('sources')
if sources is None or not is_sequence(sources):
@@ -123,9 +108,21 @@
"a list of source filenames") % lib_name
sources = list(sources)
+ c_sources, cxx_sources, f_sources, fmodule_sources \
+ = filter_sources(sources)
+ requiref90 = not not fmodule_sources or \
+ build_info.get('language','c')=='f90'
+
+ # save source type information so that build_ext can use it.
+ source_languages = []
+ if c_sources: source_languages.append('c')
+ if cxx_sources: source_languages.append('c++')
+ if requiref90: source_languages.append('f90')
+ elif f_sources: source_languages.append('f77')
+ build_info['source_languages'] = source_languages
+
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)
@@ -133,34 +130,42 @@
else:
log.info("building '%s' library", lib_name)
-
config_fc = build_info.get('config_fc',{})
if fcompiler is not None and config_fc:
log.info('using additional config_fc from setup script '\
'for fortran compiler: %s' \
% (config_fc,))
+ from numpy.distutils.fcompiler import new_fcompiler
+ fcompiler = new_fcompiler(compiler=fcompiler.compiler_type,
+ verbose=self.verbose,
+ dry_run=self.dry_run,
+ force=self.force,
+ requiref90=requiref90)
dist = self.distribution
base_config_fc = dist.get_option_dict('config_fc').copy()
base_config_fc.update(config_fc)
fcompiler.customize(base_config_fc)
+ # check availability of Fortran compilers
+ if (f_sources or fmodule_sources) and fcompiler is None:
+ raise DistutilsError, "library %s has Fortran sources"\
+ " but no Fortran compiler found" % (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)
+ # where compiled F90 module files are:
+ module_dirs = build_info.get('module_dirs') or []
+ module_build_dir = os.path.dirname(lib_file)
+ if requiref90: self.mkpath(module_build_dir)
- if self.compiler.compiler_type=='msvc':
+ if 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")
@@ -182,20 +187,61 @@
extra_postargs=extra_postargs)
objects.extend(cxx_objects)
- 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)
+ if f_sources or fmodule_sources:
+ extra_postargs = []
+ f_objects = []
- self.compiler.create_static_lib(objects, lib_name,
- output_dir=self.build_clib,
- debug=self.debug)
+ if requiref90:
+ if fcompiler.module_dir_switch is None:
+ existing_modules = glob('*.mod')
+ extra_postargs += fcompiler.module_options(\
+ module_dirs,module_build_dir)
+ if fmodule_sources:
+ log.info("compiling Fortran 90 module sources")
+ f_objects += fcompiler.compile(fmodule_sources,
+ output_dir=self.build_temp,
+ macros=macros,
+ include_dirs=include_dirs,
+ debug=self.debug,
+ extra_postargs=extra_postargs)
+
+ if requiref90 and self.fcompiler.module_dir_switch is None:
+ # move new compiled F90 module files to module_build_dir
+ for f in glob('*.mod'):
+ if f in existing_modules:
+ continue
+ t = os.path.join(module_build_dir, f)
+ if os.path.abspath(f)==os.path.abspath(t):
+ continue
+ if os.path.isfile(t):
+ os.remove(t)
+ try:
+ self.move_file(f, module_build_dir)
+ except DistutilsFileError:
+ log.warn('failed to move %r to %r' \
+ % (f, module_build_dir))
+
+ 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=extra_postargs)
+ else:
+ f_objects = []
+
+ objects.extend(f_objects)
+
+ # assume that default linker is suitable for
+ # linking Fortran object files
+ compiler.create_static_lib(objects, lib_name,
+ output_dir=self.build_clib,
+ debug=self.debug)
+
+ # fix library dependencies
clib_libraries = build_info.get('libraries',[])
for lname, binfo in libraries:
if lname in clib_libraries:
Modified: branches/distutils-revamp/command/build_ext.py
===================================================================
--- branches/distutils-revamp/command/build_ext.py 2007-05-21 13:01:20 UTC (rev 3794)
+++ branches/distutils-revamp/command/build_ext.py 2007-05-21 13:15:45 UTC (rev 3795)
@@ -2,26 +2,28 @@
"""
import os
-import string
import sys
from glob import glob
from distutils.dep_util import newer_group
from distutils.command.build_ext import build_ext as old_build_ext
-from distutils.errors import DistutilsFileError, DistutilsSetupError
+from distutils.errors import DistutilsFileError, DistutilsSetupError,\
+ DistutilsError
from distutils.file_util import copy_file
from numpy.distutils import log
from numpy.distutils.exec_command import exec_command
from numpy.distutils.system_info import combine_paths
from numpy.distutils.misc_util import filter_sources, has_f_sources, \
- has_cxx_sources, get_ext_source_files, all_strings, \
+ has_cxx_sources, get_ext_source_files, \
get_numpy_include_dirs, is_sequence
+from numpy.distutils.command.config_compiler import show_fortran_compilers
+try:
+ set
+except NameError:
+ from sets import Set as set
-def ext_language(ext):
- return getattr(ext, 'language', 'c')
-
class build_ext (old_build_ext):
description = "build C/C++/F extensions (compile/link to build directory)"
@@ -31,6 +33,11 @@
"specify the Fortran compiler type"),
]
+ help_options = old_build_ext.help_options + [
+ ('help-fcompiler',None, "list available Fortran compilers",
+ show_fortran_compilers),
+ ]
+
def initialize_options(self):
old_build_ext.initialize_options(self)
self.fcompiler = None
@@ -40,45 +47,7 @@
old_build_ext.finalize_options(self)
if incl_dirs is not None:
self.include_dirs.extend(self.distribution.include_dirs or [])
- self.set_undefined_options('config_fc',
- ('fcompiler', 'fcompiler'))
- self._fcompiler = None
- def initialize_fcompiler(self, build_clib):
- # Determine if Fortran compiler is needed.
- requiref77 = requiref90 = False
- if build_clib:
- lang = build_clib.languages()
- requiref77 = 'f77' in lang
- requiref90 = 'f90' in lang
- else:
- for ext in self.extensions:
- language = ext_language(ext)
- if language == 'f77':
- requiref77 = True
- elif language == 'f90':
- requiref90 = True
- elif has_f_sources(ext.sources):
- # because we don't know any better, assume F77
- requiref77 = True
-
- if not (requiref77 or requiref90):
- return
-
- if requiref90:
- self.fcompiler.need_f90()
- if requiref77:
- self.fcompiler.need_f77()
-
- fc = self.fcompiler.fortran(requiref90)
- if fc.get_version():
- fc.customize_cmd(self)
- fc.show_customization()
- else:
- self.warn('fcompiler=%s is not available.' % (
- fc.compiler_type,))
- self._fcompiler = fc
-
def run(self):
if not self.extensions:
return
@@ -86,10 +55,6 @@
# Make sure that extension sources are complete.
self.run_command('build_src')
- # 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.
if self.distribution.has_c_libraries():
self.run_command('build_clib')
build_clib = self.get_finalized_command('build_clib')
@@ -97,96 +62,163 @@
else:
build_clib = None
- # Determine if C++ compiler is needed.
- need_cxx_compiler = False
- for ext in self.extensions:
- if has_cxx_sources(ext.sources):
- need_cxx_compiler = True
- break
- if getattr(ext,'language','c') == 'c++':
- need_cxx_compiler = True
- break
+ # 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.
from distutils.ccompiler import new_compiler
- self.compiler = new_compiler(compiler=self.compiler,
+ from numpy.distutils.fcompiler import new_fcompiler
+
+ compiler_type = self.compiler
+ # Initialize C compiler:
+ self.compiler = new_compiler(compiler=compiler_type,
verbose=self.verbose,
dry_run=self.dry_run,
force=self.force)
- self.compiler.customize(self.distribution,need_cxx=need_cxx_compiler)
+ self.compiler.customize(self.distribution)
self.compiler.customize_cmd(self)
self.compiler.show_customization()
- self.initialize_fcompiler(build_clib)
+ # Create mapping of libraries built by build_clib:
+ clibs = {}
+ if build_clib is not None:
+ for libname,build_info in build_clib.libraries or []:
+ if clibs.has_key(libname):
+ log.warn('library %r defined more than once,'\
+ ' overwriting build_info %r with %r.' \
+ % (libname, clibs[libname], build_info))
+ clibs[libname] = build_info
+ # .. and distribution libraries:
+ for libname,build_info in self.distribution.libraries or []:
+ if clibs.has_key(libname):
+ # build_clib libraries have a precedence before distribution ones
+ continue
+ clibs[libname] = build_info
- # Build extensions
- self.build_extensions()
+ # Determine if C++/Fortran 77/Fortran 90 compilers are needed.
+ # Update extension libraries, library_dirs, and macros.
+ all_languages = set()
+ for ext in self.extensions:
+ ext_languages = set()
+ c_libs = []
+ c_lib_dirs = []
+ macros = []
+ for libname in ext.libraries:
+ if clibs.has_key(libname):
+ binfo = clibs[libname]
+ c_libs += binfo.get('libraries',[])
+ c_lib_dirs += binfo.get('library_dirs',[])
+ for m in binfo.get('macros',[]):
+ if m not in macros:
+ macros.append(m)
+ for l in clibs.get(libname,{}).get('source_languages',[]):
+ ext_languages.add(l)
+ if c_libs:
+ new_c_libs = ext.libraries + c_libs
+ log.info('updating extension %r libraries from %r to %r'
+ % (ext.name, ext.libraries, new_c_libs))
+ ext.libraries = new_c_libs
+ ext.library_dirs = ext.library_dirs + c_lib_dirs
+ if macros:
+ log.info('extending extension %r defined_macros with %r'
+ % (ext.name, macros))
+ ext.define_macros = ext.define_macros + macros
- def swig_sources(self, sources):
- # Do nothing. Swig sources have beed handled in build_src command.
- return sources
+ # determine extension languages
+ if has_f_sources(ext.sources):
+ ext_languages.add('f77')
+ if has_cxx_sources(ext.sources):
+ ext_languages.add('c++')
+ l = ext.language or self.compiler.detect_language(ext.sources)
+ if l:
+ ext_languages.add(l)
+ # reset language attribute for choosing proper linker
+ if 'c++' in ext_languages:
+ ext_language = 'c++'
+ elif 'f90' in ext_languages:
+ ext_language = 'f90'
+ elif 'f77' in ext_languages:
+ ext_language = 'f77'
+ else:
+ ext_language = 'c' # default
+ if l and l != ext_language and ext.language:
+ log.warn('resetting extension %r language from %r to %r.' %
+ (ext.name,l,ext_language))
+ ext.language = ext_language
+ # global language
+ all_languages.update(ext_languages)
- def get_fortran_objects(self, ext, f_sources, fmodule_sources,
- macros, include_dirs):
- if not f_sources and not fmodule_sources:
- return None, []
+ need_f90_compiler = 'f90' in all_languages
+ need_f77_compiler = 'f77' in all_languages
+ need_cxx_compiler = 'c++' in all_languages
- fcompiler = self._fcompiler
+ # Initialize C++ compiler:
+ if need_cxx_compiler:
+ self._cxx_compiler = new_compiler(compiler=compiler_type,
+ verbose=self.verbose,
+ dry_run=self.dry_run,
+ force=self.force)
+ compiler = self._cxx_compiler
+ compiler.customize(self.distribution,need_cxx=need_cxx_compiler)
+ compiler.customize_cmd(self)
+ compiler.show_customization()
+ self._cxx_compiler = compiler.cxx_compiler()
+ else:
+ self._cxx_compiler = None
- extra_postargs = []
- module_dirs = ext.module_dirs[:]
+ # Initialize Fortran 77 compiler:
+ if need_f77_compiler:
+ self._f77_compiler = new_fcompiler(compiler=self.fcompiler,
+ verbose=self.verbose,
+ dry_run=self.dry_run,
+ force=self.force,
+ requiref90=False)
+ fcompiler = self._f77_compiler
+ if fcompiler.get_version():
+ fcompiler.customize(self.distribution)
+ fcompiler.customize_cmd(self)
+ fcompiler.show_customization()
+ else:
+ self.warn('f77_compiler=%s is not available.' %
+ (fcompiler.compiler_type))
+ self._f77_compiler = None
+ else:
+ self._f77_compiler = None
- macros = []
+ # Initialize Fortran 90 compiler:
+ if need_f90_compiler:
+ self._f90_compiler = new_fcompiler(compiler=self.fcompiler,
+ verbose=self.verbose,
+ dry_run=self.dry_run,
+ force=self.force,
+ requiref90=True)
+ fcompiler = self._f90_compiler
+ if fcompiler.get_version():
+ fcompiler.customize(self.distribution)
+ fcompiler.customize_cmd(self)
+ fcompiler.show_customization()
+ else:
+ self.warn('f90_compiler=%s is not available.' %
+ (fcompiler.compiler_type))
+ self._f90_compiler = None
+ else:
+ self._f90_compiler = None
- if fmodule_sources:
- module_build_dir = os.path.join(
- self.build_temp,os.path.dirname(
- self.get_ext_filename(fullname)))
+ # Build extensions
+ self.build_extensions()
- self.mkpath(module_build_dir)
- if fcompiler.module_dir_switch is None:
- existing_modules = glob('*.mod')
- extra_postargs += fcompiler.module_options(\
- module_dirs,module_build_dir)
+ def swig_sources(self, sources):
+ # Do nothing. Swig sources have beed handled in build_src command.
+ return sources
- f_objects = []
- if fmodule_sources:
- log.info("compiling Fortran 90 module sources")
- f_objects = 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 fmodule_sources and 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 += 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)
-
- return fcompiler, f_objects
-
def build_extension(self, ext):
sources = ext.sources
if sources is None or not is_sequence(sources):
- raise DistutilsSetupError, \
- ("in 'ext_modules' option (extension '%s'), " +
- "'sources' must be present and must be " +
- "a list of source filenames") % ext.name
+ 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:
@@ -194,10 +226,9 @@
fullname = self.get_ext_fullname(ext.name)
if self.inplace:
- modpath = string.split(fullname, '.')
- package = string.join(modpath[0:-1], '.')
+ modpath = fullname.split('.')
+ package = '.'.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,
@@ -218,17 +249,11 @@
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.
@@ -238,7 +263,29 @@
c_sources += cxx_sources
cxx_sources = []
+ # Set Fortran/C++ compilers for compilation and linking.
+ if ext.language=='f90':
+ fcompiler = self._f90_compiler
+ elif ext.language=='f77':
+ fcompiler = self._f77_compiler
+ else: # in case ext.language is c++, for instance
+ fcompiler = self._f90_compiler or self._f77_compiler
+ cxx_compiler = self._cxx_compiler
+ # check for the availability of required compilers
+ if cxx_sources and cxx_compiler is None:
+ raise DistutilsError, "extension %r has C++ sources" \
+ "but no C++ compiler found" % (ext.name)
+ if (f_sources or fmodule_sources) and fcompiler is None:
+ raise DistutilsError, "extension %r has Fortran sources " \
+ "but no Fortran compiler found" % (ext.name)
+ if ext.language in ['f77','f90'] and fcompiler is None:
+ self.warn("extension %r has Fortran libraries " \
+ "but no Fortran linker found, using default linker" % (ext.name))
+ if ext.language=='c++' and cxx_compiler is None:
+ self.warn("extension %r has C++ libraries " \
+ "but no C++ linker found, using default linker" % (ext.name))
+
kws = {'depends':ext.depends}
output_dir = self.build_temp
@@ -254,11 +301,9 @@
debug=self.debug,
extra_postargs=extra_args,
**kws)
+
if cxx_sources:
log.info("compiling C++ sources")
-
- cxx_compiler = self.compiler.cxx_compiler()
-
c_objects += cxx_compiler.compile(cxx_sources,
output_dir=output_dir,
macros=macros,
@@ -267,80 +312,117 @@
extra_postargs=extra_args,
**kws)
- fcompiler, f_objects = self.get_fortran_objects(ext,
- f_sources,
- fmodule_sources,
- macros, include_dirs)
+ extra_postargs = []
+ f_objects = []
+ if fmodule_sources:
+ log.info("compiling Fortran 90 module sources")
+ module_dirs = ext.module_dirs[:]
+ module_build_dir = os.path.join(
+ self.build_temp,os.path.dirname(
+ self.get_ext_filename(fullname)))
+ self.mkpath(module_build_dir)
+ if fcompiler.module_dir_switch is None:
+ existing_modules = glob('*.mod')
+ extra_postargs += fcompiler.module_options(
+ module_dirs,module_build_dir)
+ f_objects += 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 fcompiler.module_dir_switch is None:
+ for f in glob('*.mod'):
+ if f in existing_modules:
+ continue
+ t = os.path.join(module_build_dir, f)
+ if os.path.abspath(f)==os.path.abspath(t):
+ continue
+ if os.path.isfile(t):
+ os.remove(t)
+ try:
+ self.move_file(f, module_build_dir)
+ except DistutilsFileError:
+ log.warn('failed to move %r to %r' %
+ (f, module_build_dir))
+ 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=extra_postargs,
+ depends=ext.depends)
+
objects = c_objects + f_objects
if ext.extra_objects:
objects.extend(ext.extra_objects)
extra_args = ext.extra_link_args or []
+ libraries = self.get_libraries(ext)[:]
+ library_dirs = ext.library_dirs[:]
linker = self.compiler.link_shared_object
-
- use_fortran_linker = getattr(ext,'language','c') in ['f77','f90']
- c_libraries = []
- c_library_dirs = []
- if not use_fortran_linker and 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 = True
- fcompiler = self.fcompiler.fortran()
- break
-
- if use_fortran_linker and not fcompiler:
- fcompiler = self.fcompiler.fortran()
-
# Always use system linker when using MSVC compiler.
- if self.compiler.compiler_type=='msvc' and use_fortran_linker:
- self._libs_with_msvc_and_fortran(c_libraries, c_library_dirs)
- use_fortran_linker = False
-
- if use_fortran_linker:
- if cxx_sources:
- # XXX: Which linker should be used, Fortran or C++?
- log.warn('mixing Fortran and C++ is untested')
+ if self.compiler.compiler_type=='msvc':
+ # expand libraries with fcompiler libraries as we are
+ # not using fcompiler linker
+ self._libs_with_msvc_and_fortran(fcompiler, libraries, library_dirs)
+ elif ext.language in ['f77','f90'] and fcompiler is not None:
linker = fcompiler.link_shared_object
- language = ext.language or fcompiler.detect_language(f_sources)
- else:
- linker = 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:
- linker = self.compiler.cxx_compiler().link_shared_object
+ if ext.language=='c++' and cxx_compiler is not None:
+ linker = cxx_compiler.link_shared_object
if sys.version[:3]>='2.3':
- kws = {'target_lang':language}
+ kws = {'target_lang':ext.language}
else:
kws = {}
linker(objects, ext_filename,
- libraries=self.get_libraries(ext) + c_libraries + clib_libraries,
- library_dirs=ext.library_dirs+c_library_dirs+clib_library_dirs,
+ libraries=libraries,
+ library_dirs=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)
- def _libs_with_msvc_and_fortran(self, c_libraries, c_library_dirs):
+ def _libs_with_msvc_and_fortran(self, fcompiler, c_libraries,
+ c_library_dirs):
+ if fcompiler is None: return
+
+ for libname in c_libraries:
+ if libname.startswith('msvc'): continue
+ fileexists = False
+ for libdir in c_library_dirs or []:
+ libfile = os.path.join(libdir,'%s.lib' % (libname))
+ if os.path.isfile(libfile):
+ fileexists = True
+ break
+ if fileexists: continue
+ # make g77-compiled static libs available to MSVC
+ fileexists = False
+ for libdir in c_library_dirs:
+ libfile = os.path.join(libdir,'lib%s.a' % (libname))
+ if os.path.isfile(libfile):
+ # copy libname.a file to name.lib so that MSVC linker
+ # can find it
+ libfile2 = os.path.join(self.build_temp, libname + '.lib')
+ copy_file(libfile, libfile2)
+ if self.build_temp not in c_library_dirs:
+ c_library_dirs.append(self.build_temp)
+ fileexists = True
+ break
+ if fileexists: continue
+ log.warn('could not find library %r in directories %s'
+ % (libname, c_library_dirs))
+
# Always use system linker when using MSVC compiler.
f_lib_dirs = []
- fcompiler = self.fcompiler.fortran()
for dir in fcompiler.library_dirs:
# correct path when compiling in Cygwin but with normal Win
# Python
@@ -352,17 +434,16 @@
c_library_dirs.extend(f_lib_dirs)
# make g77-compiled static libs available to MSVC
- lib_added = False
for lib in fcompiler.libraries:
- if not lib.startswith('msvcr'):
+ if not lib.startswith('msvc'):
c_libraries.append(lib)
p = combine_paths(f_lib_dirs, 'lib' + lib + '.a')
if p:
dst_name = os.path.join(self.build_temp, lib + '.lib')
- copy_file(p[0], dst_name)
- if not lib_added:
+ if not os.path.isfile(dst_name):
+ copy_file(p[0], dst_name)
+ if self.build_temp not in c_library_dirs:
c_library_dirs.append(self.build_temp)
- lib_added = True
def get_source_files (self):
self.check_extensions_list(self.extensions)
Modified: branches/distutils-revamp/command/build_src.py
===================================================================
--- branches/distutils-revamp/command/build_src.py 2007-05-21 13:01:20 UTC (rev 3794)
+++ branches/distutils-revamp/command/build_src.py 2007-05-21 13:15:45 UTC (rev 3795)
@@ -8,6 +8,7 @@
from distutils.command import build_ext
from distutils.dep_util import newer_group, newer
from distutils.util import get_platform
+from distutils.errors import DistutilsError, DistutilsSetupError
try:
from Pyrex.Compiler import Main
@@ -23,6 +24,7 @@
appendpath, is_string, is_sequence
from numpy.distutils.from_template import process_file as process_f_file
from numpy.distutils.conv_template import process_file as process_c_file
+from numpy.distutils.exec_command import splitcmdline
class build_src(build_ext.build_ext):
@@ -30,8 +32,12 @@
user_options = [
('build-src=', 'd', "directory to \"build\" sources to"),
- ('f2pyflags=', None, "additonal flags to f2py"),
- ('swigflags=', None, "additional flags to swig"),
+ ('f2py-opts=', None, "list of f2py command line options"),
+ ('swig=', None, "path to the SWIG executable"),
+ ('swig-opts=', None, "list of SWIG command line options"),
+ ('swig-cpp', None, "make SWIG create C++ files (default is autodetected from sources)"),
+ ('f2pyflags=', None, "additional flags to f2py (use --f2py-opts= instead)"), # obsolete
+ ('swigflags=', None, "additional flags to swig (use --swig-opts= instead)"), # obsolete
('force', 'f', "forcibly build everything (ignore file timestamps)"),
('inplace', 'i',
"ignore build-lib and put compiled extensions into the source " +
@@ -53,8 +59,12 @@
self.force = None
self.inplace = None
self.package_dir = None
- self.f2pyflags = None
- self.swigflags = None
+ self.f2pyflags = None # obsolete
+ self.f2py_opts = None
+ self.swigflags = None # obsolete
+ self.swig_opts = None
+ self.swig_cpp = None
+ self.swig = None
def finalize_options(self):
self.set_undefined_options('build',
@@ -71,23 +81,49 @@
if self.build_src is None:
plat_specifier = ".%s-%s" % (get_platform(), sys.version[0:3])
self.build_src = os.path.join(self.build_base, 'src'+plat_specifier)
- if self.inplace is None:
- build_ext = self.get_finalized_command('build_ext')
- self.inplace = build_ext.inplace
# py_modules_dict is used in build_py.find_package_modules
self.py_modules_dict = {}
- if self.f2pyflags is None:
- self.f2pyflags = []
+ if self.f2pyflags:
+ if self.f2py_opts:
+ log.warn('ignoring --f2pyflags as --f2py-opts already used')
+ else:
+ self.f2py_opts = self.f2pyflags
+ self.f2pyflags = None
+ if self.f2py_opts is None:
+ self.f2py_opts = []
else:
- self.f2pyflags = self.f2pyflags.split() # XXX spaces??
+ self.f2py_opts = splitcmdline(self.f2py_opts)
- if self.swigflags is None:
- self.swigflags = []
+ if self.swigflags:
+ if self.swig_opts:
+ log.warn('ignoring --swigflags as --swig-opts already used')
+ else:
+ self.swig_opts = self.swigflags
+ self.swigflags = None
+
+ if self.swig_opts is None:
+ self.swig_opts = []
else:
- self.swigflags = self.swigflags.split() # XXX spaces??
+ self.swig_opts = splitcmdline(self.swig_opts)
+ # use options from build_ext command
+ build_ext = self.get_finalized_command('build_ext')
+ if self.inplace is None:
+ self.inplace = build_ext.inplace
+ if self.swig_cpp is None:
+ self.swig_cpp = build_ext.swig_cpp
+ for c in ['swig','swig_opt']:
+ o = '--'+c.replace('_','-')
+ v = getattr(build_ext,c,None)
+ if v:
+ if getattr(self,c):
+ log.warn('both build_src and build_ext define %s option' % (o))
+ else:
+ log.info('using "%s=%s" option from build_ext command' % (o,v))
+ setattr(self, c, v)
+
def run(self):
if not (self.extensions or self.libraries):
return
@@ -144,7 +180,7 @@
filenames = get_data_files((d,files))
new_data_files.append((d, filenames))
else:
- raise
+ raise TypeError(repr(data))
self.data_files[:] = new_data_files
def build_py_modules_sources(self):
@@ -354,16 +390,14 @@
output_file=target_file)
pyrex_result = Main.compile(source, options=options)
if pyrex_result.num_errors != 0:
- raise RuntimeError("%d errors in Pyrex compile" %
- pyrex_result.num_errors)
+ raise DistutilsError,"%d errors while compiling %r with Pyrex" \
+ % (pyrex_result.num_errors, source)
elif os.path.isfile(target_file):
- log.warn("Pyrex needed to compile %s but not available."\
- " Using old target %s"\
+ log.warn("Pyrex required for compiling %r but not available,"\
+ " using old target %r"\
% (source, target_file))
else:
- raise SystemError,"Non-existing target %r. "\
- "Perhaps you need to install Pyrex."\
- % (target_file)
+ raise DistutilsError,"Pyrex required for compiling %r but not available" % (source)
new_sources.append(target_file)
else:
new_sources.append(source)
@@ -388,9 +422,9 @@
if os.path.isfile(source):
name = get_f2py_modulename(source)
if name != ext_name:
- raise ValueError('mismatch of extension names: %s '
- 'provides %r but expected %r' % (
- source, name, ext_name))
+ raise DistutilsSetupError('mismatch of extension names: %s '
+ 'provides %r but expected %r' % (
+ source, name, ext_name))
target_file = os.path.join(target_dir,name+'module.c')
else:
log.debug(' source %s does not exist: skipping f2py\'ing.' \
@@ -399,16 +433,16 @@
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))
+ log.warn(' 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')
if not os.path.isfile(target_file):
- raise ValueError("%r missing" % (target_file,))
- log.debug(' Yes! Using %s as up-to-date target.' \
- % (target_file))
+ raise DistutilsSetupError("%r missing" % (target_file,))
+ log.info(' Yes! Using %r as up-to-date target.' \
+ % (target_file))
target_dirs.append(target_dir)
f2py_sources.append(source)
f2py_targets[source] = target_file
@@ -423,7 +457,7 @@
map(self.mkpath, target_dirs)
- f2py_options = extension.f2py_options + self.f2pyflags
+ f2py_options = extension.f2py_options + self.f2py_opts
if self.distribution.libraries:
for name,build_info in self.distribution.libraries:
@@ -434,7 +468,7 @@
if f2py_sources:
if len(f2py_sources) != 1:
- raise ValueError(
+ raise DistutilsSetupError(
'only one .pyf file is allowed per extension module but got'\
' more: %r' % (f2py_sources,))
source = f2py_sources[0]
@@ -472,7 +506,7 @@
% (target_file))
if not os.path.isfile(target_file):
- raise ValueError("%r missing" % (target_file,))
+ raise DistutilsError("f2py target file %r not generated" % (target_file,))
target_c = os.path.join(self.build_src,'fortranobject.c')
target_h = os.path.join(self.build_src,'fortranobject.h')
@@ -494,9 +528,9 @@
self.copy_file(source_h,target_h)
else:
if not os.path.isfile(target_c):
- raise ValueError("%r missing" % (target_c,))
+ raise DistutilsSetupError("f2py target_c file %r not found" % (target_c,))
if not os.path.isfile(target_h):
- raise ValueError("%r missing" % (target_h,))
+ raise DistutilsSetupError("f2py target_h file %r not found" % (target_h,))
for name_ext in ['-f2pywrappers.f','-f2pywrappers2.f90']:
filename = os.path.join(target_dir,ext_name + name_ext)
@@ -516,8 +550,12 @@
target_dirs = []
py_files = [] # swig generated .py files
target_ext = '.c'
- typ = None
- is_cpp = 0
+ if self.swig_cpp:
+ typ = 'c++'
+ is_cpp = True
+ else:
+ typ = None
+ is_cpp = False
skip_swig = 0
ext_name = extension.name.split('.')[-1]
@@ -533,35 +571,43 @@
if os.path.isfile(source):
name = get_swig_modulename(source)
if name != ext_name[1:]:
- raise ValueError(
+ raise DistutilsSetupError(
'mismatch of extension names: %s provides %r'
' but expected %r' % (source, name, ext_name[1:]))
if typ is None:
typ = get_swig_target(source)
is_cpp = typ=='c++'
- if is_cpp:
- target_ext = '.cpp'
+ if is_cpp: target_ext = '.cpp'
else:
- assert typ == get_swig_target(source), repr(typ)
+ typ2 = get_swig_target(source)
+ if typ!=typ2:
+ log.warn('expected %r but source %r defines %r swig target' \
+ % (typ, source, typ2))
+ if typ2=='c++':
+ log.warn('resetting swig target to c++ (some targets may have .c extension)')
+ is_cpp = True
+ target_ext = '.cpp'
+ else:
+ log.warn('assuming that %r has c++ swig target' % (source))
target_file = os.path.join(target_dir,'%s_wrap%s' \
% (name, target_ext))
else:
- log.debug(' source %s does not exist: skipping swig\'ing.' \
+ log.warn(' 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.' \
+ log.warn(' 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)
if not os.path.isfile(target_file):
- raise ValueError("%r missing" % (target_file,))
- log.debug(' Yes! Using %s as up-to-date target.' \
- % (target_file))
+ raise DistutilsSetupError("%r missing" % (target_file,))
+ log.warn(' Yes! Using %r 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'))
@@ -577,7 +623,7 @@
return new_sources + py_files
map(self.mkpath, target_dirs)
- swig = self.find_swig()
+ swig = self.swig or self.find_swig()
swig_cmd = [swig, "-python"]
if is_cpp:
swig_cmd.append('-c++')
@@ -589,7 +635,7 @@
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 \
+ self.spawn(swig_cmd + self.swig_opts \
+ ["-o", target, '-outdir', py_target_dir, source])
else:
log.debug(" skipping '%s' swig interface (up-to-date)" \
Modified: branches/distutils-revamp/command/config.py
===================================================================
--- branches/distutils-revamp/command/config.py 2007-05-21 13:01:20 UTC (rev 3794)
+++ branches/distutils-revamp/command/config.py 2007-05-21 13:15:45 UTC (rev 3795)
@@ -3,56 +3,41 @@
# compilers (they must define linker_exe first).
# Pearu Peterson
-import os, signal, copy
+import os, signal
from distutils.command.config import config as old_config
from distutils.command.config import LANG_EXT
from distutils import log
+from distutils.file_util import copy_file
from numpy.distutils.exec_command import exec_command
-from numpy.distutils.fcompiler import FCompiler, new_fcompiler
LANG_EXT['f77'] = '.f'
LANG_EXT['f90'] = '.f90'
class config(old_config):
old_config.user_options += [
- ('fcompiler=', None,
- "specify the Fortran compiler type"),
+ ('fcompiler=', None, "specify the Fortran compiler type"),
]
def initialize_options(self):
self.fcompiler = None
old_config.initialize_options(self)
- 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'))
- self._fcompiler = None
-
- def run(self):
- self._check_compiler()
-
- def _check_compiler(self):
+ def _check_compiler (self):
old_config._check_compiler(self)
+ from numpy.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()
- def get_fcompiler(self):
- if self._fcompiler is None:
- fc = self.fcompiler.fortran()
- fc.force = 1
- fc.dry_run = self.dry_run
- fc.customize(self.distribution)
- fc.customize_cmd(self)
- fc.show_customization()
- self._fcompiler = fc
- return self._fcompiler
-
- def _wrap_method(self, mth, lang, args):
+ 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.get_fcompiler()
+ if lang in ['f77','f90']:
+ self.compiler = self.fcompiler
try:
ret = mth(*((self,)+args))
except (DistutilsExecError,CompileError),msg:
@@ -68,6 +53,47 @@
def _link (self, body,
headers, include_dirs,
libraries, library_dirs, lang):
+ if self.compiler.compiler_type=='msvc':
+ libraries = (libraries or [])[:]
+ library_dirs = (library_dirs or [])[:]
+ if lang in ['f77','f90']:
+ lang = 'c' # always use system linker when using MSVC compiler
+ if self.fcompiler:
+ for d in self.fcompiler.library_dirs or []:
+ # correct path when compiling in Cygwin but with
+ # normal Win Python
+ if d.startswith('/usr/lib'):
+ s,o = exec_command(['cygpath', '-w', d],
+ use_tee=False)
+ if not s: d = o
+ library_dirs.append(d)
+ for libname in self.fcompiler.libraries or []:
+ if libname not in libraries:
+ libraries.append(libname)
+ for libname in libraries:
+ if libname.startswith('msvc'): continue
+ fileexists = False
+ for libdir in library_dirs or []:
+ libfile = os.path.join(libdir,'%s.lib' % (libname))
+ if os.path.isfile(libfile):
+ fileexists = True
+ break
+ if fileexists: continue
+ # make g77-compiled static libs available to MSVC
+ fileexists = False
+ for libdir in library_dirs:
+ libfile = os.path.join(libdir,'lib%s.a' % (libname))
+ if os.path.isfile(libfile):
+ # copy libname.a file to name.lib so that MSVC linker
+ # can find it
+ libfile2 = os.path.join(libdir,'%s.lib' % (libname))
+ copy_file(libfile, libfile2)
+ self.temp_files.append(libfile2)
+ fileexists = True
+ break
+ if fileexists: continue
+ log.warn('could not find library %r in directories %s' \
+ % (libname, library_dirs))
return self._wrap_method(old_config._link,lang,
(body, headers, include_dirs,
libraries, library_dirs, lang))
Modified: branches/distutils-revamp/command/config_compiler.py
===================================================================
--- branches/distutils-revamp/command/config_compiler.py 2007-05-21 13:01:20 UTC (rev 3794)
+++ branches/distutils-revamp/command/config_compiler.py 2007-05-21 13:15:45 UTC (rev 3795)
@@ -1,81 +1,18 @@
import sys
-import copy
-import distutils.core
from distutils.core import Command
-from distutils.errors import DistutilsSetupError
-from distutils import log
-from numpy.distutils.fcompiler import show_fcompilers, new_fcompiler
+from numpy.distutils import log
-#XXX: Implement confic_cc for enhancing C/C++ compiler options.
#XXX: Linker flags
def show_fortran_compilers(_cache=[]):
# Using cache to prevent infinite recursion
- if _cache:
- return
+ if _cache: return
_cache.append(1)
- show_fcompilers()
+ from numpy.distutils.fcompiler import show_fcompilers
+ import distutils.core
+ dist = distutils.core._setup_distribution
+ show_fcompilers(dist)
-class FCompilerProxy(object):
- """
- A layer of indirection to simplify choosing the correct Fortran compiler.
-
- If need_f90(), f90(), or fortran(requiref90=True) is called at any time,
- a Fortran 90 compiler is found and used for *all* Fortran sources,
- including Fortran 77 sources.
- """
- #XXX The ability to use a separate F77 compiler is likely not
- # necessary: of all the compilers we support, only the 'gnu'
- # compiler (g77) doesn't support F90, and everything else supports
- # both.
-
- def __init__(self, compiler_type, distribution):
- self._fcompiler = None
- self._have_f77 = None
- self._have_f90 = None
- self._compiler_type = compiler_type
- self.distribution = distribution
-
- def _set_fcompiler(self, requiref90=False):
- fc = new_fcompiler(compiler=self._compiler_type,
- dry_run=self.distribution.dry_run,
- verbose=self.distribution.verbose,
- requiref90=requiref90)
- if fc is None:
- raise DistutilsSetupError("could not find a Fortran compiler")
- fc.customize(self.distribution)
- self._fcompiler = fc
- self._have_f77 = fc.compiler_f77 is not None
- if requiref90:
- self._have_f90 = fc.compiler_f90 is not None
- log.info('%s (%s)' % (fc.description, fc.get_version()))
-
- def need_f77(self):
- if self._fcompiler is None:
- self._set_fcompiler(requiref90=False)
- if not self._have_f77:
- raise DistutilsSetupError("could not find a Fortran 77 compiler")
-
- def need_f90(self):
- if self._fcompiler is None or self._have_f90 is None:
- self._set_fcompiler(requiref90=True)
- if not self._have_f90:
- raise DistutilsSetupError("could not find a Fortran 90 compiler")
-
- def f77(self):
- self.need_f77()
- return copy.copy(self._fcompiler)
-
- def f90(self):
- self.need_f90()
- return copy.copy(self._fcompiler)
-
- def fortran(self, requiref90=False):
- if requiref90:
- return self.f90()
- else:
- return self.f77()
-
class config_fc(Command):
""" Distutils command to hold user specified options
to Fortran compilers.
@@ -83,24 +20,19 @@
config_fc command is used by the FCompiler.customize() method.
"""
+ description = "specify Fortran 77/Fortran 90 compiler information"
+
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"),
- ('ldshared=',None,"shared-library linker command"),
- ('ld=',None,"static library linker command"),
- ('ar=',None,"archiver command (ar)"),
- ('ranlib=',None,"ranlib command"),
('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"),
- ('fflags=',None,"extra flags for Fortran compiler"),
- ('ldflags=',None,"linker flags"),
- ('arflags=',None,"flags for ar"),
]
help_options = [
@@ -116,21 +48,77 @@
self.f90exec = None
self.f77flags = None
self.f90flags = None
- self.ldshared = None
- self.ld = None
- self.ar = None
- self.ranlib = None
self.opt = None
self.arch = None
self.debug = None
self.noopt = None
self.noarch = None
- self.fflags = None
- self.ldflags = None
- self.arflags = None
def finalize_options(self):
- self.fcompiler = FCompilerProxy(self.fcompiler, self.distribution)
+ log.info('unifing config_fc, config, build_clib, build_ext, build commands --fcompiler options')
+ build_clib = self.get_finalized_command('build_clib')
+ build_ext = self.get_finalized_command('build_ext')
+ config = self.get_finalized_command('config')
+ build = self.get_finalized_command('build')
+ cmd_list = [self, config, build_clib, build_ext, build]
+ for a in ['fcompiler']:
+ l = []
+ for c in cmd_list:
+ v = getattr(c,a)
+ if v is not None:
+ if not isinstance(v, str): v = v.compiler_type
+ if v not in l: l.append(v)
+ if not l: v1 = None
+ else: v1 = l[0]
+ if len(l)>1:
+ log.warn(' commands have different --%s options: %s'\
+ ', using first in list as default' % (a, l))
+ if v1:
+ for c in cmd_list:
+ if getattr(c,a) is None: setattr(c, a, v1)
def run(self):
- pass
+ # Do nothing.
+ return
+
+class config_cc(Command):
+ """ Distutils command to hold user specified options
+ to C/C++ compilers.
+ """
+
+ description = "specify C/C++ compiler information"
+
+ user_options = [
+ ('compiler=',None,"specify C/C++ compiler type"),
+ ]
+
+ def initialize_options(self):
+ self.compiler = None
+
+ def finalize_options(self):
+ log.info('unifing config_cc, config, build_clib, build_ext, build commands --compiler options')
+ build_clib = self.get_finalized_command('build_clib')
+ build_ext = self.get_finalized_command('build_ext')
+ config = self.get_finalized_command('config')
+ build = self.get_finalized_command('build')
+ cmd_list = [self, config, build_clib, build_ext, build]
+ for a in ['compiler']:
+ l = []
+ for c in cmd_list:
+ v = getattr(c,a)
+ if v is not None:
+ if not isinstance(v, str): v = v.compiler_type
+ if v not in l: l.append(v)
+ if not l: v1 = None
+ else: v1 = l[0]
+ if len(l)>1:
+ log.warn(' commands have different --%s options: %s'\
+ ', using first in list as default' % (a, l))
+ if v1:
+ for c in cmd_list:
+ if getattr(c,a) is None: setattr(c, a, v1)
+ return
+
+ def run(self):
+ # Do nothing.
+ return
Modified: branches/distutils-revamp/core.py
===================================================================
--- branches/distutils-revamp/core.py 2007-05-21 13:01:20 UTC (rev 3794)
+++ branches/distutils-revamp/core.py 2007-05-21 13:15:45 UTC (rev 3795)
@@ -39,6 +39,7 @@
numpy_cmdclass = {'build': build.build,
'build_src': build_src.build_src,
'build_scripts': build_scripts.build_scripts,
+ 'config_cc': config_compiler.config_cc,
'config_fc': config_compiler.config_fc,
'config': config.config,
'build_ext': build_ext.build_ext,
Modified: branches/distutils-revamp/fcompiler/__init__.py
===================================================================
--- branches/distutils-revamp/fcompiler/__init__.py 2007-05-21 13:01:20 UTC (rev 3794)
+++ branches/distutils-revamp/fcompiler/__init__.py 2007-05-21 13:15:45 UTC (rev 3795)
@@ -770,7 +770,6 @@
dist.cmdclass['config_fc'] = config_fc
dist.parse_config_files()
dist.parse_command_line()
-
compilers = []
compilers_na = []
compilers_ni = []
@@ -779,12 +778,14 @@
platform_compilers = available_fcompilers_for_platform()
for compiler in platform_compilers:
v = None
+ log.set_verbosity(-2)
try:
c = new_fcompiler(compiler=compiler, verbose=dist.verbose)
c.customize(dist)
v = c.get_version()
except (DistutilsModuleError, CompilerNotFound):
pass
+
if v is None:
compilers_na.append(("fcompiler="+compiler, None,
fcompiler_class[compiler][2]))
Modified: branches/distutils-revamp/misc_util.py
===================================================================
--- branches/distutils-revamp/misc_util.py 2007-05-21 13:01:20 UTC (rev 3794)
+++ branches/distutils-revamp/misc_util.py 2007-05-21 13:15:45 UTC (rev 3795)
@@ -309,8 +309,9 @@
return [seq]
def get_language(sources):
+ # not used in numpy/scipy packages, use build_ext.detect_language instead
""" Determine language value (c,f77,f90) from sources """
- language = 'c'
+ language = None
for source in sources:
if isinstance(source, str):
if f90_ext_match(source):
@@ -1020,11 +1021,7 @@
ext_args = copy.copy(kw)
ext_args['name'] = dot_join(self.name,name)
ext_args['sources'] = sources
-
- language = ext_args.get('language',None)
- if language is None:
- ext_args['language'] = get_language(sources)
-
+
if ext_args.has_key('extra_info'):
extra_info = ext_args['extra_info']
del ext_args['extra_info']
@@ -1089,10 +1086,6 @@
name = name #+ '__OF__' + self.name
build_info['sources'] = sources
- language = build_info.get('language',None)
- if language is None:
- build_info['language'] = get_language(sources)
-
self._fix_paths_dict(build_info)
self.libraries.append((name,build_info))
Modified: branches/distutils-revamp/system_info.py
===================================================================
--- branches/distutils-revamp/system_info.py 2007-05-21 13:01:20 UTC (rev 3794)
+++ branches/distutils-revamp/system_info.py 2007-05-21 13:15:45 UTC (rev 3795)
@@ -1107,7 +1107,7 @@
self.set_info(**info)
atlas_version_c_text = r'''
-/* This file is generated from numpy_distutils/system_info.py */
+/* This file is generated from numpy/distutils/system_info.py */
void ATL_buildinfo(void);
int main(void) {
ATL_buildinfo();
More information about the Numpy-svn
mailing list