diff options
Diffstat (limited to 'numpy/distutils/command')
| -rw-r--r-- | numpy/distutils/command/build_clib.py | 42 | ||||
| -rw-r--r-- | numpy/distutils/command/build_ext.py | 70 |
2 files changed, 86 insertions, 26 deletions
diff --git a/numpy/distutils/command/build_clib.py b/numpy/distutils/command/build_clib.py index 594c3f67f..910493a77 100644 --- a/numpy/distutils/command/build_clib.py +++ b/numpy/distutils/command/build_clib.py @@ -12,8 +12,8 @@ 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, \ - get_numpy_include_dirs, get_library_names + has_cxx_sources, all_strings, get_lib_source_files, is_sequence, \ + get_numpy_include_dirs # Fix Python distutils bug sf #1718574: _l = old_build_clib.user_options @@ -131,11 +131,6 @@ class build_clib(old_build_clib): return filenames def build_libraries(self, libraries): - library_names = get_library_names() - library_order = {v: k for k, v in enumerate(library_names)} - libraries = sorted( - libraries, key=lambda library: library_order[library[0]]) - for (lib_name, build_info) in libraries: self.build_a_library(build_info, lib_name, libraries) @@ -292,13 +287,32 @@ class build_clib(old_build_clib): 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) + if f_objects and not fcompiler.can_ccompiler_link(compiler): + # Default linker cannot link Fortran object files, and results + # need to be wrapped later. Instead of creating a real static + # library, just keep track of the object files. + listfn = os.path.join(self.build_clib, + lib_name + '.fobjects') + with open(listfn, 'w') as f: + f.write("\n".join(os.path.abspath(obj) for obj in f_objects)) + + listfn = os.path.join(self.build_clib, + lib_name + '.cobjects') + with open(listfn, 'w') as f: + f.write("\n".join(os.path.abspath(obj) for obj in objects)) + + # create empty "library" file for dependency tracking + lib_fname = os.path.join(self.build_clib, + lib_name + compiler.static_lib_extension) + with open(lib_fname, 'wb') as f: + pass + else: + # assume that default linker is suitable for + # linking Fortran object files + objects.extend(f_objects) + compiler.create_static_lib(objects, lib_name, + output_dir=self.build_clib, + debug=self.debug) # fix library dependencies clib_libraries = build_info.get('libraries', []) diff --git a/numpy/distutils/command/build_ext.py b/numpy/distutils/command/build_ext.py index cf0747d2f..d935a3303 100644 --- a/numpy/distutils/command/build_ext.py +++ b/numpy/distutils/command/build_ext.py @@ -119,6 +119,11 @@ class build_ext (old_build_ext): self.compiler.customize_cmd(self) self.compiler.show_customization() + # Setup directory for storing generated extra DLL files on Windows + self.extra_dll_dir = os.path.join(self.build_temp, 'extra-dll') + if not os.path.isdir(self.extra_dll_dir): + os.makedirs(self.extra_dll_dir) + # Create mapping of libraries built by build_clib: clibs = {} if build_clib is not None: @@ -256,18 +261,16 @@ class build_ext (old_build_ext): # Build extensions self.build_extensions() - shared_libs = system_info.shared_libs - if shared_libs: - runtime_lib_dir = os.path.join( - self.build_lib, self.distribution.get_name(), '_lib') - try: + # Copy over any extra DLL files + runtime_lib_dir = os.path.join( + self.build_lib, self.distribution.get_name(), 'extra-dll') + for fn in os.listdir(self.extra_dll_dir): + if not fn.lower().endswith('.dll'): + continue + if not os.path.isdir(runtime_lib_dir): os.makedirs(runtime_lib_dir) - except OSError: - pass - - for runtime_lib in shared_libs: - if runtime_lib: - copy_file(runtime_lib, runtime_lib_dir) + runtime_lib = os.path.join(self.extra_dll_dir, fn) + copy_file(runtime_lib, runtime_lib_dir) def swig_sources(self, sources): # Do nothing. Swig sources have beed handled in build_src command. @@ -422,7 +425,12 @@ class build_ext (old_build_ext): extra_postargs=extra_postargs, depends=ext.depends) - objects = c_objects + f_objects + if f_objects and not fcompiler.can_ccompiler_link(self.compiler): + unlinkable_fobjects = f_objects + objects = c_objects + else: + unlinkable_fobjects = [] + objects = c_objects + f_objects if ext.extra_objects: objects.extend(ext.extra_objects) @@ -443,6 +451,12 @@ class build_ext (old_build_ext): if ext.language == 'c++' and cxx_compiler is not None: linker = cxx_compiler.link_shared_object + if fcompiler is not None: + objects, libraries = self._process_unlinkable_fobjects( + objects, libraries, + fcompiler, library_dirs, + unlinkable_fobjects) + linker(objects, ext_filename, libraries=libraries, library_dirs=library_dirs, @@ -462,6 +476,38 @@ class build_ext (old_build_ext): self.compiler.create_static_lib( objects, "_gfortran_workaround", output_dir=build_clib, debug=self.debug) + def _process_unlinkable_fobjects(self, objects, libraries, + fcompiler, library_dirs, + unlinkable_fobjects): + libraries = list(libraries) + objects = list(objects) + unlinkable_fobjects = list(unlinkable_fobjects) + + # Expand possible fake static libraries to objects + for lib in list(libraries): + for libdir in library_dirs: + fake_lib = os.path.join(libdir, lib + '.fobjects') + if os.path.isfile(fake_lib): + # Replace fake static library + libraries.remove(lib) + with open(fake_lib, 'r') as f: + unlinkable_fobjects.extend(f.read().splitlines()) + + # Expand C objects + c_lib = os.path.join(libdir, lib + '.cobjects') + with open(c_lib, 'r') as f: + objects.extend(f.read().splitlines()) + + # Wrap unlinkable objects to a linkable one + if unlinkable_fobjects: + fobjects = [os.path.relpath(obj) for obj in unlinkable_fobjects] + wrapped = fcompiler.wrap_unlinkable_objects( + fobjects, output_dir=self.build_temp, + extra_dll_dir=self.extra_dll_dir) + objects.extend(wrapped) + + return objects, libraries + def _libs_with_msvc_and_fortran(self, fcompiler, c_libraries, c_library_dirs): if fcompiler is None: |
