无法创建链接静态库的可执行文件

时间:2018-03-16 04:52:00

标签: c linux ubuntu linker

在文件夹test中,我创建了hello.hhello.cmain.c。 我的目标是从hello.hhello.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

我想知道是不是有什么问题?

3 个答案:

答案 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)

以下提议的代码:

  1. 更正了已发布代码和命令行语句中的几个问题。
  2. 执行所需的操作
  3. 干净地编译/链接
  4. 现在建议更改已发布的代码和命令行语句:

    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.cmain.c,并允许它做正确的事 在幕后。您还没有尝试过自己调用cc1as

但相比之下,当你来链接你的程序时,你还没有使用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链接 - 例如 除非他们将应用程序定位到裸机环境,并且你 可以理解为什么。