【发布时间】: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
研究
我在互联网上搜索了有类似问题的人,发现了以下相关内容:
- 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!
尝试使用较新的标头会产生相同的包含问题:
> /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 中的不兼容文件?
【问题讨论】:
-
@BasileStarynkevitch 一些看起来相关的部分,但不是全部。有很多事情要经历!具体来说,我查看了常见问题解答并 grepped 了 glibc 和 headers 的完整 PDF 手册,这就是我进入 isystem 的原因。我还看了这里:gnu.org/software/libc/manual/html_mono/libc.html#Installation 修改 gcc 和/或重建它是最后的手段,我希望尽可能避免它,因为它会给我们的构建过程增加更多的“特殊性”。
-
您可能需要查看GNU binutils 的文档,因为它是(或可能)由
gcc或g++调用的
标签: linux gcc g++ glibc include-path