在尝试用C编写内核时,我遇到了一个奇怪的问题:当提示g静态编译一个非常基本的C文件并将其编译为二进制文件时,它总是跳过静态数学库(libm. a),最终无法编译。
尝试编译简单的C文件:
test.cpp
int main() {
return 0;
}
使用以下g++命令:
g++ -static test.cpp -Wl,--oformat=binary
我收到以下错误输出:
/usr/bin/ld: skipping incompatible /usr/lib/gcc/x86_64-linux-gnu/11/../../../x86_64-linux-gnu/libm.a when searching for -lm
/usr/bin/ld: skipping incompatible /lib/x86_64-linux-gnu/libm.a when searching for -lm
/usr/bin/ld: skipping incompatible /usr/lib/x86_64-linux-gnu/libm.a when searching for -lm
/usr/bin/ld: skipping incompatible /lib/x86_64-linux-gnu/libm.a when searching for -lm
/usr/bin/ld: skipping incompatible /usr/lib/x86_64-linux-gnu/libm.a when searching for -lm
/usr/bin/ld: cannot find -lm: No such file or directory
我正在虚拟机上运行Linux薄荷肉桂V.21(Vanessa)。
为了缩小问题的范围,我还尝试排除-static标志:
g++ test.cpp -Wl,--oformat=binary
这会导致完全不同的错误:
/usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/11/libstdc++.so: error adding symbols: file in wrong format
collect2: error: ld returned 1 exit status
经过彻底的研究,我意识到这可能是由于32位库和64位文件之间的不兼容造成的。所有内容都应该是64位的。我确实尝试使用file来确定libm. a的位数。
在/usr/lib/x86_64-linux-gnu/libm. a上使用文件命令时,我收到以下输出:
libm.a: ASCII text
这使我得出结论,可能库被损坏了,需要更新。但是,在运行sudo apt-get install libc 6-dev之后,问题仍然存在。
我不知道现在该怎么办。
更新:我已经在文本编辑器中打开了libm. a,文件的全部内容如下:
/* GNU ld script
*/
OUTPUT_FORMAT(elf64-x86-64)
GROUP ( /usr/lib/x86_64-linux-gnu/libm-2.35.a /usr/lib/x86_64-linux-gnu/libmvec.a )
更新2:显然这是一个链接器脚本,引用的文件libm-2.35.a
和libmvec.a
都在我的目录中,根据objdump,它们是64位版本。
根据编译器的错误输出,在我的例子中,不管什么原因,g++(或者更具体地说,ld)无法使用这个链接器脚本。
1条答案
按热度按时间pengsaosao1#
我得出的结论是,通常不可能将涉及面向对象特性的C代码静态链接到一个功能齐全的二进制文件中,因为libm. a显然只能链接到ELF。
此外:即使是静态版本的glibc,这也是必需的,引用其他动态库,使其对内核代码无用。
可能有一些变通的方法,但是g在默认情况下似乎不支持这个功能。