我正在使用GNU工具链构建一个项目,一切正常,直到我链接它,链接器抱怨它丢失/无法找到crti.o
。这不是我的目标文件之一,它似乎与libc有关但我无法理解为什么它需要这个crti.o
,它不会使用库文件,例如libc.a
?
我正在为手臂平台进行交叉编译。我在工具链中有该文件,但如何让链接器包含它?
crti.o
位于其中一个“库”搜索路径上,但是它应该在库路径中查找.o
文件吗?
gcc
和ld
的搜索路径是否相同?
答案 0 :(得分:23)
crti.o
是bootstrap库,通常很小。它通常静态链接到您的二进制文件。它应该在/usr/lib
。
如果您正在运行二进制发行版,他们倾向于将所有开发人员的东西放入-dev包(例如libc6-dev),因为不需要运行已编译的程序,只是为了构建它们。
你不是在进行交叉编译吗?
如果您正在进行交叉编译,那么gcc的搜索路径通常不会与您的crti.o匹配。它应该是在工具链的时候构建的。要检查的第一件事是gcc -print-search-dirs
并查看crti.o是否在任何这些路径中。
链接实际上是由ld完成的,但它的路径由gcc传递给它。找出正在发生的事情的最快方法可能就是编译一个helloworld.c程序并对其进行分析以查看传递给ld的内容并查看发生了什么。
strace -v -o log -f -e trace=open,fork,execve gcc hello.c -o test
打开日志文件并搜索crti.o,因为你可以看到我的非交叉编译器:
10616 execve("/usr/bin/ld", ["/usr/bin/ld", "--eh-frame-hdr", "-m", "elf_x86_64", "--hash-style=both", "-dynamic-linker", "/lib64/ld-linux-x86-64.so.2", "-o"
, "test", "/usr/lib/gcc/x86_64-linux-gnu/4."..., "/usr/lib/gcc/x86_64-linux-gnu/4."..., "/usr/lib/gcc/x86_64-linux-gnu/4."..., "-L/usr/lib/gcc/x86_64-linux-g
nu/"..., "-L/usr/lib/gcc/x86_64-linux-gnu/"..., "-L/usr/lib/gcc/x86_64-linux-gnu/"..., "-L/lib/../lib", "-L/usr/lib/../lib", "-L/usr/lib/gcc/x86_64-linux-gnu
/"..., "/tmp/cc4rFJWD.o", "-lgcc", "--as-needed", "-lgcc_s", "--no-as-needed", "-lc", "-lgcc", "--as-needed", "-lgcc_s", "--no-as-needed", "/usr/lib/gcc/x86_
64-linux-gnu/4."..., "/usr/lib/gcc/x86_64-linux-gnu/4."...], "COLLECT_GCC=gcc", "COLLECT_GCC_OPTIONS=\'-o\' \'test\' "..., "COMPILER_PATH=/usr/lib/gcc/x86_6"..., "LIBRARY_PATH=/usr/lib/gcc/x86_64"..., "CO
LLECT_NO_DEMANGLE="]) = 0
10616 open("/etc/ld.so.cache", O_RDONLY) = 3
10616 open("/usr/lib/libbfd-2.18.0.20080103.so", O_RDONLY) = 3
10616 open("/lib/libc.so.6", O_RDONLY) = 3
10616 open("test", O_RDWR|O_CREAT|O_TRUNC, 0666) = 3
10616 open("/usr/lib/gcc/x86_64-linux-gnu/4.2.3/../../../../lib/crt1.o", O_RDONLY) = 4
10616 open("/usr/lib/gcc/x86_64-linux-gnu/4.2.3/../../../../lib/crti.o", O_RDONLY) = 5
10616 open("/usr/lib/gcc/x86_64-linux-gnu/4.2.3/crtbegin.o", O_RDONLY) = 6
10616 open("/tmp/cc4rFJWD.o", O_RDONLY) = 7
如果您发现open(...crti.o) = -1 ENOENT
的一系列尝试,ld
感到困惑,您想知道它的开放路径来自哪里......
答案 1 :(得分:3)
交叉编译时遇到了同样的问题。 crti.o位于< sysroot> / usr / lib64 中,但链接器找不到它。
原来,创建一个空目录< sysroot> / usr / lib 修复了该问题。似乎链接器首先会搜索路径< sysroot> / usr / lib ,只有它存在时才会考虑< sysroot> / usr / lib64
这是链接器中的错误吗?或者这种行为记录在哪里?
答案 2 :(得分:3)
在我的案例Linux Mint 18.0/Ubuntu 16.04
中,我根本没有crti.o
:
$ find /usr/ -name crti*
我找不到任何内容,所以我安装了开发包:
sudo apt-get install libc6-dev
如果您找到一些图书馆read here
答案 3 :(得分:1)
好的,我必须重新安装工具链,以便随后包含丢失的文件。这看起来很奇怪,因为它应该在gcc路径上找到它。我猜的主要问题是我的计算机上有15个不同的crti.o文件而且没有指向正确的文件。仍然没有制作,但它现在有效:-)感谢您的帮助: - )
答案 4 :(得分:1)
我在设置错误的交叉编译器时遇到了类似的问题。我像这样绕过它:
/home/rob/compiler/usr/bin/arm-linux-gcc --sysroot=/home/rob/compiler hello.c
这假设/ lib,/ usr / include等存在于sysroot选项指向的位置。这可能不是应该如何完成的,但是当我需要编译一个简单的C文件时,它让我摆脱了麻烦。
答案 5 :(得分:1)
如果要交叉编译,请在LDFLAGS中添加sysroot选项
export LDFLAGS =“”-sysroot = $ {SDKTARGETSYSROOT}“ -L $ {SDKTARGETSYSROOT} / lib -L $ {SDKTARGETSYSROOT} / usr / lib -L $ {SDKTARGETSYSROOT} / usr / lib / arm-poky- linux-gnueabi / 5.3.0“
答案 6 :(得分:0)
我在默认的Ubuntu 8.04安装上遇到了同样的问题。我必须手动获取libc开发人员头文件/文件才能正常工作。
答案 7 :(得分:0)
这为我解决了(交叉编译ARM的pjsip):
export LDFLAGS='--sysroot=/home/me/<path-to-my-sysroot-parent>/sysroot'