linux - 如何使g++正确使用我自己的glibc构建的 header ?

标签 linux gcc g++ glibc include-path

如果上下文太多,最后会有TL; DR!
上下文
我正在尝试将项目使用的glibc版本更新为2.23(我知道它很旧,这是另一个问题)。为此,我需要换出库并使用关联的解释器。
换出看起来像ABI更改的解释器时,我遇到了一些问题,所以我认为这可能是因为头文件已进行了某种更改,并开始着手将那些包含在项目中。
最初,我尝试使用-I包含 header ,但出现错误(请参见下文)。后来我尝试设置--sysroot,但这很快就感觉像是一种错误的处理方式,因为我本质上是在重新发明g++已经对系统头文件所做的工作。后来我发现了另一种看起来更有希望的机制(请参阅问题部分)。
可以是XY issue吗?绝对可以,但是无论哪种方式,我所看到的问题对我来说都很奇怪。
问题
我调查了是否存在其他机制来在gcc和g++中包含系统库(例如glibc)的 header 。我发现了标记-isystem:

   -isystem dir
      Search dir for header files, after all directories specified by -I but before the standard system directories.  Mark it as a system directory, so that it gets the same special treatment as is applied to the standard system directories.  If dir begins with "=", then the "="
      will be replaced by the sysroot prefix; see --sysroot and -isysroot.

我认为这可能是需要的,并着手将该标志集成到项目的构建系统中。生成的g++命令如下所示(简化并分成多行):
> /path/to/gcc-6.3.0/bin/g++
  -c
  -Wl,--dynamic-linker=/path/to/glibc-2.23/build/install/lib/ld-linux-x86-64.so.2
  -Wl,--rpath=/path/to/glibc-2.23/build/install/lib
  -isystem /path/to/glibc-2.23/build/install/include
  -I.
  -I/project-foo/include
  -I/project-bar/include
  -o example.o 
  example.cpp
这将导致以下错误,随后是许多类似错误:
In file included from /usr/include/math.h:71:0,
                 from /path/to/gcc-6.3.0/include/c++/6.3.0/cmath:45,
                 from example.cpp:42:
/path/to/glibc-2.23/build/install/include/bits/mathcalls.h:63:16: error: expected constructor, destructor, or type conversion before '(' token
 __MATHCALL_VEC (cos,, (_Mdouble_ __x));
