这会考虑到您的 cmets:
然后我尝试了 ld -o Cuteee main.o -L。 -lmyhello 但仍因 ld 失败:警告:找不到条目符号 _start;默认为 00000000004000b0 ./libmyhello.a(hello.o): In function 'hello': hello.c:(.text+0x1e): undefined reference to 'printf' 我又困惑了。
gcc 是用于编译和链接 C 程序的 GCC 工具驱动程序。
当您使用表示您想要编译 C 的选项和输入调用它时
源文件,比如hello.c,它首先调用GNU C编译器cc1,来编译hello.c
文件到一个临时程序集文件,比如/tmp/cc8bfSqS.s。它悄悄地添加到编译器命令行
编译 C 时不变的各种样板选项
在您的系统上,免去您的麻烦。
然后它调用 GNU 汇编器 as,将 /tmp/cc8bfSqS.s 汇编到目标文件
hello.o.
如果您要求 gcc 详细,您可以从编译输出中挑选出所有这些内容,
例如
gcc -v -c hello.c
当您使用表示您想要链接的选项和输入调用 gcc 时
目标文件和可能的库到程序或共享库中,
它调用 GCC 内部工具 collect2 来执行此操作 -
依次调用系统链接器ld - 和gcc 悄悄地添加到命令行
许多样板选项、库和目标文件总是
需要链接 C 语言程序或共享库,再次
省去你的麻烦。
您已使用gcc 编译hello.c 和main.c 并允许它做正确的事
幕后的事情。您还没有尝试自己调用 cc1 和 as。
但相比之下,当你来链接你的程序时,你并没有使用gcc;你有
自己调用了ld,没有任何样板添加到
gcc 将创建的命令行。这就是链接失败的原因。
如果您在详细模式下将您的程序与gcc 链接:
gcc -v -o Cuteee main.o -L. -lhello
您可以从输出中选择collect2 命令行,类似于:
/usr/lib/gcc/x86_64-linux-gnu/7/collect2 \
-plugin /usr/lib/gcc/x86_64-linux-gnu/7/liblto_plugin.so \
-plugin-opt=/usr/lib/gcc/x86_64-linux-gnu/7/lto-wrapper \
-plugin-opt=-fresolution=/tmp/ccgWPdno.res \
-plugin-opt=-pass-through=-lgcc \
-plugin-opt=-pass-through=-lgcc_s \
-plugin-opt=-pass-through=-lc \
-plugin-opt=-pass-through=-lgcc \
-plugin-opt=-pass-through=-lgcc_s \
--sysroot=/ --build-id --eh-frame-hdr -m elf_x86_64 --hash-style=gnu \
--as-needed -dynamic-linker /lib64/ld-linux-x86-64.so.2 \
-pie -z now -z relro -o Cuteee \
/usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/Scrt1.o \
/usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/crti.o \
/usr/lib/gcc/x86_64-linux-gnu/7/crtbeginS.o -L. \
-L/usr/lib/gcc/x86_64-linux-gnu/7 \
-L/usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu \
-L/usr/lib/gcc/x86_64-linux-gnu/7/../../../../lib \
-L/lib/x86_64-linux-gnu -L/lib/../lib \
-L/usr/lib/x86_64-linux-gnu \
-L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/7/../../.. \
main.o -lhello -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc \
--as-needed -lgcc_s --no-as-needed \
/usr/lib/gcc/x86_64-linux-gnu/7/crtendS.o \
/usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/crtn.o
所有传递给collect2 的选项都传递给
ld。因此,如果您将 /usr/lib/gcc/x86_64-linux-gnu/7/collect2 替换为
ld 在那个怪物命令行中(或者更确切地说是你使用的命令行
你自己的系统),你会发现它链接了你的程序./Cuteee。
这就是将程序与gcc 链接所做的事情,在上面:
ld -o Cuteee hello.o -lmyhello
您的链接尝试失败的错误之一:
cannot find entry symbol _start
是因为你没有链接Scrt1.o (/usr/lib/x86_64-linux-gnu/Scrt1.o,
在上面的命令行中),其中包含 C 运行时初始化代码
一个动态链接的C程序:它定义了符号_start,它的地址是程序的入口点,
加载器在运行时和程序初始化后将初始控制传递给它
完成它调用main。
其他联动错误:
undefined reference to 'printf
是因为你没有链接标准C库-lc
(/lib/x86_64-linux-gnu/libc.so.6)。
如果没有必要,程序员不会直接与ld 链接 - 例如。
除非他们将应用程序定位到裸机环境,而您
可以看出原因。