【问题标题】:How to create an executable that links to a static library using a Makefile?如何使用 Makefile 创建链接到静态库的可执行文件?
【发布时间】:2021-08-02 19:15:42
【问题描述】:

我是 C 新手,Makefile 让我很难受。在 Makefile 中,我想制作一个链接到静态库的可执行文件。我的理解是,要从位于src/projecttest.c 生成可执行文件,命令将是gcc src/project/test.c -o test,并且该可执行文件将命名为test。如果我想让可执行文件也与静态库链接,lib.a 我该怎么做?

【问题讨论】:

  • 听起来你真正的困惑是关于在 C 中编译和链接,而不是 makefile……只是说。

标签: c makefile


【解决方案1】:

首先,lib.a 不是一个规范的“有效”静态库文件名,库文件名应该以 lib 开头并以库的实际名称继续,例如libsomething.a。然后,您可以将此类库与-lsomething 链接,假设它位于适当的系统目录中。如果没有,您可以添加-Lpath/to/directory 以使链接器也查看path/to/directory 以获取libsomething.a。另请参阅:Order in which library directories are searched and linked。或者,如果是静态库,您也可以将库直接添加到 GCC 命令行:gcc prog.c libsomething.a

在一个非常基本的Makefile 中,我会这样做:

test: src/project/test.c path/to/libsomething.a
    gcc $^ -o $@

