示例#1
0
    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
示例#2
0
 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)
示例#3
0
    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)
示例#4
0
    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