def __init__(self, compiler, preferred_shared=True, executable=None, **kw): include_dir = var('INCLUDEPY') assert include_dir is not None prefix = path.clean(var('prefix')) assert prefix is not None directories = [] if var('LIBPL'): directories.append(path.clean(var('LIBPL'))) if var('base'): directories.append(path.join(var('base'), 'libs')) directories.append(path.join(var('base'), 'DLLs')) self.version = (var('py_version')[0], var('py_version')[2]) name_suffixes = [''.join(self.version), ''] for k in ['LDVERSION', 'py_version_nodot', 'py_version_short']: if var(k): name_suffixes.append(var(k)) super().__init__( "python", compiler, find_includes = ['Python.h'], name_suffixes = name_suffixes, prefixes = [prefix], include_directories = var('INCLUDEPY') and [var('INCLUDEPY')] or [], directories = directories, preferred_shared = preferred_shared, shared = kw.get('shared'), ) components = [] if platform.IS_WINDOWS and not self.shared: components = ['pyexpat', 'unicodedata'] self.components = list( Library( component, compiler, prefixes = [prefix], include_directories = var('INCLUDEPY') and [var('INCLUDEPY')] or [], directories = directories, shared = self.shared, ) for component in components ) self.ext = var('SO')[1:] self.libraries = [self] + self.components
def _env_list(self, singular, plural): dir_ = self.env_var(singular) dirs = dir_ is not None and [dir_] or [] dirs += self.env_var(plural, []) dir_ = self.env.get(singular.upper()) dirs += dir_ is not None and [dir_] or [] dirs += self.env.get(plural.upper(), []) return tools.unique(path.clean(d) for d in dirs)
def _set_directories_and_files(self, directories): dirs = self._env_directories() files = self._env_files() if dirs and files: self.directories = dirs self.files = files tools.debug("Found %s library directories and files from environment" % self.name) return else: self.directories = [] self.files = [] tools.debug("Searching %s library directories and files" % self.name) dirs.extend(directories) if self.macosx_framework: dirs.extend(path.join(p, 'Library', 'Frameworks') for p in self.prefixes) else: dirs.extend(path.join(p, 'lib') for p in self.prefixes) if self.use_system_paths: dirs.extend(self.library_system_paths()) if self.macosx_framework: dirs = (path.join(dir_, self.name + '.framework', 'lib') for dir_ in dirs) dirs = list(path.clean(d) for d in tools.unique(dirs) if path.exists(d)) if self.binary_file_names is not None: names = self.binary_file_names else: names = [self.name] extensions_list = [] if self.macosx_framework: extensions_list = [None] if self.shared is not None: extensions_list = [ ( self.shared, self.compiler.library_extensions( self.shared, for_linker = True, ) ) ] else: extensions_list = [ ( self.preferred_shared, self.compiler.library_extensions(self.preferred_shared, for_linker = True) ), ( not self.preferred_shared, self.compiler.library_extensions(not self.preferred_shared, for_linker = True) ), ] for name in names: files = [] for shared, extensions in extensions_list: for dir_ in dirs: files.extend(self._find_files(dir_, name, extensions)) if files and self.only_one_binary_file: if self.shared is None: self.shared = shared files = files[:1] tools.debug("Stopping search for %s library files." % name) break if files: break # do not mix shared and non shared extensions if not files: tools.fatal( "Cannot find %s library files:" % self.name, "\t* Set 'directories' when creating the library", "\t* Set the environment variable '%s_DIRECTORY'" % self.name.upper(), "\t* Set the environment variable '%s_DIRECTORIES'" % self.name.upper(), "\t* Set the environment variable '%s_PREFIX'" % self.name.upper(), "\t* Set the environment variable '%s_PREFIXES'" % self.name.upper(), "\t* Set the environment variable 'PREFIX'", "\t* Set the environment variable 'PREFIXES'", "NOTE: Directories checked: %s" % ', '.join(dirs), sep='\n' ) else: self.files.extend(files) self.directories.extend(path.dirname(f) for f in files)
def _get_link_flags(self, kw): link_flags = [] if self.attr("allow_unresolved_symbols", kw): # link_flags.append('-Wl,--allow-shlib-undefined') # link_flags.append('-Wl,--unresolved-symbols=ignore-all') if self.name == "clang": link_flags.extend(["-undefined", "dynamic_lookup"]) else: link_flags.extend(["-undefined=dynamic_lookup"]) if self.attr("multithreading", kw): link_flags.append("-pthread") library_directories = self.library_directories[:] pic = self.attr("position_independent_code", kw) if pic and not platform.IS_WINDOWS: link_flags.append("-fPIC") if self.attr("hidden_visibility", kw): link_flags.append("-fvisibility=hidden") if self.lang == "c++": link_flags.append("-fvisibility-inlines-hidden") if platform.IS_MACOSX: link_flags.append("-headerpad_max_install_names") if platform.IS_WINDOWS: link_flags.append("--enable-stdcall-fixup") export_libraries = self.list_attr("export_libraries", kw) if self.name != "clang": excluded_libs = [] for lib in self.list_attr("libraries", kw): if lib not in export_libraries: if isinstance(lib, Target): if not lib.shared: excluded_libs.append(lib.path) elif not (lib.macosx_framework or lib.system): if not lib.shared: excluded_libs.extend(lib.files) if excluded_libs: # Specifying multiple comma separated libs here does not work # Specifying full path does not work ... (but no error) link_flags.extend("-Wl,--exclude-libs,%s" % path.basename(f) for f in excluded_libs) rpath_dirs = [] if self.attr("recursive_linking", kw): link_flags.append("-Wl,-(") for lib in self.list_attr("libraries", kw): if isinstance(lib, Target): if self.name == "clang" and lib in export_libraries: if lib.shared: link_flags.extend(["-Xlinker", "-reexport_library", "-Xlinker", lib]) else: link_flags.extend(["-Xlinker", "-force_load", "-Xlinker", lib]) else: link_flags.append(lib) rpath_dirs.append(path.dirname(lib.path)) elif lib.macosx_framework: link_flags.extend(["-framework", lib.name]) elif lib.system == True: link_flags.append("-l%s" % lib.name) else: for f in lib.files: # if not platform.IS_MACOSX: # if lib.shared: # link_flags.append('-Wl,-Bdynamic') # else: # link_flags.append('-Wl,-Bstatic') if self.name == "clang" and lib in export_libraries: if lib.shared: link_flags.extend(["-Xlinker", "-reexport_library", "-Xlinker", f]) else: link_flags.extend(["-Xlinker", "-force_load", "-Xlinker", f]) else: link_flags.append(f) for dir_ in lib.directories: library_directories.append(dir_) if self.attr("recursive_linking", kw): link_flags.append("-Wl,-)") # if not platform.IS_MACOSX: # link_flags.append('-Wl,-Bdynamic') rpath_dirs.extend(library_directories) rpath_dirs = tools.unique(path.clean(p) for p in rpath_dirs) if rpath_dirs: if platform.IS_MACOSX: link_flags.extend(("-Wl,-rpath,%s" % d) for d in rpath_dirs) elif not platform.IS_WINDOWS: link_flags.append("-Wl,-rpath," + ":".join(rpath_dirs)) link_flags.extend(self.additional_link_flags.get(self.name, [])) if self.attr("static_libstd", kw): link_flags.append("-L%s" % self.static_stdlib_directory) link_flags.append("-static-libgcc") return link_flags