def __init__(self, compiler): self.static_fftw_dir = os.environ.get('STATIC_FFTW_DIR', None) if not os.path.exists(self.static_fftw_dir): raise LinkError('STATIC_FFTW_DIR="%s" was specified but does not exist' % self.static_fftw_dir) # call parent init super(self.__class__, self).__init__(compiler)
def link( self, target_desc, objects, output_filename, output_dir=None, libraries=None, library_dirs=None, runtime_library_dirs=None, export_symbols=None, debug=0, extra_preargs=None, extra_postargs=None, build_temp=None, target_lang=None, ): objects, output_dir = self._fix_object_args(objects, output_dir) libraries, library_dirs, runtime_library_dirs = self._fix_lib_args( libraries, library_dirs, runtime_library_dirs ) lib_opts = gen_lib_options(self, library_dirs, runtime_library_dirs, libraries) if is_string(output_dir): output_filename = os.path.join(output_dir, output_filename) elif output_dir is not None: raise TypeError("'output_dir' must be a string or None") if self._need_link(objects, output_filename): if self.library_switch[-1] == " ": o_args = [self.library_switch.strip(), output_filename] else: o_args = [self.library_switch.strip() + output_filename] if is_string(self.objects): ld_args = objects + [self.objects] else: ld_args = objects + self.objects ld_args = ld_args + lib_opts + o_args if debug: ld_args[:0] = ["-g"] if extra_preargs: ld_args[:0] = extra_preargs if extra_postargs: ld_args.extend(extra_postargs) self.mkpath(os.path.dirname(output_filename)) if target_desc == CCompiler.EXECUTABLE: linker = self.linker_exe[:] else: linker = self.linker_so[:] command = linker + ld_args try: self.spawn(command) except DistutilsExecError: msg = str(get_exception()) raise LinkError(msg) else: log.debug("skipping %s (up-to-date)", output_filename)
def link(self, target_desc, objects, output_filename, output_dir=None, libraries=None, library_dirs=None, runtime_library_dirs=None, export_symbols=None, debug=0, extra_preargs=None, extra_postargs=None, build_temp=None, target_lang=None): objects, output_dir = self._fix_object_args(objects, output_dir) fixed_args = self._fix_lib_args(libraries, library_dirs, runtime_library_dirs) libraries, library_dirs, runtime_library_dirs = fixed_args lib_opts = gen_lib_options(self, library_dirs, runtime_library_dirs, libraries) if not isinstance(output_dir, (str, type(None))): raise TypeError("'output_dir' must be a string or None") if output_dir is not None: output_filename = os.path.join(output_dir, output_filename) if self._need_link(objects, output_filename): ld_args = (objects + self.objects + lib_opts + ['-o', output_filename]) if debug: ld_args[:0] = ['-g'] if extra_preargs: ld_args[:0] = extra_preargs if extra_postargs: ld_args.extend(extra_postargs) self.mkpath(os.path.dirname(output_filename)) try: if target_desc == CCompiler.EXECUTABLE: linker = self.linker_exe[:] else: linker = self.linker_so[:] if target_lang == "c++" and self.compiler_cxx: # skip over environment variable settings if /usr/bin/env # is used to set up the linker's environment. # This is needed on OSX. Note: this assumes that the # normal and C++ compiler have the same environment # settings. i = 0 if os.path.basename(linker[0]) == "env": i = 1 while '=' in linker[i]: i += 1 linker[i] = self.compiler_cxx[i] if sys.platform == 'darwin': linker = _osx_support.compiler_fixup(linker, ld_args) ld_args = ['-arch', 'x86_64'] + ld_args self.spawn(linker + ld_args) except DistutilsExecError as msg: raise LinkError(msg) else: log.debug("skipping %s (up-to-date)", output_filename)
def link(self, target_desc, objects, output_filename, output_dir=None, libraries=None, library_dirs=None, runtime_library_dirs=None, export_symbols=None, debug=0, extra_preargs=None, extra_postargs=None, build_temp=None, target_lang=None): objects, output_dir = self._fix_object_args(objects, output_dir) fixed_args = self._fix_lib_args(libraries, library_dirs, runtime_library_dirs) libraries, library_dirs, runtime_library_dirs = fixed_args lib_opts = gen_lib_options(self, library_dirs, runtime_library_dirs, libraries) if not isinstance(output_dir, (str, type(None))): raise TypeError("'output_dir' must be a string or None") if output_dir is not None: output_filename = os.path.join(output_dir, output_filename) if self._need_link(objects, output_filename): ld_args = objects + self.objects + lib_opts + [ '-o', output_filename ] if debug: ld_args[:0] = ['-g'] if extra_preargs: ld_args[:0] = extra_preargs if extra_postargs: ld_args.extend(extra_postargs) self.mkpath(os.path.dirname(output_filename)) try: if target_desc == CCompiler.EXECUTABLE: linker = self.linker_exe[:] else: linker = self.linker_so[:] if target_lang == 'c++' and self.compiler_cxx: i = 0 if os.path.basename(linker[0]) == 'env': i = 1 while '=' in linker[i]: i += 1 linker[i] = self.compiler_cxx[i] if sys.platform == 'darwin': linker = _osx_support.compiler_fixup(linker, ld_args) self.spawn(linker + ld_args) except DistutilsExecError as msg: raise LinkError(msg) else: log.debug('skipping %s (up-to-date)', output_filename)
def getlibraries(): """Use system information to find lapack, blas libraries""" from distutils.errors import LinkError from numpy.distutils import system_info hasmkl = system_info.get_info("mkl") if hasmkl: return ["mkl_rt"] libraries = ["lapack", "blas"] for lib in libraries: if not system_info.get_info(lib): raise LinkError("Cannot find {} library".format(lib)) return libraries
def link(self, target_desc, objects, output_filename, output_dir=None, libraries=None, library_dirs=None, runtime_library_dirs=None, export_symbols=None, debug=0, extra_preargs=None, extra_postargs= None, build_temp=None, target_lang=None): if not self.initialized: self.initialize() objects, output_dir = self._fix_object_args(objects, output_dir) fixed_args = self._fix_lib_args(libraries, library_dirs, runtime_library_dirs) libraries, library_dirs, runtime_library_dirs = fixed_args if runtime_library_dirs: self.warn( "I don't know what to do with 'runtime_library_dirs': " + str(runtime_library_dirs)) lib_opts = gen_lib_options(self, library_dirs, runtime_library_dirs, libraries) if output_dir is not None: output_filename = os.path.join(output_dir, output_filename) if self._need_link(objects, output_filename): if target_desc == CCompiler.EXECUTABLE: if debug: ldflags = self.ldflags_shared_debug[1:] else: ldflags = self.ldflags_shared[1:] elif debug: ldflags = self.ldflags_shared_debug else: ldflags = self.ldflags_shared export_opts = [] for sym in (export_symbols or []): export_opts.append('/EXPORT:' + sym) ld_args = ldflags + lib_opts + export_opts + objects + ['/OUT:' + output_filename] if export_symbols is not None: dll_name, dll_ext = os.path.splitext(os.path.basename( output_filename)) implib_file = os.path.join(os.path.dirname(objects[0]), self.library_filename(dll_name)) ld_args.append('/IMPLIB:' + implib_file) if extra_preargs: ld_args[:0] = extra_preargs if extra_postargs: ld_args.extend(extra_postargs) self.mkpath(os.path.dirname(output_filename)) try: self.spawn([self.linker] + ld_args) except DistutilsExecError as msg: raise LinkError(msg) else: log.debug('skipping %s (up-to-date)', output_filename)
def link(self, *args, **kwargs): target_desc = args[0] if target_desc == cc.CCompiler.SHARED_OBJECT: self._binpath = self.executables['linker_so'][0] self._linkOpts = self._SharedLinkOpts elif target_desc == cc.CCompiler.EXECUTABLE: self._binpath = self.executables['linker_exe'][0] self._linkOpts = self._exeLinkOpts self._linkOutputOpts = self._outputOpts else: raise LinkError( 'This CCompiler implementation does not know' ' how to link anything except an extension module (that is, a' ' shared object file).') return DCompiler.link(self, *args, **kwargs)
def build_java2cpython(self): sources = self.java2cpython_sources distutils.log.info("building java2cpython library") # First, compile the source code to object files in the library # directory. (This should probably change to putting object # files in a temporary build directory.) include_dirs = \ [sysconfig.get_config_var("INCLUDEPY"), "java"] +\ get_jvm_include_dirs() python_lib_dir, lib_name = self.get_java2cpython_libdest() library_dirs = [python_lib_dir] output_dir = os.path.join(os.path.dirname( self.get_ext_fullpath("javabridge.jars")), "jars") export_symbols = ['Java_org_cellprofiler_javabridge_CPython_exec'] objects = self.compiler.compile(sources, output_dir=self.build_temp, include_dirs=include_dirs, debug=self.debug) ver = sys.version_info needs_manifest = sys.platform == 'win32' and ver.major == 2 and not is_mingw extra_postargs = ["/MANIFEST"] if needs_manifest else None libraries = ["python{}{}".format(ver.major, ver.minor)] if is_mingw else None self.compiler.link( CCompiler.SHARED_OBJECT, objects, lib_name, output_dir=output_dir, debug=self.debug, library_dirs=library_dirs, libraries=libraries, export_symbols=export_symbols, extra_postargs=extra_postargs) if needs_manifest: temp_dir = os.path.dirname(objects[0]) manifest_name = lib_name +".manifest" lib_path = os.path.join(output_dir, lib_name) manifest_file = os.path.join(temp_dir, manifest_name) lib_path = os.path.abspath(lib_path) manifest_file = os.path.abspath(manifest_file) out_arg = '-outputresource:%s;2' % lib_path try: self.compiler.spawn([ 'mt.exe', '-nologo', '-manifest', manifest_file, out_arg]) except DistutilsExecError as msg: raise LinkError(msg)
def link_osx(self, target_desc, objects, output_filename, output_dir=None, libraries=None, library_dirs=None, runtime_library_dirs=None, export_symbols=None, debug=0, extra_preargs=None, extra_postargs=None, build_temp=None, target_lang=None): """Link the objects.""" # use separate copies, so we can modify the lists libraries = copy.copy(libraries or []) libraries.extend(self.dll_libraries) # Copy of unix link so we can remove the darwin test #UnixCCompiler.link(self, target_desc, objects, output_filename, # output_dir, libraries, library_dirs, runtime_library_dirs, # None, # export_symbols, we do this in our def-file # debug, extra_preargs, extra_postargs, build_temp, target_lang) objects, output_dir = self._fix_object_args(objects, output_dir) libraries, library_dirs, runtime_library_dirs = \ self._fix_lib_args(libraries, library_dirs, runtime_library_dirs) lib_opts = gen_lib_options(self, library_dirs, runtime_library_dirs, libraries) #if type(output_dir) not in (StringType, NoneType): # raise TypeError("'output_dir' must be a string or None") if output_dir is not None: output_filename = os.path.join(output_dir, output_filename) if self._need_link(objects, output_filename): ld_args = (objects + self.objects + lib_opts + ['-o', output_filename]) if debug: ld_args[:0] = ['-g'] if extra_preargs: ld_args[:0] = extra_preargs if extra_postargs: ld_args.extend(extra_postargs) self.mkpath(os.path.dirname(output_filename)) try: if target_desc == CCompiler.EXECUTABLE: linker = self.linker_exe[:] else: linker = self.linker_so[:] if target_lang == "c++" and self.compiler_cxx: # skip over environment variable settings if /usr/bin/env # is used to set up the linker's environment. # This is needed on OSX. Note: this assumes that the # normal and C++ compiler have the same environment # settings. i = 0 if os.path.basename(linker[0]) == "env": i = 1 while '=' in linker[i]: i = i + 1 linker[i] = self.compiler_cxx[i] #if sys.platform == 'darwin': # linker = _osx_support.compiler_fixup(linker, ld_args) # ld_args = ['-arch', 'x86_64'] + ld_args self.spawn(linker + ld_args) except DistutilsExecError as msg: raise LinkError(msg) else: log.debug("skipping %s (up-to-date)", output_filename)
def link(self, target_desc, objects, output_filename, output_dir=None, libraries=None, library_dirs=None, runtime_library_dirs=None, export_symbols=None, debug=0, extra_preargs=None, extra_postargs=None, build_temp=None, target_lang=None): objects, output_dir = self._fix_object_args(objects, output_dir) fixed_args = self._fix_lib_args(libraries, library_dirs, runtime_library_dirs) libraries, library_dirs, runtime_library_dirs = fixed_args lib_opts = gen_lib_options(self, library_dirs, runtime_library_dirs, libraries) if not isinstance(output_dir, (str, type(None))): raise TypeError("'output_dir' must be a string or None") if output_dir is not None: output_filename = os.path.join(output_dir, output_filename) if self._need_link(objects, output_filename): ld_args = (objects + self.objects + lib_opts + ['-o', output_filename]) if debug: ld_args[:0] = ['-g'] if extra_preargs: ld_args[:0] = extra_preargs if extra_postargs: ld_args.extend(extra_postargs) self.mkpath(os.path.dirname(output_filename)) try: if target_desc == CCompiler.EXECUTABLE: linker = self.linker_exe[:] else: linker = self.linker_so[:] if target_lang == "c++" and self.compiler_cxx: # skip over environment variable settings if /usr/bin/env # is used to set up the linker's environment. # This is needed on OSX. Note: this assumes that the # normal and C++ compiler have the same environment # settings. i = 0 if os.path.basename(linker[0]) == "env": i = 1 while '=' in linker[i]: i += 1 if os.path.basename(linker[i]) == 'ld_so_aix': # AIX platforms prefix the compiler with the ld_so_aix # script, so we need to adjust our linker index offset = 1 else: offset = 0 linker[i+offset] = self.compiler_cxx[i] if sys.platform == 'darwin': linker = _osx_support.compiler_fixup(linker, ld_args) # iOS: since clang is not available, we send a nicer error message: if (sys.platform == 'darwin' and os.uname().machine.startswith('iP')): raise DistutilsExecError("There are no linkers available on iOS, sorry.") self.spawn(linker + ld_args) except DistutilsExecError as msg: raise LinkError(msg) else: log.debug("skipping %s (up-to-date)", output_filename)
def search_dependencies(self): # lib_checks = {} data_types = ['DOUBLE', 'SINGLE', 'LONG'] data_types_short = ['', 'f', 'l'] lib_types = ['', 'THREADS', 'OMP'] functions = ['plan_dft', 'init_threads', 'init_threads'] if self.support_mpi: lib_types.append('MPI') functions.append('mpi_init') for d, s in zip(data_types, data_types_short): # first check for serial library... basic_lib = self.check('', 'plan_dft', d, s, True) self.add_library(basic_lib) # ...then multithreading: link check with threads requires # the serial library. Both omp and posix define the same # function names. Prefer openmp if linking dynamically, # else fall back to pthreads. pthreads can be prioritized over # openmp by defining the environment variable PYFFTW_USE_PTHREADS if 'PYFFTW_USE_PTHREADS' not in os.environ: # openmp requires special linker treatment self.linker_flags.append(self.openmp_linker_flag()) lib_omp = self.check( 'OMP', 'init_threads', d, s, basic_lib and not hasattr(self, 'static_fftw_dir')) if lib_omp: self.add_library(lib_omp) # manually set flag because it won't be checked below self.compile_time_env[self.HAVE(d, 'THREADS')] = False else: self.linker_flags.pop() else: lib_omp = False self.compile_time_env[self.HAVE(d, 'OMP')] = False if lib_omp: self.compile_time_env[self.HAVE(d, 'THREADS')] = False if not lib_omp: # -pthread added for gcc/clang when checking for threads self.linker_flags.append(self.pthread_linker_flag()) lib_pthread = self.check('THREADS', 'init_threads', d, s, basic_lib) if lib_pthread: self.add_library(lib_pthread) else: self.linker_flags.pop() # On windows, the serial and posix threading functions are # build into one library as released on fftw.org. openMP # and MPI are not supported in the releases if get_platform() in ('win32', 'win-amd64'): if basic_lib: self.compile_time_env[self.HAVE(d, 'THREADS')] = True # check whatever multithreading is available self.compile_time_env[self.HAVE( d, 'MULTITHREADING')] = self.compile_time_env[self.HAVE( d, 'OMP')] or self.compile_time_env[self.HAVE( d, 'THREADS')] # check MPI only if headers were found self.add_library( self.check('MPI', 'mpi_init', d, s, basic_lib and self.support_mpi)) # compile only if mpi.h *and* one of the fftw mpi libraries are found if self.support_mpi: found_mpi_types = [] for d in data_types: if self.compile_time_env['HAVE_' + d + '_MPI']: found_mpi_types.append(d) else: self.compile_time_env['HAVE_MPI'] = False # Pretend FFTW precision not available, regardless if it was found or # not. Useful for testing that pyfftw still works without requiring all # precisions if 'PYFFTW_IGNORE_SINGLE' in os.environ: self.compile_time_env['HAVE_SINGLE'] = False if 'PYFFTW_IGNORE_DOUBLE' in os.environ: self.compile_time_env['HAVE_DOUBLE'] = False if 'PYFFTW_IGNORE_LONG' in os.environ: self.compile_time_env['HAVE_LONG'] = False log.debug(repr(self.compile_time_env)) # required package: FFTW itself have_fftw = False for d in data_types: have_fftw |= self.compile_time_env['HAVE_' + d] if not have_fftw: raise LinkError("Could not find any of the FFTW libraries") log.info('Build pyFFTW with support for FFTW with') for d in data_types: if not self.compile_time_env[self.HAVE(d)]: continue s = d.lower() + ' precision' if self.compile_time_env[self.HAVE(d, 'OMP')]: s += ' + openMP' elif self.compile_time_env[self.HAVE(d, 'THREADS')]: s += ' + pthreads' if self.compile_time_env[self.HAVE(d, 'MPI')]: s += ' + MPI' log.info(s)
def link(self, target_desc, objects, output_filename, output_dir=None, libraries=None, library_dirs=None, runtime_library_dirs=None, export_symbols=None, debug=0, extra_preargs=None, extra_postargs=None, build_temp=None, target_lang=None): objects, output_dir = self._fix_object_args(objects, output_dir) fixed_args = self._fix_lib_args(libraries, library_dirs, runtime_library_dirs) libraries, library_dirs, runtime_library_dirs = fixed_args # lib_opts = gen_lib_options(self, library_dirs, runtime_library_dirs, # libraries) if not isinstance(output_dir, (str, type(None))): raise TypeError("'output_dir' must be a string or None") if output_dir is not None: output_filename = os.path.join(output_dir, output_filename) if self._need_link(objects, output_filename): # ld_args = (objects + self.objects + # lib_opts + [link_output_qualifier, output_filename]) opt_file = tempfile.NamedTemporaryFile(suffix='.OPT', delete=False) opt_lines = [] for obj_file in objects: obj_file_vms = vms.decc.to_vms(obj_file, 0, 0)[0] opt_lines.append(obj_file_vms) vms_libraries_set = set() verbose = False # True # '_multiarray_umath' in output_filename for lib_file in libraries: lib_file_vms = None _, lib_file_ext = os.path.splitext(lib_file) if lib_file_ext: # looks like full path lib_file_ext = lib_file_ext.upper() if lib_file_ext in ('.OLB', '.EXE'): if re.search(r'[:\[\]]', lib_file): lib_file_vms = lib_file else: lib_file_vms = vms.decc.to_vms(lib_file, 0, 0)[0] if not lib_file_vms: # find the library in the library_dirs for lib_dir in library_dirs: for lib_ext in ['', '.OLB', '.EXE']: try: lib_path = os.path.join( lib_dir, lib_file + lib_ext) st = os.stat(lib_path) if not stat.S_ISDIR(st.st_mode): lib_file_ext = lib_ext lib_file_vms = vms.decc.to_vms( lib_path, 0, 0)[0] break except: pass else: continue break if lib_file_vms and lib_file_vms.lower( ) not in vms_libraries_set: # write it to the OPT opt_line = lib_file_vms + ('/LIBRARY' if lib_file_ext == '.OLB' else '/SHAREABLE') opt_lines.append(opt_line) vms_libraries_set.add(lib_file_vms.lower()) opt_lines.append('GSMATCH=LEQUAL,1,0') opt_lines.append('CASE_SENSITIVE=YES') proc_names = dict() try: repository = open('CXX_REPOSITORY/CXX$DEMANGLER_DB') for line in repository: full_name = line[31:-1] short_name = line[:31] proc_names[full_name] = short_name repository.close() except: pass def shorten_name(name): if len(name) <= 31: return name try: return proc_names[name] except: return name[:31] if export_symbols and len(export_symbols): opt_lines.append('SYMBOL_VECTOR=( -') for export_symbol in export_symbols[:-1]: opt_lines.append( shorten_name(export_symbol) + '=PROCEDURE, -') for export_symbol in export_symbols[-1:]: opt_lines.append( shorten_name(export_symbol) + '=PROCEDURE )') if verbose: print("--- OPT START\n") print('\n'.join(opt_lines)) print("--- OPT END\n") opt_file.write(('\n'.join(opt_lines)).encode()) opt_file.close() opt_name_vms = vms.decc.to_vms(opt_file.name, 0, 0)[0] link_output_qualifier = '/EXECUTABLE=' if target_desc == CCompiler.EXECUTABLE else '/SHAREABLE=' output_filename_vms = vms.decc.to_vms(output_filename, 0, 0)[0] ld_args = [ link_output_qualifier + output_filename_vms, opt_name_vms + "/OPTIONS" ] if debug: map_file, _ = os.path.splitext(output_filename) map_file_vms = vms.decc.to_vms(map_file + '.MAP', 0, 0)[0] ld_args[:0] = ['/DEBUG/MAP=' + map_file_vms] if extra_preargs: ld_args[:0] = extra_preargs if extra_postargs: ld_args.extend(extra_postargs) self.mkpath(os.path.dirname(output_filename)) try: linker = self.linker[:] self.spawn(linker + ld_args) except DistutilsExecError as msg: raise LinkError(msg) finally: os.unlink(opt_file.name) else: log.debug("skipping %s (up-to-date)", output_filename)
def link( self, target_desc, objects, output_filename, output_dir=None, libraries=None, library_dirs=None, runtime_library_dirs=None, export_symbols=None, debug=0, extra_preargs=None, extra_postargs=None, build_temp=None, target_lang=None, ): if not self.initialized: self.initialize() (objects, output_dir) = self._fix_object_args(objects, output_dir) fixed_args = self._fix_lib_args(libraries, library_dirs, runtime_library_dirs) (libraries, library_dirs, runtime_library_dirs) = fixed_args if runtime_library_dirs: self.warn("I don't know what to do with 'runtime_library_dirs': " + str(runtime_library_dirs)) lib_opts = gen_lib_options(self, library_dirs, runtime_library_dirs, libraries) if output_dir is not None: output_filename = os.path.join(output_dir, output_filename) if self._need_link(objects, output_filename): if target_desc == CCompiler.EXECUTABLE: if debug: ldflags = self.ldflags_shared_debug[1:] else: ldflags = self.ldflags_shared[1:] else: if debug: ldflags = self.ldflags_shared_debug else: ldflags = self.ldflags_shared export_opts = [] for sym in export_symbols or []: export_opts.append("/EXPORT:" + sym) ld_args = (ldflags + lib_opts + export_opts + objects + ["/OUT:" + output_filename]) # The MSVC linker generates .lib and .exp files, which cannot be # suppressed by any linker switches. The .lib files may even be # needed! Make sure they are generated in the temporary build # directory. Since they have different names for debug and release # builds, they can go into the same directory. build_temp = os.path.dirname(objects[0]) if export_symbols is not None: (dll_name, dll_ext) = os.path.splitext(os.path.basename(output_filename)) implib_file = os.path.join(build_temp, self.library_filename(dll_name)) ld_args.append("/IMPLIB:" + implib_file) self.manifest_setup_ldargs(output_filename, build_temp, ld_args) if extra_preargs: ld_args[:0] = extra_preargs if extra_postargs: ld_args.extend(extra_postargs) self.mkpath(os.path.dirname(output_filename)) try: self.spawn([self.linker] + ld_args) except DistutilsExecError as msg: raise LinkError(msg) # embed the manifest # XXX - this is somewhat fragile - if mt.exe fails, distutils # will still consider the DLL up-to-date, but it will not have a # manifest. Maybe we should link to a temp file? OTOH, that # implies a build environment error that shouldn't go undetected. mfinfo = self.manifest_get_embed_info(target_desc, ld_args) if mfinfo is not None: mffilename, mfid = mfinfo out_arg = "-outputresource:%s;%s" % (output_filename, mfid) try: self.spawn([ "mt.exe", "-nologo", "-manifest", mffilename, out_arg ]) except DistutilsExecError as msg: raise LinkError(msg) else: log.debug("skipping %s (up-to-date)", output_filename)
def link(self, target_desc, objects, output_filename, output_dir=None, libraries=None, library_dirs=None, runtime_library_dirs=None, export_symbols=None, debug=0, extra_preargs=None, extra_postargs=None, build_temp=None, target_lang=None): if not self.initialized: self.initialize() (objects, output_dir) = self._fix_object_args(objects, output_dir) fixed_args = self._fix_lib_args(libraries, library_dirs, runtime_library_dirs) (libraries, library_dirs, runtime_library_dirs) = fixed_args if runtime_library_dirs: self.warn("I don't know what to do with 'runtime_library_dirs': " + str(runtime_library_dirs)) lib_opts = gen_lib_options(self, library_dirs, runtime_library_dirs, libraries) if output_dir is not None: output_filename = os.path.join(output_dir, output_filename) if self._need_link(objects, output_filename): if target_desc == CCompiler.EXECUTABLE: if debug: ldflags = self.ldflags_shared_debug[1:] else: ldflags = self.ldflags_shared[1:] else: if debug: ldflags = self.ldflags_shared_debug else: ldflags = self.ldflags_shared export_opts = [] for sym in (export_symbols or []): export_opts.append("/EXPORT:" + sym) ld_args = (ldflags + lib_opts + export_opts + objects + ['/OUT:' + output_filename]) # The MSVC linker generates .lib and .exp files, which cannot be # suppressed by any linker switches. The .lib files may even be # needed! Make sure they are generated in the temporary build # directory. Since they have different names for debug and release # builds, they can go into the same directory. build_temp = os.path.dirname(objects[0]) if export_symbols is not None: (dll_name, dll_ext) = os.path.splitext(os.path.basename(output_filename)) implib_file = os.path.join(build_temp, self.library_filename(dll_name)) ld_args.append('/IMPLIB:' + implib_file) # Embedded manifests are recommended - see MSDN article titled # "How to: Embed a Manifest Inside a C/C++ Application" # (currently at http://msdn2.microsoft.com/en-us/library/ms235591(VS.80).aspx) # Ask the linker to generate the manifest in the temp dir, so # we can embed it later. temp_manifest = os.path.join( build_temp, os.path.basename(output_filename) + ".manifest") ld_args.append('/MANIFESTFILE:' + temp_manifest) if extra_preargs: ld_args[:0] = extra_preargs if extra_postargs: ld_args.extend(extra_postargs) self.mkpath(os.path.dirname(output_filename)) try: self.spawn([self.linker] + ld_args) except DistutilsExecError as msg: raise LinkError(msg) # embed the manifest # XXX - this is somewhat fragile - if mt.exe fails, distutils # will still consider the DLL up-to-date, but it will not have a # manifest. Maybe we should link to a temp file? OTOH, that # implies a build environment error that shouldn't go undetected. if target_desc == CCompiler.EXECUTABLE: mfid = 1 else: mfid = 2 try: # Remove references to the Visual C runtime, so they will # fall through to the Visual C dependency of Python.exe. # This way, when installed for a restricted user (e.g. # runtimes are not in WinSxS folder, but in Python's own # folder), the runtimes do not need to be in every folder # with .pyd's. manifest_f = open(temp_manifest, "rb") manifest_buf = manifest_f.read() manifest_f.close() pattern = re.compile( r"""<assemblyIdentity.*?name=("|')Microsoft\."""\ r"""VC\d{2}\.CRT("|').*?(/>|</assemblyIdentity>)""", re.DOTALL) manifest_buf = re.sub(pattern, "", manifest_buf) pattern = "<dependentAssembly>\s*</dependentAssembly>" manifest_buf = re.sub(pattern, "", manifest_buf) manifest_f = open(temp_manifest, "wb") manifest_f.write(manifest_buf) manifest_f.close() except IOError: pass out_arg = '-outputresource:%s;%s' % (output_filename, mfid) try: self.spawn( ['mt.exe', '-nologo', '-manifest', temp_manifest, out_arg]) except DistutilsExecError as msg: raise LinkError(msg) else: log.debug("skipping %s (up-to-date)", output_filename)
def link(self, target_desc, objects, output_filename, output_dir=None, libraries=None, library_dirs=None, runtime_library_dirs=None, export_symbols=None, debug=0, extra_preargs=None, extra_postargs=None, build_temp=None, target_lang=None): objects, output_dir = self._fix_object_args(objects, output_dir) libraries, library_dirs, runtime_library_dirs = self._fix_lib_args( libraries, library_dirs, runtime_library_dirs) if runtime_library_dirs: log.warn("I don't know what to do with 'runtime_library_dirs': %s", str(runtime_library_dirs)) if output_dir is not None: output_filename = os.path.join(output_dir, output_filename) if self._need_link(objects, output_filename): if target_desc == CCompiler.EXECUTABLE: startup_obj = 'c0w32' if debug: ld_args = self.ldflags_exe_debug[:] else: ld_args = self.ldflags_exe[:] else: startup_obj = 'c0d32' if debug: ld_args = self.ldflags_shared_debug[:] else: ld_args = self.ldflags_shared[:] if export_symbols is None: def_file = '' else: head, tail = os.path.split(output_filename) modname, ext = os.path.splitext(tail) temp_dir = os.path.dirname(objects[0]) def_file = os.path.join(temp_dir, '%s.def' % modname) contents = ['EXPORTS'] for sym in (export_symbols or []): contents.append(' %s=_%s' % (sym, sym)) self.execute(write_file, (def_file, contents), 'writing %s' % def_file) objects2 = map(os.path.normpath, objects) objects = [startup_obj] resources = [] for file in objects2: base, ext = os.path.splitext(os.path.normcase(file)) if ext == '.res': resources.append(file) else: objects.append(file) for l in library_dirs: ld_args.append('/L%s' % os.path.normpath(l)) ld_args.append('/L.') ld_args.extend(objects) ld_args.extend([',', output_filename]) ld_args.append(',,') for lib in libraries: libfile = self.find_library_file(library_dirs, lib, debug) if libfile is None: ld_args.append(lib) else: ld_args.append(libfile) ld_args.append('import32') ld_args.append('cw32mt') ld_args.extend([',', def_file]) ld_args.append(',') ld_args.extend(resources) if extra_preargs: ld_args[:0] = extra_preargs if extra_postargs: ld_args.extend(extra_postargs) self.mkpath(os.path.dirname(output_filename)) try: self.spawn([self.linker] + ld_args) except DistutilsExecError as msg: raise LinkError(msg) else: log.debug('skipping %s (up-to-date)', output_filename)
def run(self): global have_greenlet global have_good_greenlet if not have_stackless and not have_good_greenlet: if have_greenlet: log.info( 'no stackless found, but found old (unusable) greenlet') else: log.info('no stackless or greenlet found') log.info( 'attempting to download and compile greenlet with easy_install' ) install_purelib = self.get_finalized_command( 'install').install_purelib # Not created yet: #so_ext = command_obj.get_finalized_command( # 'build_ext').compiler.shared_lib_extension from distutils.ccompiler import new_compiler so_ext = new_compiler().shared_lib_extension # '.so' from distutils.file_util import copy_file from distutils.dir_util import remove_tree from distutils.dir_util import copy_tree # TODO(pts): Auto-detect pip (is it calling us, setup.py?) and try pip. try: from setuptools.command import easy_install except ImportError: easy_install = None if not easy_install: raise LinkError( 'neither stackless or greenlet found, ' 'and easy_install was not found either to install them, ' 'see the Installation section of README.txt') old_log_level = log._global_log.threshold mkpath('tmp') greenlet_file_pattern = 'tmp/greenlet-*.egg' for filename in glob.glob(greenlet_file_pattern): remove_tree(filename) if easy_install.main( ['-dtmp', '-m', '-U', '-Z', 'greenlet>=0.3.1']): # We usually won't reach this, easy_install calls sys.exit. raise DistutilsError('installation of greenlet failed') # Restore values overridden by easy_install.main. # See also setuptools.dist for overriding Distribution. log.set_threshold(old_log_level) for module in ('distutils.dist', 'distutils.core', 'distutils.cmd'): __import__(module, {}, {}, ('', )).Distribution = Distribution for module in ('distutils.core', 'distutils.extension', 'distutils.command.build_ext'): __import__(module, {}, {}, ('', )).Extension = Extension # Now extract greenlet.so from tmp/greenlet-*.egg log.info('extracting greenlet from its egg and installing it') greenlet_file_names = glob.glob(greenlet_file_pattern) if (len(greenlet_file_names) != 1 or not os.path.isdir(greenlet_file_names[0])): raise DistutilsError('could not find any of: %s' % greenlet_file_pattern) greenlet_so = 'greenlet' + so_ext copy_file(os.path.join(greenlet_file_names[0], greenlet_so), install_purelib) egg_info_dir = (os.path.join( install_purelib, '-'.join( os.path.basename(greenlet_file_names[0]).split('-')[:-2])) + '.egg-info') if os.path.isfile(os.path.join(egg_info_dir, 'PKG-INFO')): remove_tree(egg_info_dir) copy_tree(os.path.join(greenlet_file_names[0], 'EGG-INFO'), egg_info_dir) sys.modules.pop('greenlet', None) try: import greenlet have_greenlet = True have_good_greenlet = IsGoodGreenlet(greenlet) except ImportError: raise LinkError( 'neither stackless or greenlet found, ' 'and could not import greenlet after easy_install, ' 'see the Installation section of README.txt')
def link(target_desc, objects, output_filename, output_dir=None, libraries=None, library_dirs=None, runtime_library_dirs=None, export_symbols=None, debug=0, extra_preargs=None, extra_postargs=None, build_temp=None, target_lang=None): if not self.initialized: self.initialize() objects, output_dir = self._fix_object_args(objects, output_dir) fixed_args = self._fix_lib_args(libraries, library_dirs, runtime_library_dirs) libraries, library_dirs, runtime_library_dirs = fixed_args if runtime_library_dirs: self.warn( "I don't know what to do with 'runtime_library_dirs': " + str(runtime_library_dirs)) lib_opts = gen_lib_options(self, library_dirs, runtime_library_dirs, libraries) if output_dir is not None: output_filename = os.path.join(output_dir, output_filename) if self._need_link(objects, output_filename): ldflags = self._ldflags[target_desc, debug] export_opts = [ "/EXPORT:" + sym for sym in (export_symbols or []) ] ld_args = (ldflags + lib_opts + export_opts + objects + ['/OUT:' + output_filename]) # The MSVC linker generates .lib and .exp files, which cannot be # suppressed by any linker switches. The .lib files may even be # needed! Make sure they are generated in the temporary build # directory. Since they have different names for debug and release # builds, they can go into the same directory. build_temp = os.path.dirname(objects[0]) if export_symbols is not None: (dll_name, dll_ext) = os.path.splitext( os.path.basename(output_filename)) implib_file = os.path.join(build_temp, self.library_filename(dll_name)) ld_args.append('/IMPLIB:' + implib_file) if extra_preargs: ld_args[:0] = extra_preargs if extra_postargs: ld_args.extend(extra_postargs) output_dir = os.path.dirname(os.path.abspath(output_filename)) self.mkpath(output_dir) try: ld_args.append("/NODEFAULTLIB:LIBCMT") log.debug('Executing "%s" %s', self.linker, ' '.join(ld_args)) self.spawn([self.linker] + ld_args) self._copy_vcruntime(output_dir) except DistutilsExecError as msg: print('-----', ld_args) raise LinkError(msg) else: log.debug("skipping %s (up-to-date)", output_filename)
def link( self, target_desc, objects, output_filename, output_dir=None, libraries=None, library_dirs=None, runtime_library_dirs=None, export_symbols=None, debug=0, extra_preargs=None, extra_postargs=None, build_temp=None, target_lang=None, ): objects, output_dir = self._fix_object_args(objects, output_dir) fixed_args = self._fix_lib_args(libraries, library_dirs, runtime_library_dirs) libraries, library_dirs, runtime_library_dirs = fixed_args lib_opts = gen_lib_options(self, library_dirs, runtime_library_dirs, libraries) if not isinstance(output_dir, (str, type(None))): raise TypeError("'output_dir' must be a string or None") if output_dir is not None: output_filename = os.path.join(output_dir, output_filename) if self._need_link(objects, output_filename): ld_args = objects + self.objects + lib_opts + [ '-o', output_filename ] if debug: ld_args[:0] = ['-g'] if extra_preargs: ld_args[:0] = extra_preargs if extra_postargs: ld_args.extend(extra_postargs) self.mkpath(os.path.dirname(output_filename)) try: # Select a linker based on context: linker_exe when # building an executable or linker_so (with shared options) # when building a shared library. building_exe = target_desc == CCompiler.EXECUTABLE linker = (self.linker_exe if building_exe else self.linker_so)[:] if target_lang == "c++" and self.compiler_cxx: env, linker_ne = _split_env(linker) aix, linker_na = _split_aix(linker_ne) _, compiler_cxx_ne = _split_env(self.compiler_cxx) _, linker_exe_ne = _split_env(self.linker_exe) params = _linker_params(linker_na, linker_exe_ne) linker = env + aix + compiler_cxx_ne + params linker = compiler_fixup(linker, ld_args) self.spawn(linker + ld_args) except DistutilsExecError as msg: raise LinkError(msg) else: log.debug("skipping %s (up-to-date)", output_filename)
def AutoDetect(command_obj): """Auto detect compilation information for a C extension. Args: command_obj: Any distutils.command object. """ # We could add more directories (e.g. those in /etc/ld.so.conf), but that's # system-specific, see http://stackoverflow.com/questions/2230467 . # TODO(pts): Issue a fatal error if libev or libevhdns was not found. # TODO(pts): Find libevhdns separately. retval = { 'include_dirs': [], 'library_dirs': [], 'libraries': [], 'define_macros': [], 'is_found': False, 'sources': [], 'depends': [] } if have_stackless: retval['define_macros'].append(('COIO_USE_CO_STACKLESS', None)) elif have_greenlet: if not have_good_greenlet: raise LinkError('detected old (unusable) version of greenlet, ' 'see the Installation section of README.txt') retval['define_macros'].append(('COIO_USE_CO_GREENLET', None)) else: raise LinkError('neither stackless or greenlet found, ' 'see the Installation section of README.txt') compiler = GetCompiler(command_obj) prefixes = filter( bool, os.getenv('LD_LIBRARY_PATH', '').split(':') + [sys.prefix, '/usr/local', '/usr']) is_found = False is_asked = False event_driver = None if os.getenv('SYNCLESS_USE_LIBEV', ''): assert event_driver is None event_driver = 'libev' if os.getenv('SYNCLESS_USE_LIBEVENT1', ''): assert event_driver is None event_driver = 'libevent1' if os.getenv('SYNCLESS_USE_LIBEVENT2', ''): assert event_driver is None event_driver = 'libevent2' if os.getenv('SYNCLESS_USE_MINIEVENT', ''): assert event_driver is None event_driver = 'minievent' asked_for_libevhdns = bool(os.getenv('SYNCLESS_USE_LIBEVHDNS', '')) allowed_minievent = bool(os.getenv('SYNCLESS_ALLOW_MINIEVENT', '1')) if event_driver in (None, 'libev'): if FindLib(retval=retval, compiler=compiler, prefixes=prefixes, includes=['ev.h'], library='ev', symbols=['ev_once']): if asked_for_libevhdns: if not FindLib(retval=retval, compiler=compiler, prefixes=prefixes, includes=[()], library='evhdns', symbols=['evdns_resolve_ipv4'], link_with_prev_libraries=['ev']): raise LinkError('evhdns not found') retval['define_macros'].append(('COIO_USE_LIBEVHDNS', None)) retval['libraries'].append('evhdns') else: retval['define_macros'].append(('COIO_USE_MINIHDNS', None)) retval['sources'].append('coio_src/coio_minihdns.c') event_driver = 'libev' retval['is_found'] = True retval['libraries'].append('ev') retval['define_macros'].append(('COIO_USE_LIBEV', None)) # TODO(pts): Add support for evhdns here. if event_driver in (None, 'libevent2'): if asked_for_libevhdns: # TODO(pts): Add support for evhdns here. raise LinkError('evhdns does not work yet with libevent2') # event2/event_compat.h in libevent-2.0.10 doesn't contain a prototype # for event_reinit() and event_add() (they are in event2/event.h), so we # don't check for those here. if (FindLib(retval=retval, compiler=compiler, prefixes=prefixes, includes=['event2/event_compat.h'], library='event', symbols=['event_init', 'event_loop']) and FindLib( retval=retval, compiler=compiler, prefixes=prefixes, includes=['event2/dns.h', 'event2/dns_compat.h'], library='event', symbols=[ 'evdns_resolve_ipv4', 'evdns_resolve_reverse_ipv6' ])): event_driver = 'libevent2' retval['is_found'] = True # TODO(pts): Try to link something libevent1 doesn't have. retval['libraries'].extend(['event']) retval['define_macros'].append(('COIO_USE_LIBEVENT2', None)) if event_driver in (None, 'libevent1'): if asked_for_libevhdns: # TODO(pts): Add support for evhdns here. raise LinkError('evhdns does not work yet with libevent1') lib_event = 'event' prefixes2 = list(prefixes) for prefix in prefixes: # Prefer libevent-1.4.so* because libevent.so might be libevent2 (sigh). lib_file = os.path.join(prefix, 'lib', 'libevent-1.4.so.2') if os.path.isfile(lib_file): lib_event = lib_file prefixes2 = [prefix] break if (FindLib(retval=retval, compiler=compiler, prefixes=prefixes2, includes=['./coio_src/coio_event1_event.h'], library=lib_event, symbols=['event_init', 'event_loop', 'event_reinit']) and FindLib(retval=retval, compiler=compiler, prefixes=prefixes2, includes=['evdns.h'], library=lib_event, symbols=[ 'evdns_resolve_ipv4', 'evdns_resolve_reverse_ipv6' ])): event_driver = 'libevent1' retval['is_found'] = True retval['libraries'].append(lib_event) retval['define_macros'].append(('COIO_USE_LIBEVENT1', None)) if event_driver in ('minievent', None) and allowed_minievent: event_driver = 'minievent' retval['is_found'] = True retval['define_macros'].append(('COIO_USE_MINIEVENT', None)) if asked_for_libevhdns: if not FindLib(retval=retval, compiler=compiler, prefixes=prefixes, includes=[()], library='evhdns', symbols=['evdns_resolve_ipv4'], link_with_prev_libraries=['ev']): raise LinkError('evhdns not found') retval['define_macros'].append(('COIO_USE_LIBEVHDNS', None)) retval['libraries'].append('evhdns') else: retval['define_macros'].append(('COIO_USE_MINIHDNS', None)) retval['sources'].append('coio_src/coio_minihdns.c') retval['sources'].append('coio_src/coio_minievent.c') retval['depends'].append('coio_src/coio_minievent.h') if not retval.pop('is_found'): raise LinkError('libevent/libev not found, ' 'see the Installation section of README.txt') retval['python_version'] = sys.version repr_retval = repr(retval) if 'setuptools' in sys.modules and '-q' in sys.argv: log.error('using C env %s' % repr_retval) else: log.info('using C env %s' % repr_retval) try: old_repr_retval = open('setup.cenv').read() except IOError: old_repr_retval = None if repr_retval != old_repr_retval: open('setup.cenv', 'w').write(repr_retval) return retval
def search_dependencies(self): # lib_checks = {} data_types = ['DOUBLE', 'SINGLE', 'LONG', 'QUAD'] data_types_short = ['', 'f', 'l', 'q'] lib_types = ['', 'THREADS', 'OMP'] functions = ['plan_dft', 'init_threads', 'init_threads'] if self.support_mpi: lib_types.append('MPI') functions.append('mpi_init') for d, s in zip(data_types, data_types_short): # first check for serial library... basic_lib = self.check('', 'plan_dft', d, s, True) self.add_library(basic_lib) # ...then multithreading: link check with threads requires # the serial library. Both omp and posix define the same # function names. Prefer openmp if linking dynamically, # else fall back to pthreads. pthreads can be prioritized over # openmp by defining the environment variable PYFFTW_USE_PTHREADS if 'PYFFTW_USE_PTHREADS' not in os.environ: # openmp requires special linker treatment self.linker_flags.append(self.openmp_linker_flag()) lib_omp = self.check( 'OMP', 'init_threads', d, s, basic_lib and not hasattr(self, 'static_fftw_dir')) if lib_omp: self.add_library(lib_omp) else: self.linker_flags.pop() else: lib_omp = False self.compile_time_env[self.HAVE(d, 'OMP')] = False if lib_omp: self.compile_time_env[self.HAVE(d, 'THREADS')] = False if not lib_omp: # -pthread added for gcc/clang when checking for threads self.linker_flags.append(self.pthread_linker_flag()) lib_pthread = self.check('THREADS', 'init_threads', d, s, basic_lib) if lib_pthread: self.add_library(lib_pthread) else: self.linker_flags.pop() # check MPI only if headers were found self.add_library( self.check('MPI', 'mpi_init', d, s, basic_lib and self.support_mpi)) # On windows, the serial and posix threading functions are # build into one library as released on fftw.org. mpi is # not supported in the releases if get_platform() in ('win32', 'win-amd64'): if basic_lib: self.compile_time_env[self.HAVE(d, 'THREADS')] = True # optional packages summary: True if exists for any of the data types for l in lib_types[1:]: self.compile_time_env['HAVE_' + l] = False for d in data_types: self.compile_time_env['HAVE_' + l] |= self.compile_time_env[self.HAVE( d, l)] # compile only if mpi.h *and* one of the fftw mpi libraries are found if self.support_mpi: found_mpi_types = [] for d in data_types: if self.compile_time_env['HAVE_' + d + '_MPI']: found_mpi_types.append(d) else: self.compile_time_env['HAVE_MPI'] = False log.debug(repr(self.compile_time_env)) # required package: FFTW itself have_fftw = False for d in data_types: have_fftw |= self.compile_time_env['HAVE_' + d] if not have_fftw: raise LinkError("Could not find any of the FFTW libraries") log.info('Discovered FFTW with') for d in data_types: if not self.compile_time_env[self.HAVE(d)]: continue s = d.lower() + ' precision' if self.compile_time_env[self.HAVE(d, 'OMP')]: s += ' + openMP' elif self.compile_time_env[self.HAVE(d, 'THREADS')]: s += ' + pthreads' if self.compile_time_env[self.HAVE(d, 'MPI')]: s += ' + MPI' log.info(s)
def link(self, target_desc, objects, output_filename, output_dir=None, libraries=None, library_dirs=None, runtime_library_dirs=None, export_symbols=None, debug=0, extra_preargs=None, extra_postargs=None, build_temp=None, target_lang=None): # XXX this ignores 'build_temp'! should follow the lead of # msvccompiler.py (objects, output_dir) = self._fix_object_args(objects, output_dir) (libraries, library_dirs, runtime_library_dirs) = \ self._fix_lib_args (libraries, library_dirs, runtime_library_dirs) if runtime_library_dirs: log.warn("I don't know what to do with 'runtime_library_dirs': %s", str(runtime_library_dirs)) if output_dir is not None: output_filename = os.path.join(output_dir, output_filename) if self._need_link(objects, output_filename): # Figure out linker args based on type of target. if target_desc == CCompiler.EXECUTABLE: startup_obj = 'c0w32' if debug: ld_args = self.ldflags_exe_debug[:] else: ld_args = self.ldflags_exe[:] else: startup_obj = 'c0d32' if debug: ld_args = self.ldflags_shared_debug[:] else: ld_args = self.ldflags_shared[:] # Create a temporary exports file for use by the linker if export_symbols is None: def_file = '' else: head, tail = os.path.split(output_filename) modname, ext = os.path.splitext(tail) temp_dir = os.path.dirname( objects[0]) # preserve tree structure def_file = os.path.join(temp_dir, '%s.def' % modname) contents = ['EXPORTS'] for sym in (export_symbols or []): contents.append(' %s=_%s' % (sym, sym)) self.execute(write_file, (def_file, contents), "writing %s" % def_file) # Borland C++ has problems with '/' in paths objects2 = map(os.path.normpath, objects) # split objects in .obj and .res files # Borland C++ needs them at different positions in the command line objects = [startup_obj] resources = [] for file in objects2: (base, ext) = os.path.splitext(os.path.normcase(file)) if ext == '.res': resources.append(file) else: objects.append(file) for l in library_dirs: ld_args.append("/L%s" % os.path.normpath(l)) ld_args.append("/L.") # we sometimes use relative paths # list of object files ld_args.extend(objects) # XXX the command-line syntax for Borland C++ is a bit wonky; # certain filenames are jammed together in one big string, but # comma-delimited. This doesn't mesh too well with the # Unix-centric attitude (with a DOS/Windows quoting hack) of # 'spawn()', so constructing the argument list is a bit # awkward. Note that doing the obvious thing and jamming all # the filenames and commas into one argument would be wrong, # because 'spawn()' would quote any filenames with spaces in # them. Arghghh!. Apparently it works fine as coded... # name of dll/exe file ld_args.extend([',', output_filename]) # no map file and start libraries ld_args.append(',,') for lib in libraries: # see if we find it and if there is a bcpp specific lib # (xxx_bcpp.lib) libfile = self.find_library_file(library_dirs, lib, debug) if libfile is None: ld_args.append(lib) # probably a BCPP internal library -- don't warn else: # full name which prefers bcpp_xxx.lib over xxx.lib ld_args.append(libfile) # some default libraries ld_args.append('import32') ld_args.append('cw32mt') # def file for export symbols ld_args.extend([',', def_file]) # add _resource files ld_args.append(',') ld_args.extend(resources) if extra_preargs: ld_args[:0] = extra_preargs if extra_postargs: ld_args.extend(extra_postargs) self.mkpath(os.path.dirname(output_filename)) try: self.spawn([self.linker] + ld_args) except DistutilsExecError as msg: raise LinkError(msg) else: log.debug("skipping %s (up-to-date)", output_filename)
def _link(self, output, sources): args = [] libtool = utils.get_libtool_command(self._options) if libtool: # Note: MSVC Builds do not use libtool! # In the libtool case, put together the linker command, as we did before. # We aren't using distutils to link in this case. args.extend(libtool) args.append('--mode=link') args.append('--tag=CC') if self._options.quiet: args.append('--silent') args.extend(self._linker_cmd) args.extend(['-o', output]) if os.name == 'nt': args.append('-Wl,--export-all-symbols') else: args.append('-export-dynamic') if not self._compiler.check_is_msvc(): # These envvars are not used for MSVC Builds! # MSVC Builds use the INCLUDE, LIB envvars, # which are automatically picked up during # compilation and linking for cppflag in shlex.split(os.environ.get('CPPFLAGS', '')): args.append(cppflag) for cflag in shlex.split(os.environ.get('CFLAGS', '')): args.append(cflag) # Make sure to list the library to be introspected first since it's # likely to be uninstalled yet and we want the uninstalled RPATHs have # priority (or we might run with installed library that is older) for source in sources: if not os.path.exists(source): raise CompilerError( "Could not find object file: %s" % (source, )) if libtool: args.extend(sources) pkg_config_libs = self._run_pkgconfig('--libs') if not self._options.external_library: self._compiler.get_internal_link_flags(args, libtool, self._options.libraries, self._options.extra_libraries, self._options.library_paths) args.extend(pkg_config_libs) else: args.extend(pkg_config_libs) self._compiler.get_external_link_flags(args, libtool, self._options.libraries) if not self._compiler.check_is_msvc(): for ldflag in shlex.split(os.environ.get('LDFLAGS', '')): args.append(ldflag) if not libtool: # non-libtool: prepare distutils for linking the introspection # dumper program... try: self._compiler.link(output, sources, args) # Ignore failing to embed the manifest files, when the manifest # file does not exist, especially for MSVC 2010 and later builds. # If we are on Visual C++ 2005/2008, where # this embedding is required, the build will fail anyway, as # the dumper program will likely fail to run, and this means # something went wrong with the build. except LinkError as e: if self._compiler.check_is_msvc(): msg = str(e) if msg[msg.rfind('mt.exe'):] == 'mt.exe\' failed with exit status 31': if sys.version_info < (3, 0): sys.exc_clear() pass else: raise LinkError(e) else: raise LinkError(e) else: # libtool: Run the assembled link command, we don't use distutils # for linking here. if not self._options.quiet: print("g-ir-scanner: link: %s" % ( subprocess.list2cmdline(args), )) sys.stdout.flush() msys = os.environ.get('MSYSTEM', None) if msys: shell = os.environ.get('SHELL', 'sh.exe') # Create a temporary script file that # runs the command we want tf, tf_name = tempfile.mkstemp() with os.fdopen(tf, 'wb') as f: shellcontents = ' '.join([x.replace('\\', '/') for x in args]) fcontents = '#!/bin/sh\nunset PWD\n{}\n'.format(shellcontents) f.write(fcontents) shell = utils.which(shell) args = [shell, tf_name.replace('\\', '/')] try: subprocess.check_call(args) except subprocess.CalledProcessError as e: raise LinkerError(e) finally: if msys: os.remove(tf_name)
def link(self, target_desc, objects, output_filename, output_dir=None, libraries=None, library_dirs=None, runtime_library_dirs=None, export_symbols=None, debug=0, extra_preargs=None, extra_postargs=None, build_temp=None, target_lang=None): objects, output_dir = self._fix_object_args(objects, output_dir) fixed_args = self._fix_lib_args(libraries, library_dirs, runtime_library_dirs) libraries, library_dirs, runtime_library_dirs = fixed_args # filter out standard library paths, which are not explicitely needed # for linking system_libdirs = ['/lib', '/lib64', '/usr/lib', '/usr/lib64'] multiarch = sysconfig.get_config_var("MULTIARCH") if multiarch: system_libdirs.extend( ['/lib/%s' % multiarch, '/usr/lib/%s' % multiarch]) library_dirs = [ dir for dir in library_dirs if not dir in system_libdirs ] runtime_library_dirs = [ dir for dir in runtime_library_dirs if not dir in system_libdirs ] lib_opts = gen_lib_options(self, library_dirs, runtime_library_dirs, libraries) if not isinstance(output_dir, (str, type(None))): raise TypeError("'output_dir' must be a string or None") if output_dir is not None: output_filename = os.path.join(output_dir, output_filename) if self._need_link(objects, output_filename): ld_args = (objects + self.objects + lib_opts + ['-o', output_filename]) if debug: ld_args[:0] = ['-g'] if extra_preargs: ld_args[:0] = extra_preargs if extra_postargs: ld_args.extend(extra_postargs) self.mkpath(os.path.dirname(output_filename)) try: if target_desc == CCompiler.EXECUTABLE: linker = self.linker_exe[:] else: linker = self.linker_so[:] if target_lang == "c++" and self.compiler_cxx: # skip over environment variable settings if /usr/bin/env # is used to set up the linker's environment. # This is needed on OSX. Note: this assumes that the # normal and C++ compiler have the same environment # settings. i = 0 if os.path.basename(linker[0]) == "env": i = 1 while '=' in linker[i]: i += 1 if os.path.basename(linker[i]) == 'ld_so_aix': # AIX platforms prefix the compiler with the ld_so_aix # script, so we need to adjust our linker index offset = 1 else: offset = 0 linker[i + offset] = self.compiler_cxx[i] if sys.platform == 'darwin': linker = _osx_support.compiler_fixup(linker, ld_args) self.spawn(linker + ld_args) except DistutilsExecError as msg: raise LinkError(msg) else: log.debug("skipping %s (up-to-date)", output_filename)
def link(self, target_desc, objects, output_filename, output_dir=None, libraries=None, library_dirs=None, runtime_library_dirs=None, export_symbols=None, debug=0, extra_preargs=None, extra_postargs=None, build_temp=None, target_lang=None): if not self.initialized: self.initialize() (objects, output_dir) = self._fix_object_args(objects, output_dir) fixed_args = self._fix_lib_args(libraries, library_dirs, runtime_library_dirs) (libraries, library_dirs, runtime_library_dirs) = fixed_args if runtime_library_dirs: self.warn("I don't know what to do with 'runtime_library_dirs': " + str(runtime_library_dirs)) lib_opts = gen_lib_options(self, library_dirs, runtime_library_dirs, libraries) if output_dir is not None: output_filename = os.path.join(output_dir, output_filename) if self._need_link(objects, output_filename): if target_desc == CCompiler.EXECUTABLE: if debug: ldflags = self.ldflags_shared_debug[1:] else: ldflags = self.ldflags_shared[1:] else: if debug: ldflags = self.ldflags_shared_debug else: ldflags = self.ldflags_shared export_opts = [] for sym in (export_symbols or []): export_opts.append("/EXPORT:" + sym) ld_args = (ldflags + lib_opts + export_opts + objects + ['/OUT:' + output_filename]) # The MSVC linker generates .lib and .exp files, which cannot be # suppressed by any linker switches. The .lib files may even be # needed! Make sure they are generated in the temporary build # directory. Since they have different names for debug and release # builds, they can go into the same directory. build_temp = os.path.dirname(objects[0]) if export_symbols is not None: (dll_name, dll_ext) = os.path.splitext(os.path.basename(output_filename)) implib_file = os.path.join(build_temp, self.library_filename(dll_name)) ld_args.append('/IMPLIB:' + implib_file) # Embedded manifests are recommended - see MSDN article titled # "How to: Embed a Manifest Inside a C/C++ Application" # (currently at http://msdn2.microsoft.com/en-us/library/ms235591(VS.80).aspx) # Ask the linker to generate the manifest in the temp dir, so # we can embed it later. temp_manifest = os.path.join( build_temp, os.path.basename(output_filename) + ".manifest") ld_args.append('/MANIFESTFILE:' + temp_manifest) if extra_preargs: ld_args[:0] = extra_preargs if extra_postargs: ld_args.extend(extra_postargs) self.mkpath(os.path.dirname(output_filename)) try: self.spawn([self.linker] + ld_args) except DistutilsExecError as msg: raise LinkError(msg) # embed the manifest # XXX - this is somewhat fragile - if mt.exe fails, distutils # will still consider the DLL up-to-date, but it will not have a # manifest. Maybe we should link to a temp file? OTOH, that # implies a build environment error that shouldn't go undetected. mfid = 1 if target_desc == CCompiler.EXECUTABLE else 2 out_arg = '-outputresource:%s;%s' % (output_filename, mfid) try: self.spawn( ['mt.exe', '-nologo', '-manifest', temp_manifest, out_arg]) except DistutilsExecError as msg: raise LinkError(msg) else: log.debug("skipping %s (up-to-date)", output_filename)
def link(self, target_desc, objects, output_filename, output_dir=None, libraries=None, library_dirs=None, runtime_library_dirs=None, export_symbols=None, debug=0, extra_preargs=None, extra_postargs=None, build_temp=None, target_lang=None): # Distutils defaults to None for "unspecified option list"; we want # empty lists in that case (this substitution is done here in the body # rather than by changing the default parameters in case distutils # passes None explicitly). libraries = libraries or [] library_dirs = library_dirs or [] runtime_library_dirs = runtime_library_dirs or [] export_symbols = export_symbols or [] extra_preargs = extra_preargs or [] extra_postargs = extra_postargs or [] # On 64-bit Windows we just link to pythonXX.lib from the installation if _is_win64(): library_dirs = list(set(_build_ext_library_dirs() + library_dirs)) binpath = self._binpath if hasattr(self, '_linkOutputOpts'): outputOpts = self._linkOutputOpts[:] else: outputOpts = self._outputOpts[:] objectOpts = [_qp(fn) for fn in objects] (objects, output_dir) = self._fix_object_args(objects, output_dir) (libraries, library_dirs, runtime_library_dirs) = \ self._fix_lib_args (libraries, library_dirs, runtime_library_dirs) if runtime_library_dirs: self.warn('This CCompiler implementation does nothing with' ' "runtime_library_dirs": ' + str(runtime_library_dirs)) if output_dir and os.path.basename(output_filename) == output_filename: output_filename = os.path.join(output_dir, output_filename) else: if not output_filename: raise DistutilsFileError( 'Neither output_dir nor' \ ' output_filename was specified.') output_dir = os.path.dirname(output_filename) if not output_dir: raise DistutilsFileError( 'Unable to guess output_dir on the'\ ' bases of output_filename "%s" alone.' % output_filename) # Format the output filename option # (-offilename in DMD, -o filename in GDC, -of=filename in LDC) outputOpts[-1] = outputOpts[-1] % _qp( winpath(output_filename, self.winonly)) if not os.path.exists(output_dir): os.makedirs(output_dir) if not self._need_link(objects, output_filename): print("All binary output files are up to date.") return if self.build_exe: sharedOpts = [] linkOpts = self._exeLinkOpts pythonLibOpt = [] if target_desc != cc.CCompiler.EXECUTABLE: raise LinkError( 'This CCompiler implementation should be building' ' an executable') else: # The .def file (on Windows) or -shared and -soname (on Linux) sharedOpts = self._def_file(build_temp, output_filename) if target_desc != cc.CCompiler.SHARED_OBJECT: raise LinkError( 'This CCompiler implementation should be building ' ' a shared object') linkOpts = self._linkOpts # The python .lib file, if needed pythonLibOpt = self._lib_file(libraries) if pythonLibOpt: pythonLibOpt = _qp(pythonLibOpt) # Library linkage options print("library_dirs: %s" % (library_dirs, )) print("runtime_library_dirs: %s" % (runtime_library_dirs, )) print("libraries: %s" % (libraries, )) libOpts = gen_lib_options(self, library_dirs, runtime_library_dirs, libraries) # Optimization opts if debug: optimizationOpts = self._debugOptimizeOpts elif self.optimize: optimizationOpts = self._releaseOptimizeOpts else: optimizationOpts = self._defaultOptimizeOpts cmdElements = ([binpath] + extra_preargs + linkOpts + optimizationOpts + outputOpts + [pythonLibOpt] + objectOpts + libOpts + sharedOpts + extra_postargs) cmdElements = [el for el in cmdElements if el] wrapped_spawn(self, cmdElements, 'pyd_link')
def link( self, target_desc, objects, output_filename, output_dir=None, libraries=None, library_dirs=None, runtime_library_dirs=None, export_symbols=None, debug=0, extra_preargs=None, extra_postargs=None, build_temp=None, target_lang=None, ): if not self.initialized: self.initialize() (objects, output_dir) = self._fix_object_args(objects, output_dir) fixed_args = self._fix_lib_args(libraries, library_dirs, runtime_library_dirs) (libraries, library_dirs, runtime_library_dirs) = fixed_args if runtime_library_dirs: self.warn("I don't know what to do with 'runtime_library_dirs': " + str(runtime_library_dirs)) lib_opts = gen_lib_options(self, library_dirs, runtime_library_dirs, libraries) if output_dir is not None: output_filename = os.path.join(output_dir, output_filename) if self._need_link(objects, output_filename): if target_desc == CCompiler.EXECUTABLE: if debug: ldflags = self.ldflags_shared_debug[1:] else: ldflags = self.ldflags_shared[1:] else: if debug: ldflags = self.ldflags_shared_debug else: ldflags = self.ldflags_shared export_opts = [] for sym in export_symbols or []: export_opts.append("/EXPORT:" + sym) ld_args = (ldflags + lib_opts + export_opts + objects + ["/OUT:" + output_filename]) # The MSVC linker generates .lib and .exp files, which cannot be # suppressed by any linker switches. The .lib files may even be # needed! Make sure they are generated in the temporary build # directory. Since they have different names for debug and release # builds, they can go into the same directory. if export_symbols is not None: (dll_name, dll_ext) = os.path.splitext(os.path.basename(output_filename)) implib_file = os.path.join(os.path.dirname(objects[0]), self.library_filename(dll_name)) ld_args.append("/IMPLIB:" + implib_file) if extra_preargs: ld_args[:0] = extra_preargs if extra_postargs: ld_args.extend(extra_postargs) self.mkpath(os.path.dirname(output_filename)) try: self.spawn([self.linker] + ld_args) except DistutilsExecError as msg: raise LinkError(msg) else: log.debug("skipping %s (up-to-date)", output_filename)
def _link(self, output, sources): args = [] libtool = utils.get_libtool_command(self._options) if libtool: # Note: MSVC Builds do not use libtool! # In the libtool case, put together the linker command, as we did before. # We aren't using distutils to link in this case. args.extend(libtool) args.append('--mode=link') args.append('--tag=CC') if self._options.quiet: args.append('--silent') args.extend(self._linker_cmd) args.extend(['-o', output]) if os.name == 'nt': args.append('-Wl,--export-all-symbols') else: args.append('-export-dynamic') if not self._compiler.check_is_msvc(): # These envvars are not used for MSVC Builds! # MSVC Builds use the INCLUDE, LIB envvars, # which are automatically picked up during # compilation and linking cppflags = os.environ.get('CPPFLAGS', '') for cppflag in cppflags.split(): args.append(cppflag) cflags = os.environ.get('CFLAGS', '') for cflag in cflags.split(): args.append(cflag) ldflags = os.environ.get('LDFLAGS', '') for ldflag in ldflags.split(): args.append(ldflag) # Make sure to list the library to be introspected first since it's # likely to be uninstalled yet and we want the uninstalled RPATHs have # priority (or we might run with installed library that is older) for source in sources: if not os.path.exists(source): raise CompilerError( "Could not find object file: %s" % (source, )) if libtool: args.extend(sources) pkg_config_libs = self._run_pkgconfig('--libs') if not self._options.external_library: self._compiler.get_internal_link_flags(args, libtool, self._options.libraries, self._options.library_paths) args.extend(pkg_config_libs) else: args.extend(pkg_config_libs) self._compiler.get_external_link_flags(args, libtool, self._options.libraries) if not libtool: # non-libtool: prepare distutils for linking the introspection # dumper program... try: self._compiler.link(output, sources, args) # Ignore failing to embed the manifest files, when the manifest # file does not exist, especially for MSVC 2010 and later builds. # If we are on Visual C++ 2005/2008, where # this embedding is required, the build will fail anyway, as # the dumper program will likely fail to run, and this means # something went wrong with the build. except LinkError, e: if self._compiler.check_is_msvc(): msg = str(e) if msg[msg.rfind('mt.exe'):] == 'mt.exe\' failed with exit status 31': sys.exc_clear() pass else: raise LinkError(e) else: raise LinkError(e)