在文件夹test
中,我创建了hello.h
,hello.c
,main.c
。
我的目标是从hello.h
,hello.c
创建一个静态库,并从库中创建一个可执行文件main.c
。
以下是我所做的。
hello.h:
#ifndef HELLO_H
#define HELLO_H
void hello(const char* name);
#endif
的hello.c:
#include <stdio.h>
void hello(const char* name){
printf("hello %s! \n",name);
}
main.c中:
#include "hello.h"
int main(){
hello("everyone");
return 0;
}
在终端(在test
文件夹中):我运行
gcc -c hello.c
ar crv libmyhello.a hello.o // to create a staticlib
gcc -c main.c
ld -o Cuteee hello.o -lmyhello
>>> ld: cannot find -lmyhello
我想知道是不是有什么问题?
答案 0 :(得分:2)
您需要提供-L
让gcc知道查找-l
库的位置:
gcc -c hello.c
ar crv libmyhello.a hello.o
gcc -c main.c
gcc main.o -L. -lmyhello -o Cuteee
要创建最终的可执行文件,使用gcc就足够了,不需要ld。
请参阅this question以了解您可能不需要专门使用ld
的原因。
答案 1 :(得分:1)
以下提议的代码:
现在建议更改已发布的代码和命令行语句:
hello.h
#ifndef HELLO_H
#define HELLO_H
void hello( const char* );
#endif
=======================
hello.c:
#include <stdio.h>
#include "hello.h"
void hello(const char* name)
{
printf("hello %s! \n",name);
}
========================
main.c:
#include "hello.h"
int main( void )
{
hello("everyone");
return 0;
}
=========================
In terminal (in test folder):
gcc -Wall -Wextra -Wconversion -pedantic -std=gnu11 -c hello.c -o hello.o -I.
ar crv libmyhello.a hello.o
=========================
gcc -Wall -Wextra -Wconversion -pedantic -std=gnu11 -c main.c -o main.o -I.
ld -static main.o -o Cuteee -L. -lmyhello
=========================
./Cuteee
=========================
this should eliminate the error message:
>>> ld: cannot find -lmyhello
答案 2 :(得分:1)
这会考虑您的意见:
然后我尝试了ld -o Cuteee main.o -L。 -lmyhello但仍然失败,使用ld:warning:找不到条目符号_start;默认为00000000004000b0 ./libmyhello.a(hello.o):在函数&#39; hello&#39;:hello.c :(。text + 0x1e):未定义引用&#39; printf&#39;我又困惑了。
gcc
是用于编译和链接C程序的GCC tooldriver。
当您使用选项和输入调用它时,表示您想要编译C
源文件,比如hello.c
,它首先调用GNU C编译器cc1
来编译hello.c
文件到临时程序集文件,比如说/tmp/cc8bfSqS.s
。它悄然添加到编译器命令行
各种样板选项,对于编译C是不变的
在你的系统上,为你省事。
然后调用GNU汇编程序as
将/tmp/cc8bfSqS.s
汇编到目标文件
hello.o
。
如果你要求gcc
详细,你可以从编译输出中选出所有这些,
e.g。
gcc -v -c hello.c
当您使用表示您想要链接的选项和输入调用gcc
时
目标文件和可能的库到程序或共享库中,
它调用GCC内部工具collect2
来执行它 - 这个
反过来调用系统链接器ld
- 并且gcc
安静地添加到命令行
许多样板选项,库和目标文件总是如此
将C语言程序或共享库再次链接到
给你带来麻烦。
您已使用gcc
来编译hello.c
和main.c
,并允许它做正确的事
在幕后。您还没有尝试过自己调用cc1
和as
。
但相比之下,当你来链接你的程序时,你还没有使用gcc
;你&#39;已经
自己调用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
链接 - 例如
除非他们将应用程序定位到裸机环境,并且你
可以理解为什么。