我正在使用 GNU 工具链构建一个项目,一切正常,直到我开始链接它,链接器抱怨它丢失/找不到
crti.o
。这不是我的目标文件之一,它似乎与 libc 有关,但我不明白为什么它需要这个crti.o
,它不会使用库文件,例如libc.a
?
我正在针对arm平台进行交叉编译。我在工具链中有该文件,但如何让链接器包含它?
crti.o
位于“库”搜索路径之一,但是否应该在库路径上查找 .o
文件?
gcc
和ld
的搜索路径是否相同?
crti.o
是引导库,通常很小。它通常静态链接到您的二进制文件中。应该可以在/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
感到困惑,并且您想看看它打开的路径来自哪里......
我在交叉编译时遇到了同样的问题。 crti.o 位于
事实证明,创建一个空目录
这是链接器中的错误吗?或者这种行为是否记录在某处?
就我而言
Linux Mint 18.0/Ubuntu 16.04
,我根本没有crti.o
:
$ find /usr/ -name crti*
我什么也没找到,所以我安装了开发者包:
sudo apt-get install libc6-dev
如果您找到一些库请阅读此处
好吧,我必须重新安装工具链,以便包含丢失的文件。这看起来很奇怪,因为它应该在 gcc 路径上找到它。我猜想主要问题是我的计算机上有 15 个左右不同的 crti.o 文件,但没有指向正确的文件。从那以后仍然没有成功,但现在可以了:-)感谢您的帮助:-)
我也遇到过类似的问题,因为交叉编译器设置不当。我像这样解决了这个问题:
/home/rob/compiler/usr/bin/arm-linux-gcc --sysroot=/home/rob/compiler hello.c
这假设 /lib、/usr/include 等存在于 sysroot 选项指向的位置。这可能不是事情应该如何完成的,但当我需要编译一个简单的 C 文件时,它让我摆脱了麻烦。
如果是交叉编译,请在LDFLAGS中添加sysroot选项
export LDFLAGS=""--sysroot=${SDKTARGETSYSROOT}" -L${SDKTARGETSYSROOT}/lib -L${SDKTARGETSYSROOT}/usr/lib -L${SDKTARGETSYSROOT}/usr/lib/arm-poky-linux-gnueabi/5.3.0"
我在默认安装 Ubuntu 8.04 时遇到了同样的问题。我必须手动获取 libc 开发人员标头/文件才能使其工作。
这为我解决了(为 ARM 交叉编译 pjsip):
export LDFLAGS='--sysroot=/home/me/<path-to-my-sysroot-parent>/sysroot'
除了这里的所有其他答案(以及@stsquad的好建议(https://stackoverflow.com/a/91595/385390)之外,还要考虑开发工具已升级且路径已更改但,在具体的开发项目中,automake生成的文件是陈旧的,查看以前的开发工具路径。在这种情况下尝试再次引导automake生成的文件。
如果没有引导脚本,也许这可以完成这项工作:
aclocal \
&& automake --gnu --add-missing \
&& autoconf --verbose --force --warnings=all \
&& autoupdate \
&& libtoolize -c -f -i \
&& autoreconf --install --symlink --force