【问题标题】:How can get g++ to use my own glibc build's headers correctly?如何让 g++ 正确使用我自己的 glibc 构建的头文件?
【发布时间】:2020-10-28 21:41:09
【问题描述】:

如果上下文太多,最后会有一个 TL;DR!

上下文

我正在尝试将项目使用的 glibc 版本更新到 2.23(我知道它很旧,这是另一个问题)。为此,我需要更换库并使用相关的解释器。

我在更换解释器时遇到了一些问题,看起来像是 ABI 更改,所以我认为这可能是因为头文件发生了某种变化,并开始着手将这些文件包含到项目中。

起初我尝试使用-I 来包含标题,但出现错误(见下文)。后来我尝试设置--sysroot,但这很快就感觉像是错误的做事方式,因为我本质上是在重新发明g++已经对系统头文件所做的事情。后来我发现了另一种看起来更有希望的机制(参见问题部分)。

这可能是XY issue 吗?绝对可以,但不管怎样,我看到的问题对我来说似乎很奇怪。

问题

我研究了在 gcc 和 g++ 中是否存在不同的机制来包含系统库(例如 glibc)的标头。我找到了标志-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

研究

我在互联网上搜索了有类似问题的人,发现了以下相关内容:

最后一个是最有希望的;它讨论了为什么-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!

我发现了一些相关的事情:

我看到的唯一解决方案是完全重新编译 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!

尝试使用较新的标头会产生相同的包含问题:

> /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 构建中的标头,而不会意外包含 /usr/include 中的不兼容文件?

【问题讨论】:

  • 您阅读过GCC 的文档吗?而GNU cpp 呢? GCC 是免费软件,你可以重新编译并改进它
  • @BasileStarynkevitch 一些看起来相关的部分,但不是全部。有很多事情要经历!具体来说,我查看了常见问题解答并 grepped 了 glibc 和 headers 的完整 PDF 手册,这就是我进入 isystem 的原因。我还看了这里:gnu.org/software/libc/manual/html_mono/libc.html#Installation 修改 gcc 和/或重建它是最后的手段,我希望尽可能避免它,因为它会给我们的构建过程增加更多的“特殊性”。
  • 您可能需要查看GNU binutils 的文档,因为它是(或可能)由gccg++ 调用的

标签: linux gcc g++ glibc include-path


【解决方案1】:

在您的 GCC 版本中,&lt;cmath&gt; 使用 #include_next,这意味着您需要确保包含 cmath 文件的目录位于 之前(在包含搜索路径上)具有正确 math.h 的目录,用于您正在构建的 glibc 版本。

您可以使用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

【讨论】:

  • 我刚试过这个并编译了,但是运行时我仍然遇到Assertion info[DT_RPATH] == NULL'`的问题。既然它回答了这个问题,我仍然会接受这个,但如果您在评论中有任何关于断言问题的其他信息,那将不胜感激。如果答案太复杂,那么我只需要发布一个新问题。使用 --sysroot 最明显的事情是产生了应该在他们自己的问题中解决的新问题。谢谢!
  • 您可能使用-Wl,--rpath 构建了 glibc,这不起作用。
  • 确实我做了,尝试删除它,仍然没有快乐。我会问另一个问题:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-07
  • 2021-11-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多