【问题标题】:Fail to create an executable file linking a static library无法创建链接静态库的可执行文件
【发布时间】:2018-03-16 04:52:00
【问题描述】:

在文件夹test,我创建hello.h,hello.c,main.c。 我的目标是从hello.hhello.c 创建一个静态库,并从库和main.c 创建一个可执行文件。 以下是我所做的。

你好.h:

#ifndef HELLO_H  
#define HELLO_H  
void hello(const char* name);  
#endif

你好.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

不知道有什么问题?

【问题讨论】:

  • 文件:hello.c需要有声明:#include "hello.h"

标签: c linux ubuntu linker


【解决方案1】:

您需要提供 -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 的原因。

【讨论】:

  • 但是我很好奇如何在这里使用ld(虽然gcc更好)。然后我尝试了ld -o Cuteee main.o -L. -lmyhello,但仍然失败ld: warning: cannot find entry symbol _start; defaulting to 00000000004000b0./libmyhello.a(hello.o): In function 'hello':hello.c:(.text+0x1e): undefined reference to 'printf' 我再次感到困惑。
  • printf 来自 libc 库,因此您可能还需要使用 -lc 链接到它。
【解决方案2】:

这会考虑到您的 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.cmain.c 并允许它做正确的事 幕后的事情。您还没有尝试自己调用 cc1as

但相比之下,当你来链接你的程序时,你并没有使用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 链接 - 例如。 除非他们将应用程序定位到裸机环境,而您 可以看出原因。

【讨论】:

    【解决方案3】:

    以下建议的代码:

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

    现在建议对已发布的代码和命令行语句进行更改:

    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
    

    【讨论】:

      猜你喜欢
      • 2013-06-24
      • 1970-01-01
      • 1970-01-01
      • 2011-06-07
      • 2010-12-16
      • 2010-12-07
      • 2016-01-11
      • 2010-12-25
      • 2018-12-28
      相关资源
      最近更新 更多