【讨论】:

    【解决方案2】:

    如果我想让可执行文件也与静态库 lib.a 链接,我该怎么做?

    简短的回答是:只需将库包含在 gcc 命令中使用

            gcc src/project/test.c -o test libstuff.a
    

    或者使用

           gcc src/project/test.c -o test -lstuff -Llibfolder
    

    -Llibfolder 添加到完成库搜索的文件夹列表中。库的文件夹搜索顺序类似于#include 处理所发生的情况。

    回去制作

    我将展示一个最小的示例,说明如何在 Linux Ubuntu 20 下使用 C 语言构建和使用静态库,并通过一个非常短的 makefile 管理其使用。

    这是最小的,仅用于演示目的。有更好的方法来写这个,但我希望这样写会让你更容易遵循逻辑。

    注意:arLinux 中的存档器,就像Windows 中的LIB。管理库创建的程序。

    示例

    把这4个文件放在一个文件夹里

        Makefile  myLib.c  myLib.h  testing.c
    

    我们想从myLib.c 构建一个库libmyLib.a 并在testing 中使用它

    C 源代码

    对于图书馆:

    // myLib.h
    int twice(int);
    
    // myLib.c
    #include    <stdio.h>
    int twice(int value) { return value + value; }
    

    测试程序

    // testing.c
    #include <stdio.h>
    #include "myLib.h"
    int main(void)
    {   int x = 42;
        printf("x = %d, twice(%d) = %d\n", x, x, twice(x)  );
        return 0;
    }
    

    测试输出

    testing 只是调用twice(42) 并输出84

    x = 42, twice(42) = 84
    

    使用makefile

    我们想输入 make 并构建 libmyLib.a,编译 testing.c 并生成 testing

    类似的东西(make 输出现在被抑制):

    so_user@DSK-2009:~/projects/so0802$ ls -ltr
    total 32
    -rw-r--r-- 1 so_user so_user   266 Aug  2 17:46 Makefile
    -rw-r--r-- 1 so_user so_user    26 Aug  2 18:23 myLib.h
    -rw-r--r-- 1 so_user so_user   155 Aug  2 18:23 testing.c
    -rw-r--r-- 1 so_user so_user    79 Aug  2 18:23 myLib.c
    so_user@DSK-2009:~/projects/so0802$ make
    
    // supressed output //
    
    so_user@DSK-2009:~/projects/so0802$ ls -ltr
    total 44
    -rw-r--r-- 1 so_user so_user   266 Aug  2 17:46 Makefile
    -rw-r--r-- 1 so_user so_user    26 Aug  2 18:23 myLib.h
    -rw-r--r-- 1 so_user so_user   155 Aug  2 18:23 testing.c
    -rw-r--r-- 1 so_user so_user    79 Aug  2 18:23 myLib.c
    -rw-r--r-- 1 so_user so_user  1792 Aug  2 18:42 testing.o
    -rw-r--r-- 1 so_user so_user  1368 Aug  2 18:42 myLib.o
    -rw-r--r-- 1 so_user so_user  1510 Aug  2 18:42 libmyLib.a
    -rwxr-xr-x 1 so_user so_user 16760 Aug  2 18:42 testing
    so_user@DSK-2009:~/projects/so0802$ ./testing
    x = 42, twice(42) = 84
    so_user@DSK-2009:~/projects/so0802$ 
    
    

    make 是一个非常聪明的程序,它考虑了文件的最后修改时间,是的,使 内容保持最新。 make 基于所谓的 makefile,其名称默认为 Makefile。在 makefile 中要更新的东西称为targets

    makefile,即使是一个简短的项目,也可能是一件复杂的事情。但总比不使用要容易。

    make 运行会做什么?

    您可以将所谓的targets 呈现给make。如果您只输入make,程序将搜索名为Makefile 的文件,并在该文件中搜索名为all 的目标。

    下面的第一个命令只更新库,而第二个将尝试目标all

        make libMylib.a
        make
    

    make -n

    您可以随时尝试-nmake 将列出程序将执行哪些更新目标。

    按照上面的例子...

    so_user@DSK-2009:~/projects/so0802$ make -n
    make: Nothing to be done for 'all'.
    so_user@DSK-2009:~/projects/so0802$ 
    

    由于目标都已更新。现在假设 testing.c 已更改:

    so_user@DSK-2009:~/projects/so0802$ touch testing.c
    so_user@DSK-2009:~/projects/so0802$ ls -ltr
    total 44
    -rw-r--r-- 1 so_user so_user   266 Aug  2 17:46 Makefile
    -rw-r--r-- 1 so_user so_user    26 Aug  2 18:23 myLib.h
    -rw-r--r-- 1 so_user so_user    79 Aug  2 18:23 myLib.c
    -rw-r--r-- 1 so_user so_user  1792 Aug  2 18:42 testing.o
    -rw-r--r-- 1 so_user so_user  1368 Aug  2 18:42 myLib.o
    -rw-r--r-- 1 so_user so_user  1510 Aug  2 18:42 libmyLib.a
    -rwxr-xr-x 1 so_user so_user 16760 Aug  2 18:42 testing
    -rw-r--r-- 1 so_user so_user   155 Aug  2 18:57 testing.c
    so_user@DSK-2009:~/projects/so0802$ make -n 
    gcc -c -Wall testing.c
    gcc -o testing testing.o libmyLib.a
    so_user@DSK-2009:~/projects/so0802$ 
    

    你看到了,因为testing.c比较新,但是由于库没有改变,我们需要编译程序并将它与库链接:

    -rw-r--r-- 1 toninho toninho   266 Aug  2 17:46 Makefile
    -rw-r--r-- 1 toninho toninho    26 Aug  2 18:23 myLib.h
    -rw-r--r-- 1 toninho toninho    79 Aug  2 18:23 myLib.c
    -rw-r--r-- 1 toninho toninho  1368 Aug  2 18:42 myLib.o
    -rw-r--r-- 1 toninho toninho  1510 Aug  2 18:42 libmyLib.a
    -rw-r--r-- 1 toninho toninho   155 Aug  2 18:57 testing.c
    -rw-r--r-- 1 toninho toninho  1792 Aug  2 19:00 testing.o
    -rwxr-xr-x 1 toninho toninho 16760 Aug  2 19:00 testing
    

    但现在我们更改myLib.c 并尝试make -n

    so_user@DSK-2009:~/projects/so0802$ touch myLib.c
    so_user@DSK-2009:~/projects/so0802$ make -n
    gcc -c -Wall testing.c
    gcc -c -Wall myLib.c
    ar rcs libmyLib.a myLib.o
    gcc -o testing testing.o libmyLib.a
    so_user@DSK-2009:~/projects/so0802$ 
    

    由于库改变了,头文件也可能改变了,所以我们也需要编译testing.c。并调用ar 重建库,然后生成新的testing 可执行文件。

    这里使用的makefile

    all: testing
    
    clean:  
        rm *.o
        rm *.a
        rm testing
    
    testing: testing.o libmyLib.a
        gcc -o testing testing.o libmyLib.a
    
    testing.o: testing.c myLib.c myLib.h
        gcc -c -Wall testing.c
    
    myLib.o:    myLib.c myLib.h
        gcc -c -Wall myLib.c
    
    libmyLib.a: myLib.o
        ar rcs libmyLib.a myLib.o
    

    我希望大家对make 的情况有所了解。请随时回问。

    : 之前的东西是目标

    • clean 目标很常见,您在这里看到它只是删除了一些东西
    • 目标之后列出的内容称为依赖项,这很有意义:如果任何依赖项比目标更新,则运行依赖项行下方的命令。
    • make 在搜索要更新的目标时深度递归

    【讨论】:

      猜你喜欢
      • 2013-06-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-04-16
      • 2015-10-03
      • 2016-01-11
      • 2018-12-28
      • 2018-04-17
      相关资源
      最近更新 更多