29

我的LIBRARY_PATH环境变量中有一个自定义目录:/cs/public/lib/pkg/opencv/lib.

但是,当我使用 时g++ --print-search-dirs,我得到了这个:

libraries: =
/cs/public/lib/pkg/opencv/lib/x86_64-suse-linux/4.6/:
/cs/public/lib/pkg/opencv/lib/../lib64/:
/usr/lib64/gcc/x86_64-suse-linux/4.6/:
/usr/lib64/gcc/x86_64-suse-linux/4.6/../../../../x86_64-suse-linux/lib/x86_64-suse-linux/4.6/:
/usr/lib64/gcc/x86_64-suse-linux/4.6/../../../../x86_64-suse-linux/lib/../lib64/:
/usr/lib64/gcc/x86_64-suse-linux/4.6/../../../x86_64-suse-linux/4.6/:
/usr/lib64/gcc/x86_64-suse-linux/4.6/../../../../lib64/:
/lib/x86_64-suse-linux/4.6/:
/lib/../lib64/:
/usr/lib/x86_64-suse-linux/4.6/:
/usr/lib/../lib64/:
/cs/public/lib/pkg/opencv/lib/:
/usr/lib64/gcc/x86_64-suse-linux/4.6/../../../../x86_64-suse-linux/lib/:
/usr/lib64/gcc/x86_64-suse-linux/4.6/../../../:
/lib/:
/usr/lib/

为什么 g++ 会在我在变量中明确指定之前查看这些替代方案和一大堆其他系统位置,这在LIBRARY_PATH哪里记录?

我会理解是否在 LIBRARY_PATH 和 LIBRARY_PATH/../lib64 等之前搜索了系统默认值,但是 g++ 会先放置 LIBRARY_PATH/../lib64,然后是系统路径,然后是 LIBRARY_PATH。此订购记录在哪里?

我的 g++ 版本是g++ (SUSE Linux) 4.6.2

我的操作系统是openSUSE 12.1 (x86_64)

4

7 回答 7

11

这里问了一个类似的问题: g++ 搜索 /lib/../lib/,然后 /lib/

这些看起来吓人的搜索路径至少部分是在它构建的编译器本身时确定的,例如在配置阶段。很明显,它超出了环境变量的范围,因为可以安装多个 GCC 副本并让每个副本为gcc --print-search-dirs. 还注意到g++ --print-search-dirsgcc --print-search-dirs给出不同的结果指出 g++ 包装器也在影响搜索路径。除了配置/构建时间差异之外,GCC 肯定知道它自己的可执行文件所在的路径,并将搜索该路径的子目录。在 GCC 文档中可以找到很多这种炼金术:http:
//gcc.gnu.org/onlinedocs/gcc-4.7.1/gcc/Directory-Options.html#Directory-Options
http://gcc.gnu.org/onlinedocs/gcc-4.7.1/gcc/Environment-Variables.html#Environment-Variables

据我所知,在不编译自己的 GCC 副本的情况下,最有力的方法是使用 -L 选项指定自定义库。我这么说的原因是因为 -L 在例如 LIBRARY_PATH 之前被搜索过(参见上面关于环境变量的链接)。为了使它更容易忍受,您可以为 g++ 添加一个别名,包括在您的 .bashrc 文件中的 -L 选项。

如果您想要一个明确的答案,那么下载 GCC 源代码的副本是一种方法。例如,在 gcc.c 中会出现以下高度暗示性的注释:

/* Build a list of search directories from PATHS.
   PREFIX is a string to prepend to the list.
   If CHECK_DIR_P is true we ensure the directory exists.
   If DO_MULTI is true, multilib paths are output first, then
   non-multilib paths.
   This is used mostly by putenv_from_prefixes so we use `collect_obstack'.
   It is also used by the --print-search-dirs flag.  */

但是注释后面的功能不是很明显。

于 2012-09-18T17:44:09.990 回答
7

这是 multilib 在工作 - 一种允许在单台机器上为多个架构拥有库(但也包括整个编译和构建工具链)的机制。该 Wiki声明“multilib 后缀被附加到 GCC 搜索库的所有目录中,并通过 -L 选项传递给链接器。链接器本身对 multilibs 没有任何特殊知识,如果出现以下情况,将继续查阅其默认搜索目录在 -L 路径中找不到库。如果在单个编译中使用多个正交 ABI 更改选项,则可以串联使用多个 multilib 后缀。"。

