关于makefile:crti.o文件丢失

关于makefile:crti.o文件丢失

crti.o file missing

我正在使用GNU工具链构建一个项目,在我将其链接之前,一切正常,链接器抱怨该链接丢失/找不到crti.o。 这不是我的目标文件之一,它似乎与libc有关,但我不明白为什么它需要这个crti.o,不使用库文件,例如 libc.a

我正在交叉编译手臂平台。 我的工具链中有文件,但是如何使链接器包含它?

crti.o在"库"搜索路径之一上,但是否应该在库路径上寻找.o文件?

gccld的搜索路径是否相同?


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

如果您正在运行二进制发行版,它们倾向于将所有开发人员的资料放入-dev软件包(例如libc6-dev)中,因为运行编译的程序并不需要构建它们。

您不是交叉编译的吗?

如果您要交叉编译,通常是gcc的搜索路径与crti.o所在位置不匹配的问题。它应该在工具链建立时就已构建。首先要检查的是gcc -print-search-dirs,看看crti.o是否在这些路径中。

链接实际上是由ld完成的,但是它的路径是由gcc传递给它的。找出最新情况的最快方法是编译helloworld.c程序并跟踪它,以查看将什么传递给ld并查看正在发生的情况。

1
strace -v -o log -f -e trace=open,fork,execve gcc hello.c -o test

打开日志文件并搜索crti.o,您会看到我的非交叉编译器:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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位于 / usr / lib64中,但链接程序找不到它。

事实证明,创建一个空目录 / usr / lib可以解决此问题。似乎链接器将首先搜索路径 / usr / lib,只有存在时,它才会考虑使用 / usr / lib64。

这是链接器中的错误吗?还是在某处记录了这种行为?


对于我的Linux Mint 18.0/Ubuntu 16.04,我根本没有crti.o

1
$ find /usr/ -name crti*

我什么也没找到,所以我安装了开发人员软件包:

1
sudo apt-get install libc6-dev

如果您发现一些库,请在这里阅读


如果您是交叉编译,请在LDFLAGS中添加sysroot选项

export LDFLAGS ="-sysroot = $ {SDKTARGETSYSROOT}" -L $ {SDKTARGETSYSROOT} / lib -L ??$ {SDKTARGETSYSROOT} / usr / lib -L ??$ {SDKTARGETSYSROOT} / usr / lib / arm-poky-linux-gnueabi / 5.3.0"


设置错误的交叉编译器遇到了类似的问题。我这样绕过它:

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

假定sysroot选项指向的位置中存在/ lib,/ usr / include等。这可能不是应该做的事情,但是当我需要编译一个简单的C文件时,这使我摆脱了麻烦。


好的,我必须重新安装工具链,以便随后包括缺少的文件。似乎很奇怪,因为它应该在gcc路径上找到它。我猜的主要问题是我的计算机上有15个左右的crti.o文件,但没有指向正确的文件。从那以后仍然没有,但是现在可以了:-)感谢您的帮助:-)


这为我解决了(为ARM交叉编译pjsip):

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

我在默认的Ubuntu 8.04安装上遇到了同样的问题。我必须手动获取libc开发人员标头/文件才能运行。


推荐阅读