【问题标题】:Why does g++ look in LIBRARY_PATH/../lib64 and where is this documented?为什么 g++ 在 LIBRARY_PATH/../lib64 中查找,这在哪里记录?
【发布时间】:2012-09-14 06:42:22
【问题描述】:

我的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)

【问题讨论】:

  • 每当我将库路径添加到我的LIBRARY_PATH 并且我执行gcc --print-search-dirs 时,我都会看到我的库路径,然后是x86_64-pc-linux-gnu/4.5.4/../lib64/ 和路径本身。不仅 ../lib64/ 附加目录。
  • 是的,我的也是。我刚刚注意到,但搜索列表比附加版本更靠后,并且两者之间有系统目录。我仍然不明白这种行为,我编辑了我的问题。
  • 我猜是因为它是 64 位的,所以它首先放置所有 ../lib64/ 和 OS 库(例如 x86_64-suse-linux/4.6/)路径,前面是您的自定义库,然后是路径本身。同样的事情发生在我的 32 位 linux 系统上,除了 ../lib64 部分没有。
  • 不过,我想知道这是在哪里记录的。这有点抱怨,但我希望如果我明确设置 LIBRARY_PATH,它将优先于 /usr/lib64/gcc/x86_64-suse-linux/4.6/,特别是因为 g++ 确实 i> 注意让 LIBRARY_PATH/../lib64 优先于 /usr/lib64/gcc/x86_64-suse-linux/4.6/。
  • lib64 是在编译 GCC 时在 gcc/config/i386/t-linux 中定义的。操作系统附带的 GCC 版本在构建 GCC 之前已修补了此文件。如果您希望自定义 GCC 安装首先使用 /cs/public/lib/pkg/opencv/lib,则必须修改 gcc/config/i386/t-linux 并重新构建 GCC。

标签: c++ linux gcc g++


【解决方案1】:

这里问了一个类似的问题: g++ searches /lib/../lib/, then /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.  */

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

【讨论】:

  • 这并不能解决文档问题,但 gcc 与 g++ 中的不同行为提供了一些线索。在我的系统上,LIBRARY_PATH 条目首先出现在 gcc 搜索顺序中,但对于 g++,它们出现在搜索顺序的中间,系统路径位于两侧,如您所描述的那样。
  • 我必须说,链接的文档(以及它的最新版本)对于这个问题毫无用处。它描述了有哪些选项,但它完全没有透露炼金术。从文档中省略这是一件可怕的事情......
【解决方案2】:

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

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

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

【讨论】:

  • GCC 即使在使用--disable-multilib 构建时也会这样做。这有意义吗? wiki 链接似乎非常有用,但我不知道它是否是最新的。官方文档未能提供这种详细程度真是太遗憾了。
  • @Zulan 确实令人惊讶
【解决方案3】:

我也有同样的问题:

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

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

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

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

当我将64:../lib64 更改为64:../lib 然后而不是../lib64 gcc 附加../lib。但我无法完全解读 *multilib 或任何其他规范的含义。

【讨论】:

  • 很高兴知道我并不孤单。我也应该尝试使用规范文件。我开始确信这实际上并没有记录在任何地方。
【解决方案4】:

此答案试图总结 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 中包含的搜索路径几乎相同。如果在这两种情况下都使用 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 工具链中搜索特殊文件。其他因素(规范文件、特定于发行版的配置)可能会改变上述部分或全部。

【讨论】:

    【解决方案5】:

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

      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);
          }
    

    【讨论】:

    • 好吧,但是为什么它使用LIBRARY_PATH/[arch],然后是LIBRARY_PATH/../lib64,然后是/usr/lib64/[...],最后是LIBRARY_PATH
    【解决方案6】:

    编译器将首先查看默认路径,然后再查看其他路径。 当你打印时它是如何排序的,我现在没有,但它记录在这里,3.19 Environment Variables Affecting GCC

    【讨论】:

    • 编译器首先在“/cs/public/lib/pkg/opencv/lib/x86_64-suse-linux/4.6/:”中查找,然后在“/cs/public/lib/pkg/”中查找opencv/lib/../lib64/:”,然后在“/cs/public/lib/pkg/opencv/lib/:”中。 --print-search-dirs 的打印顺序是它们被搜索的顺序。
    • @Sancho 我认为这也取决于编译器的配置方式。从 Ubuntu 12.04 我得到这个:libraries: =/usr/lib/gcc/i686-linux-gnu/4.6/:/usr/lib/gcc/i686-linux-gnu/4.6/../../../../i686-linux-gnu/lib/i686-linux-gnu/4.6/:/usr/lib/gcc/i686-linux-gnu/4.6/../../../../i686-linux-gnu/lib/i386-linux-gnu/:/usr/lib/gcc/i686-linux-gnu/4.6/../../../../i686-linux-gnu/lib/../lib/:/usr/lib/gcc/i686-linux-gnu/4.6/../../../i686-linux-gnu/4.6/:/usr/lib/gcc/i686-linux-gnu/4.6/../../../i386-linux-gnu/:/usr/lib/gcc/i686-linux-gnu/4.6/../../../../lib/:/lib/i686-linux-gnu/4.6/:/lib/i386-linux-gnu/
    • 在这种情况下您的 LIBRARY_PATH 设置为什么?我没有看到任何自定义路径。
    【解决方案7】:

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

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

    这可能在 GCC 手册的某处有所解释。

    【讨论】:

    • 谢谢,这是一个有用的信息。我仍然不清楚规范文件中的任何内容如何确定基于LIBRARY_PATH 的库搜索路径的顺序。我在 gcc 手册中找不到详细信息。我发现了一个相关的问题,该问题对此问题进行了详细介绍:stackoverflow.com/questions/11688893/…
    • GCC 从各种来源(builtin、env、params)收集列表,传递它,然后扩展规范。所以最终结果是由规格决定的。
    • 我知道规格决定结果,但是如何LIBRARY_PATH/[arch]LIBRARY_PATH/../lib/usr/lib64/[...] 出现在 LIBRARY_PATH 之前的规范行是什么?我将如何改变它以使情况并非如此?我说不出来。
    • 我之前说过,你可以给gcc你自己的spec,看看the manual
    • 我的意思是,我应该在我的自定义规范文件中放入哪一行以使LIBRARY_PATH 位于LIBRARY_PATH/[arch] 之前和/usr/lib64/[...] 之前?您链接到的手册未提供此信息。如果你能回答这个问题,并指出它的文档,你就会得到赏金。
    猜你喜欢
    • 1970-01-01
    • 2019-12-23
    • 1970-01-01
    • 2011-11-25
    • 2022-10-01
    • 1970-01-01
    • 2019-12-07
    • 1970-01-01
    相关资源
    最近更新 更多