因此,根据上述描述,体系结构标记字符串或其不同变体被附加到编译器接收的每个库搜索路径,因为它不区分默认路径和自定义路径。您的自定义路径排在第一位,但它经历了与其他路径相同的“扩展”过程。

由于需要处理 i386 兼容性,现在似乎在大多数 x64 发行版上默认使用 multilib 机制,这实际上意味着大多数安装在那里。

于 2012-09-18T20:51:29.323 回答
2

我有完全相同的问题:

Fedora 17, gcc 4.7 and gcc 4.3
CentOS 6.3, gcc 4.4
Unubuntu 12, gcc 4.6

所以看起来这是大多数 gcc 版本的问题。至少根据这个,这种奇怪的行为可能首先出现在 gcc 4.2 中。

我尝试复制规格并与它们一起玩。看起来*multilib规范用于根据平台附加特定的字符串。例如我原来的空间看起来像:

*multilib:
. !m64 !m32;64:../lib64 m64 !m32;32:../lib !m64 m32;

当我改为64:../lib64then64:../lib而不是../lib64gcc appended时../lib。但我无法完全解读*multilib其他规格或任何其他规格的含义。

于 2012-10-03T08:34:15.807 回答
2

这个答案试图总结 GCC 和 Clang 的搜索路径行为。

海合会

包含路径:对于以下格式的命令行:

CPLUS_INCLUDE_PATH=EDIR g++ -IIDIR -isystemSDIR

以下目录列表用作搜索路径#include <...>

IDIR                                           # '-I' directories.
SDIR                                           # '-isystem' directories.
EDIR                                           # *_INCLUDE_PATH directories.
GCCDIR/include/c++/GCCVER                      # libstdc++ directory (C++).
GCCDIR/include/c++/GCCVER/GCCARCH              # libstdc++ directory (C++).
GCCDIR/include/c++/GCCVER/backward             # libstdc++ directory (C++).
GCCDIR/lib/gcc/GCCARCH/GCCVER/include          # GCC arch-specific directory.
/usr/local/include/GCCARCH                     # Local arch-specific include directory.
/usr/local/include                             # Local include directory.
GCCDIR/include                                 # GCC include directory.
GCCDIR/lib/gcc/GCCARCH/GCCVER/include-fixed    # GCC include-fixed directory.
/usr/include/GCCARCH                           # System include arch-specific directory.
/usr/include                                   # System include directory.

库路径:对于以下格式的命令行:

LIBRARY_PATH=EDIR gcc -BBDIR -LLDIR

以下参数被传递给链接器:

-LLDIR                                         # '-L' directories.
-LBDIR                                         # '-B' directories.
-LEDIR/../libXX                                # Multilib directories from LIBRARY_PATH.
-LGCCDIR/lib/gcc/GCCARCH/GCCVER                # GCC arch-specific library directory.
-LGCCDIR/libXX                                 # GCC multilib library directory.
-L/libXX                                       # System multilib library directory.
-L/usr/libXX                                   # System multilib library directory. 
-LEDIR                                         # LIBRARY_PATH directories.
-LGCCDIR/lib                                   # Other GCC libraries.

包含路径:对于以下格式的命令行:

CPLUS_INCLUDE_PATH=EDIR clang++ --gcc-toolchain=GCCDIR -BBDIR -IIDIR -isystemSDIR

以下目录列表用作搜索路径#include <...>

IDIR                                           # '-I' directories.
SDIR                                           # '-isystem' directories.
EDIR                                           # *_INCLUDE_PATH directories.
 # If -stdlib=libstdc++ is used:
   GCCDIR/include/c++/GCCVER                   # libstdc++ directory from the selected GCC toolchain (C++).
   GCCDIR/include/c++/GCCVER/GCCARCH           # libstdc++ directory from the selected GCC toolchain (C++).
   GCCDIR/include/c++/GCCVER/backward          # libstdc++ directory from the selected GCC toolchain (C++).
 # If -stdlib=libc++ is used:
   CLANGDIR/include/c++/v1                     # libc++ directory (C++).
