def run(self): if not self.libraries: return # Make sure that library sources are complete. languages = [] # Make sure that extension sources are complete. self.run_command('build_src') for (lib_name, build_info) in self.libraries: l = build_info.get('language', None) if l and l not in languages: languages.append(l) 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()) if self.warn_error: self.compiler.compiler.append('-Werror') self.compiler.compiler_so.append('-Werror') libraries = self.libraries self.libraries = None self.compiler.customize_cmd(self) self.libraries = libraries self.compiler.show_customization() if not self.disable_optimization: dispatch_hpath = os.path.join("numpy", "distutils", "include", "npy_cpu_dispatch_config.h") dispatch_hpath = os.path.join( self.get_finalized_command("build_src").build_src, dispatch_hpath) opt_cache_path = os.path.abspath( os.path.join(self.build_temp, 'ccompiler_opt_cache_clib.py')) self.compiler_opt = new_ccompiler_opt( compiler=self.compiler, dispatch_hpath=dispatch_hpath, cpu_baseline=self.cpu_baseline, cpu_dispatch=self.cpu_dispatch, cache_path=opt_cache_path) if not self.compiler_opt.is_cached(): log.info( "Detected changes on compiler optimizations, force rebuilding" ) self.force = True import atexit def report(): log.info( "\n########### CLIB COMPILER OPTIMIZATION ###########") log.info(self.compiler_opt.report(full=True)) atexit.register(report) if self.have_f_sources(): from numpy.distutils.fcompiler import new_fcompiler self._f_compiler = new_fcompiler(compiler=self.fcompiler, verbose=self.verbose, dry_run=self.dry_run, force=self.force, requiref90='f90' in languages, c_compiler=self.compiler) if self._f_compiler is not None: self._f_compiler.customize(self.distribution) libraries = self.libraries self.libraries = None self._f_compiler.customize_cmd(self) self.libraries = libraries self._f_compiler.show_customization() else: self._f_compiler = None self.build_libraries(self.libraries) if self.inplace: for l in self.distribution.installed_libraries: libname = self.compiler.library_filename(l.name) source = os.path.join(self.build_clib, libname) target = os.path.join(l.target_dir, libname) self.mkpath(l.target_dir) shutil.copy(source, target)
def run(self): if not self.extensions: return # Make sure that extension sources are complete. self.run_command('build_src') if self.distribution.has_c_libraries(): if self.inplace: if self.distribution.have_run.get('build_clib'): log.warn('build_clib already run, it is too late to ' 'ensure in-place build of build_clib') build_clib = self.distribution.get_command_obj( 'build_clib') else: build_clib = self.distribution.get_command_obj( 'build_clib') build_clib.inplace = 1 build_clib.ensure_finalized() build_clib.run() self.distribution.have_run['build_clib'] = 1 else: self.run_command('build_clib') 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. from distutils.ccompiler import new_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) self.compiler.customize_cmd(self) if self.warn_error: self.compiler.compiler.append('-Werror') self.compiler.compiler_so.append('-Werror') self.compiler.show_customization() if not self.disable_optimization: dispatch_hpath = os.path.join("numpy", "distutils", "include", "npy_cpu_dispatch_config.h") dispatch_hpath = os.path.join( self.get_finalized_command("build_src").build_src, dispatch_hpath) opt_cache_path = os.path.abspath( os.path.join(self.build_temp, 'ccompiler_opt_cache_ext.py')) if hasattr(self, "compiler_opt"): # By default `CCompilerOpt` update the cache at the exit of # the process, which may lead to duplicate building # (see build_extension()/force_rebuild) if run() called # multiple times within the same os process/thread without # giving the chance the previous instances of `CCompilerOpt` # to update the cache. self.compiler_opt.cache_flush() self.compiler_opt = new_ccompiler_opt( compiler=self.compiler, dispatch_hpath=dispatch_hpath, cpu_baseline=self.cpu_baseline, cpu_dispatch=self.cpu_dispatch, cache_path=opt_cache_path) def report(copt): log.info("\n########### EXT COMPILER OPTIMIZATION ###########") log.info(copt.report(full=True)) import atexit atexit.register(report, self.compiler_opt) # Setup directory for storing generated extra DLL files on Windows self.extra_dll_dir = os.path.join(self.build_temp, '.libs') 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: for libname, build_info in build_clib.libraries or []: if libname in clibs and clibs[libname] != build_info: log.warn('library %r defined more than once,' ' overwriting build_info\n%s... \nwith\n%s...' % (libname, repr(clibs[libname])[:300], repr(build_info)[:300])) clibs[libname] = build_info # .. and distribution libraries: for libname, build_info in self.distribution.libraries or []: if libname in clibs: # build_clib libraries have a precedence before distribution ones continue clibs[libname] = build_info # 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 libname in clibs: 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 # 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)) if not ext.language: ext.language = ext_language # global language all_languages.update(ext_languages) need_f90_compiler = 'f90' in all_languages need_f77_compiler = 'f77' in all_languages need_cxx_compiler = 'c++' in all_languages # 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 # Initialize Fortran 77 compiler: if need_f77_compiler: ctype = self.fcompiler self._f77_compiler = new_fcompiler(compiler=self.fcompiler, verbose=self.verbose, dry_run=self.dry_run, force=self.force, requiref90=False, c_compiler=self.compiler) fcompiler = self._f77_compiler if fcompiler: ctype = fcompiler.compiler_type fcompiler.customize(self.distribution) if fcompiler and fcompiler.get_version(): fcompiler.customize_cmd(self) fcompiler.show_customization() else: self.warn('f77_compiler=%s is not available.' % (ctype)) self._f77_compiler = None else: self._f77_compiler = None # Initialize Fortran 90 compiler: if need_f90_compiler: ctype = self.fcompiler self._f90_compiler = new_fcompiler(compiler=self.fcompiler, verbose=self.verbose, dry_run=self.dry_run, force=self.force, requiref90=True, c_compiler=self.compiler) fcompiler = self._f90_compiler if fcompiler: ctype = fcompiler.compiler_type fcompiler.customize(self.distribution) if fcompiler and fcompiler.get_version(): fcompiler.customize_cmd(self) fcompiler.show_customization() else: self.warn('f90_compiler=%s is not available.' % (ctype)) self._f90_compiler = None else: self._f90_compiler = None # Build extensions self.build_extensions() # Copy over any extra DLL files # FIXME: In the case where there are more than two packages, # we blindly assume that both packages need all of the libraries, # resulting in a larger wheel than is required. This should be fixed, # but it's so rare that I won't bother to handle it. pkg_roots = { self.get_ext_fullname(ext.name).split('.')[0] for ext in self.extensions } for pkg_root in pkg_roots: shared_lib_dir = os.path.join(pkg_root, '.libs') if not self.inplace: shared_lib_dir = os.path.join(self.build_lib, shared_lib_dir) for fn in os.listdir(self.extra_dll_dir): if not os.path.isdir(shared_lib_dir): os.makedirs(shared_lib_dir) if not fn.lower().endswith('.dll'): continue runtime_lib = os.path.join(self.extra_dll_dir, fn) copy_file(runtime_lib, shared_lib_dir)
def run(self): if not self.libraries: return # Make sure that library sources are complete. languages = [] # Make sure that extension sources are complete. self.run_command('build_src') for (lib_name, build_info) in self.libraries: l = build_info.get('language', None) if l and l not in languages: languages.append(l) 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()) if self.warn_error: self.compiler.compiler.append('-Werror') self.compiler.compiler_so.append('-Werror') libraries = self.libraries self.libraries = None self.compiler.customize_cmd(self) self.libraries = libraries self.compiler.show_customization() if not self.disable_optimization: dispatch_hpath = os.path.join("numpy", "distutils", "include", "npy_cpu_dispatch_config.h") dispatch_hpath = os.path.join( self.get_finalized_command("build_src").build_src, dispatch_hpath) opt_cache_path = os.path.abspath( os.path.join(self.build_temp, 'ccompiler_opt_cache_clib.py')) if hasattr(self, "compiler_opt"): # By default `CCompilerOpt` update the cache at the exit of # the process, which may lead to duplicate building # (see build_extension()/force_rebuild) if run() called # multiple times within the same os process/thread without # giving the chance the previous instances of `CCompilerOpt` # to update the cache. self.compiler_opt.cache_flush() self.compiler_opt = new_ccompiler_opt( compiler=self.compiler, dispatch_hpath=dispatch_hpath, cpu_baseline=self.cpu_baseline, cpu_dispatch=self.cpu_dispatch, cache_path=opt_cache_path) def report(copt): log.info( "\n########### CLIB COMPILER OPTIMIZATION ###########") log.info(copt.report(full=True)) import atexit atexit.register(report, self.compiler_opt) if self.have_f_sources(): from numpy.distutils.fcompiler import new_fcompiler self._f_compiler = new_fcompiler(compiler=self.fcompiler, verbose=self.verbose, dry_run=self.dry_run, force=self.force, requiref90='f90' in languages, c_compiler=self.compiler) if self._f_compiler is not None: self._f_compiler.customize(self.distribution) libraries = self.libraries self.libraries = None self._f_compiler.customize_cmd(self) self.libraries = libraries self._f_compiler.show_customization() else: self._f_compiler = None self.build_libraries(self.libraries) if self.inplace: for l in self.distribution.installed_libraries: libname = self.compiler.library_filename(l.name) source = os.path.join(self.build_clib, libname) target = os.path.join(l.target_dir, libname) self.mkpath(l.target_dir) shutil.copy(source, target)