【问题标题】:How to make a library .a file linkable with gcc/g++如何使库 .a 文件可与 gcc/g++ 链接
【发布时间】:2016-01-15 00:31:17
【问题描述】:

当我想编译使用 libspotify 的东西时,我可以通过在编译命令中包含术语 -lspotify 来链接 libspotify 库,然后一切正常。

如果我正在编写和安装自己的库,我应该将 .a 文件放在哪里(或者无论如何我该怎么做)才能以相同的方式链接到我的库?

如果重要的话,这个问题与 Posix 系统有关。目前我对如何在 Windows 中完成此操作不感兴趣。

【问题讨论】:

    标签: gcc installation linker posix static-libraries


    【解决方案1】:

    只要链接器 (ld) 知道在哪里查找,您就可以将您的库放在任何地方 为它。

    链接器如何知道在哪里寻找库?

    您可以通过出现一次或多次的命令行选项来告诉它在哪里查找 -L<directory>.

    如果你链接选项

    -L/look/here/first -L/look/here/second -lfoo
    

    然后ld 查找库,libfoo.so(共享)或libfoo.a(静态),首先进入 /look/here/first;在/look/here/second 中失败了;失败了 它将查看配置的默认位置列表,并失败任何 他们会失败,抱怨找不到-lfoo。虽然顺序 -L 选项很重要,-l 选项相对于 `-L 选项的顺序 没关系:

    -lfoo -L/look/here/first -L/look/here/second
    

    意思相同。

    一旦它在某处找到libfoo,链接器就不会再寻找,并且在每个目录中 它在哪里查找,默认情况下它会先查找libfoo.so,然后再查找libfoo.a

    通常我们不会通过直接调用ld 来链接。我们通过调用一个链接 特定语言的工具驱动程序,gccg++gfortran 等,通过 它选项指示它进行链接,而不是预处理或编译。 在这种情况下,工具驱动程序代表我们调用ld,并在幕后调用 附加附加的链接器选项,这些选项对于语言是不变的 有问题,使我们不必在命令行上记住和重复样板。

    ld 本身,但是,每个架构都有一个内置的默认-L 目录列表 它支持。这些是由构建您的ld 的人配置的,通常是您的发行版, 在这种情况下,您会发现默认位置是库所在的目录 通常由发行版的包管理器安装。

    因此,如果您想链接位于默认位置之一的库,您不需要 需要自己指定任何-L 选项。 -lfoo 可以。

    相反,如果您希望能够简单地链接libfoo.a 通过在链接命令行上提及-lfoo,然后您需要将其放入 链接器的默认位置之一。如果你想在这样的地方分发libfoo.a 其他用户可以以相同方式链接它的方式,然后您需要分发 它在一个包中,它将安装在默认位置之一(在目标上 系统,不管它是什么)。

    为此,您需要知道默认位置是什么。对于 Posix 系统, 您可以依赖/usr/local/lib/lib/usr/lib。但不要安装在/lib。 这是为重要的系统库保留的。查看链接器的默认搜索 目录实际上在您自己的系统上,您可以运行:

    gcc -m64 -Xlinker --verbose  2>/dev/null | grep SEARCH_DIR
    

    它会发出类似:

    SEARCH_DIR("=/usr/local/lib/x86_64-linux-gnu"); \
    SEARCH_DIR("=/lib/x86_64-linux-gnu"); \
    SEARCH_DIR("=/usr/lib/x86_64-linux-gnu"); \
    SEARCH_DIR("=/usr/local/lib64"); \
    SEARCH_DIR("=/lib64"); \
    SEARCH_DIR("=/usr/lib64"); \
    SEARCH_DIR("=/usr/local/lib"); \
    SEARCH_DIR("=/lib"); \
    SEARCH_DIR("=/usr/lib"); \
    SEARCH_DIR("=/usr/x86_64-linux-gnu/lib64"); \
    SEARCH_DIR("=/usr/x86_64-linux-gnu/lib");
    

    告诉你这些目录是默认的-L-options,按这个顺序。 请注意,您必须选择您想要的 64/32 位链接风格 很担心。将-m64 替换为-m32,你会得到一些东西 不同的。可移植的 Posix 选项(不包括 /lib)是 /usr/local/lib/usr/lib

    这回答了你的问题,但你还没有完成。大概,你的图书馆 带有一个或多个头文件,程序可以通过这些头文件导入其 API。 如果库将位于链接器的默认搜索路径中,则标头 最好在编译器的默认搜索路径中,这样程序就可以 只需#include <foo.h>#include <foo/bar.h> 并拥有编译器 无需在编译器命令行中编写 -I/foo/headers/are/here 即可找到标头。

    要查看编译器的默认搜索路径,对于 C,运行:

    echo | gcc -xc -E -v -
    

    相关的输出将类似于:

     #include "..." search starts here:
     #include <...> search starts here:
     /usr/lib/gcc/x86_64-linux-gnu/5/include
     /usr/local/include
     /usr/lib/gcc/x86_64-linux-gnu/5/include-fixed
     /usr/include/x86_64-linux-gnu
     /usr/include
    

    或者对于 C++:

    echo | gcc -xc++ -E -v -
    

    显示,例如:

     #include "..." search starts here:
     #include <...> search starts here:
     /usr/include/c++/5
     /usr/include/x86_64-linux-gnu/c++/5
     /usr/include/c++/5/backward
     /usr/lib/gcc/x86_64-linux-gnu/5/include
     /usr/local/include
     /usr/lib/gcc/x86_64-linux-gnu/5/include-fixed
     /usr/include/x86_64-linux-gnu
     /usr/include
    

    与图书馆的案例相呼应,可移植的 Posix 选项 标头为/usr/local/include/usr/include

    所以这是/usr/local/{include|lib}/usr/{include|lib} 之间的选择。但考虑到 在/usr/{include|lib} 下安装您的文件,您将更改 以不受控制的方式清点发行版的库和头文件 通过其包管理系统。如果它是,比如说,Debian 8.2,它就不会再有了。 一旦你开始这样做,一旦你做了一个错误的步骤并破坏了你的包裹, 这完全是你的问题。

    Unix 和 Linux 对安装您构建的软件有一个约定 自己或来自不受发行版包管理控制的源包 系统,它明智地保护了您的发行版的稳定性。约定是: 安装在/usr/local/{include|bin|lib}。这正是/usr/local 是什么 为了。

    底线:将您的库安装在/usr/local/lib 下,并将您的标题安装在 /usr/local/include。如果您有多个标题,则更喜欢/usr/local/include/foo 并在程序源中写#include &lt;foo/bar.h&gt;之类的。那么你就可以 编译没有特殊的-I 选项并链接库没有特殊的-L 选项,只需-lfoo

    【讨论】:

    • 这个答案非常彻底。它不仅回答了我的问题,而且可以作为我和(我认为)许多其他人的参考。非常感谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多