/usr/local/include                             # Local include directory.
CLANGDIR/lib/clang/CLANGVER/include            # Clang include directory.
/include                                       # System include directory.
/usr/include                                   # System include directory.

库路径:对于以下格式的命令行:

LIBRARY_PATH=EDIR clang --gcc-toolchain=GCCDIR -BBDIR -LLDIR    

以下参数被传递给链接器:

-LLDIR                                         # '-L' directories.
-LGCCDIR/lib/gcc/GCCARCH/GCCVER                # GCC arch-specific library directory.
-LGCCDIR/libXX                                 # GCC multilib library directory.
-L/libXX                                       # System multilib library directory.
-L/usr/libXX                                   # System multilib library directory.
-LGCCDIR/lib                                   # Other GCC libraries.
-LCLANGDIR/lib                                 # Clang libraries.
-L/lib                                         # System library directory.
-L/usr/lib                                     # System library directory.
-LEDIR                                         # LIBRARY_PATH directories.

概括

在 GCC 和 Clang 中,include 的搜索路径几乎相同。如果在这两种情况下都使用 C 前端,则省略 C++ 特定路径。GCC 和 Clang 之间的库搜索路径有很大不同,特别是-B目录的存在和 GCC 前端的奇怪操作LIBRARY_PATH

C 和 C++ 前端的库搜索路径相同。其他库搜索路径由链接器本身引入。以下摘录来自 GNU Binutils 的 vanilla 链接描述文件:

# Multilib library directories.
SEARCH_DIR("BINUTILSDIR/BINUTILSARCH/libXX");
SEARCH_DIR("BINUTILSDIR/libXX");
SEARCH_DIR("/usr/local/libXX");
SEARCH_DIR("/libXX");
SEARCH_DIR("/usr/libXX");
# Traditional library directories.
SEARCH_DIR("BINUTILSDIR/BINUTILSARCH/lib");
SEARCH_DIR("BINUTILSDIR/lib");
SEARCH_DIR("/usr/local/lib");
SEARCH_DIR("/lib");
SEARCH_DIR("/usr/lib");

还必须注意,不在上面列出的目录中搜索库依赖项。这些完全依赖于传递给链接器的选项,否则它们会从默认的系统库路径中解析。因此,同时生成和参数以确保链接正确的库可能很有用。-rpath-rpath-link-L-rpath-link

-B最后,仅在目录中搜索特殊文件(例如 CRT 对象) 。在 Clang 中,还会在选定的 GCC 工具链中搜索特殊文件。其他因素(规范文件、特定于发行版的配置)可能会改变上述部分或全部内容。

于 2018-10-31T15:35:17.577 回答
-1

路径由内置规范定义。规范定义了管道如何处理源代码以获得结果。GCC 只是驱动编译。

您可以通过 为 GCC 提供您自己的规范文件,并且您可以使用IIRC-spec=获取内置规范。-dumpspecs

这可能在 GCC 手册中的某处进行了解释。

于 2012-09-20T13:11:40.633 回答
-1

看起来需要交叉编译。从变更日志:

  Wed Mar 29 14:53:23 1995  Jim Wilson  <wilson@cygnus.com>

          * gcc.c (process_command): Delete code modifying gcc_exec_prefix.
          (main): Put it here after last use of gcc_exec_prefix.  For cross
          compiler, set startfile_prefixes if gcc_exec_prefix is set and
          standard_startfile_prefix is a relative path.

startfile_prefixes是使用 search-dirs 标志打印的内容。来自gcc/gcc.c

    if (print_search_dirs)
      {
        printf (_("install: %s%s\n"), standard_exec_prefix, machine_suffix);
        printf (_("programs: %s\n"), build_search_list (&exec_prefixes, "", 0));
        printf (_("libraries: %s\n"), build_search_list (&startfile_prefixes, "", 0));
        return (0);
      }
于 2012-09-16T17:13:27.053 回答
-1

编译器将首先查看默认路径,然后查看其他路径。当您打印时它如何排序 I don't now,但它记录在这里,3.19 Environment Variables Affecting GCC

于 2012-09-16T17:15:05.483 回答