对此进行调查,似乎该特定的math.h与此版本的glibc不兼容。它尝试使用它的事实使我感到惊讶,因为math.h文件存在于我指定的glibc目录中。为什么不使用它?这是我验证文件存在的方法:
> ls /path/to/glibc-2.23/build/install/include/math.h 
/path/to/glibc-2.23/build/install/include/math.h
研究
我在互联网上搜索了存在类似问题的人,并发现了以下相关信息:
  • https://github.com/riscv/riscv-gnu-toolchain/issues/105
  • https://askubuntu.com/questions/806220/building-ucb-logo-6-errors-in-mathcalls-h
  • -isystem on a system include directory causes errors

  • 最后的是最有希望的。它讨论了为什么-isystem在这里不起作用,说明特殊的#include_next以不同的方式遍历包含路径。在这里,解决方案似乎是“不要在需要帮助的地方使用-isystem”,但是由于我尝试使用-I只能再次遇到相同的问题,因此我不确定如何将其应用于此处。
    原始问题
    使用新的glibc进行编译时,出现以下错误(我们的构建过程最终运行了一些其编译的程序,以生成更多要编译的源,因此在编译时会出现此运行时错误):
    Inconsistency detected by ld.so: get-dynamic-info.h: 143: elf_get_dynamic_info: Assertion `info[DT_RPATH] == NULL' failed!
    
    我发现了一些与此相关的东西:
  • https://www.linuxquestions.org/questions/linux-software-2/how-to-get-local-gcc-to-link-with-local-glibc-404087/
  • https://www.linuxquestions.org/questions/programming-9/inconsistency-detected-by-ld-so-dynamic-link-h-62-elf_get_dynamic_info-assertion-621701/

  • 我看到的唯一解决方案是完全重新编译gcc以使用新的glibc。如果可能的话,我想避免这种情况,这就是导致我进入包含路线的原因。
    消除复杂的构建系统
    为了尝试消除“真实”项目上的复杂构建系统,我使用以下test.cpp文件重现了该问题:
    #include <cmath>
    
    int main() {
    
    }
    
    编译使用:
    > /path/to/gcc-6.3.0/bin/g++ test.cpp -Wl,--dynamic-linker=/path/to/glibc-2.23/build/install/lib/ld-linux-x86-64.so.2 -Wl,--rpath=/path/to/glibc-2.23/build/install/lib
    
    运行产生相同的原始问题:
    > ./a.out 
    Inconsistency detected by ld.so: get-dynamic-info.h: 143: elf_get_dynamic_info: Assertion `info[DT_RPATH] == NULL' failed!
    
    尝试使用更新的 header 会产生相同的包含问题:
    > /path/to/gcc-6.3.0/bin/g++ test.cpp -Wl,--dynamic-linker=/path/to/glibc-2.23/build/install/lib/ld-linux-x86-64.so.2 -Wl,--rpath=/path/to/glibc-2.23/build/install/lib -isystem /path/to/glibc-2.23/build/install/include
    In file included from /usr/include/math.h:71:0,
                     from /path/to/gcc-6.3.0/include/c++/6.3.0/cmath:45,
                     from test.cpp:1:
    /path/to/glibc-2.23/build/install/include/bits/mathcalls.h:63:16: error: expected constructor, destructor, or type conversion before '(' token
     __MATHCALL_VEC (cos,, (_Mdouble_ __x));
    
    TL; DR
    如何使g++正确地包含来自我的glibc构建的 header ,而不会意外地包含来自/usr/include的不兼容文件?

    最佳答案

    在您的GCC版本中,<cmath>使用#include_next,这意味着您需要确保包含cmath文件的目录位于包含您要针对的glibc版本的正确math.h的目录之前(在包含搜索路径上)。
    您可以使用g++ -v查看搜索路径。在您的情况下,可能看起来像这样:

    #include "..." search starts here:
    #include <...> search starts here:
     .
     /project-foo/include
     /project-bar/include
     /path/to/glibc-2.23/build/install/include
     /usr/include/c++/6
     /usr/include/x86_64-linux-gnu/c++/6
     /usr/lib/gcc/x86_64-linux-gnu/6/include
     /usr/local/include
     /usr/lib/gcc/x86_64-linux-gnu/6/include-fixed
     /usr/include/x86_64-linux-gnu
     /usr/include
    
    如果使用--prefix=/usr配置glibc并使用DESTDIR=/path/to/glibc-2.23/build/install安装它,则其头文件将安装在目录/path/to/glibc-2.23/build/install/usr/include中。这意味着您应该能够使用-isysroot选项,该选项将重写默认的/usr/include目录,从而使搜索路径的顺序正确:
    #include "..." search starts here:
    #include <...> search starts here:
     .
     /project-foo/include
     /project-bar/include
     /usr/include/c++/6
     /usr/include/x86_64-linux-gnu/c++/6
     /usr/include/c++/6/backward
     /usr/lib/gcc/x86_64-linux-gnu/6/include
     /usr/lib/gcc/x86_64-linux-gnu/6/include-fixed
     /path/to/glibc-2.23/build/install/usr/include
    
    

    关于linux - 如何使g++正确使用我自己的glibc构建的 header ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62795463/

    相关文章:

    c++ - 你能初始化 unique_ptr 的 "static const vectors"吗? (C++17 与 GCC 7.3)

    c++ - g++ 编译不识别 '*' 使用 Armadillo 库进行矩阵乘法

    c++ - 缺少虚拟关键字的警告

    linux - linux include/net/net_namespace.h 中的 net_generic 函数是什么?

    c++ - 混合 C++ ABI 以针对遗留库进行构建

    c - 时间测量中的负值?

    c++ - create_directories() 与 create_directories()

    C++/Linux : Undefined reference to typeinfo, 但虚拟方法似乎没问题

    linux - 如何检查 RPM .spec 文件中是否存在文件?

    c - 如何从任意 pthread_t 获取线程 ID?