crti.o文件丢失

29
我正在使用GNU工具链构建项目,一切正常,直到链接时出现了问题,链接器抱怨找不到文件。这不是我的目标文件之一,似乎与libc有关,但我不明白为什么它需要这个,难道不应该使用库文件,例如吗?
我正在为arm平台交叉编译。我在工具链中有这个文件,但如何让链接器将其包含进来? 在其中一个“库”搜索路径上,但它是否应该在库路径上寻找<.o>文件?
对于和,搜索路径是否相同?

对于 Mac,请参见:https://dev59.com/6nM_5IYBdhLWcg3wdy_z#16102800 https://dev59.com/K2TWa4cB1Zd3GeqPGLuH#16102769 - kenorb
8个回答

30

crti.o 是引导库,通常很小。它通常静态链接到二进制文件中。应该在 /usr/lib 中找到。

如果你正在运行二进制发行版,它们倾向于把所有开发人员的东西放入-dev包中(例如libc6-dev),因为这些不需要用来运行已编译的程序,只需要用来构建它们。

你没有进行交叉编译吧?

如果你正在进行交叉编译,通常问题出现在gcc的搜索路径与crti.o所在的位置不匹配。它应该在工具链构建时被构建。首先要检查的是gcc -print-search-dirs并查看其中是否有crti.o所在的路径。

实际上,链接工作是由ld完成的,但是它的路径是由gcc传递给它的。可能最快的方法是编译一个helloworld.c程序并对其进行strace,以查看传递给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 非常有用的 strace 技巧。但我的问题仍未解决(在 ARM 上交叉编译 pjsip)。 - FractalSpace
@FractalSpace,可能是另一个问题。你能发布一个带有你得到的输出的问题吗? - stsquad
@stsquad 这是工具链配置错误的同样问题。我已经找到了一个解决方案,可以为我修复这个问题。请查看下面的答案。 - FractalSpace

7
我在交叉编译时遇到同样的问题。crti.o在<sysroot>/usr/lib64中,但链接器无法找到它。
结果发现创建一个空目录<sysroot>/usr/lib解决了这个问题。似乎链接器首先会搜索路径<sysroot>/usr/lib,只有存在时才会考虑<sysroot>/usr/lib64
这是链接器的一个bug吗?还是这种行为有文档记录?

2
这对我有效。我不敢想象你必须经历多少麻烦才能发现这个问题。不知道这是一个错误还是什么 - 但或许值得在GNU ld的bugzilla或邮件列表上跟进一下。 - Tom Anderson

7
在我的情况下,Linux Mint 18.0/Ubuntu 16.04中根本没有crti.o
$ find /usr/ -name crti*

我没有找到任何东西,所以我安装了开发者包:
sudo apt-get install libc6-dev

如果你想找一些库,点击这里


1

好的,我不得不重新安装工具链,这样缺失的文件就被包含了。这似乎很奇怪,因为它应该在gcc路径上找到它。我想主要问题是我电脑上有15个左右不同的crti.o文件,并没有指向正确的文件。虽然还是不太明白,但现在它可以工作了 :-) 感谢您的帮助 :-)


1

我曾经遇到过一个类似的问题,是由于交叉编译器设置不当引起的。我通过以下方式解决了这个问题:

/home/rob/compiler/usr/bin/arm-linux-gcc --sysroot=/home/rob/compiler hello.c

这假设/sysroot选项指向的位置存在/lib、/usr/include等文件夹。这可能不是正确的做法,但当我需要编译一个简单的C文件时,它帮了我的大忙。


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"

0

这对我有用(交叉编译pjsip为ARM):

export LDFLAGS='--sysroot=/home/me/<path-to-my-sysroot-parent>/sysroot'

0

我在默认的Ubuntu 8.04安装中遇到了同样的问题。我不得不手动获取libc开发人员头文件/文件才能使其正常工作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接