如何创建一个可以与gcc / g ++链接的库.a文件

时间:2016-01-15 00:31:17

标签: gcc installation linker posix static-libraries

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

如果我正在编写和安装我自己的库,我在哪里放置.a文件(或者无论如何我都可以)以相同的方式链接到我的库?

如果重要,这个问题涉及Posix系统。目前我对如何在Windows中完成这项工作不感兴趣。

1 个答案:

答案 0 :(得分: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 - 选项。 请注意,您必须选择64/32位的链接风格 关心。将-m64替换为-m32,您就可以得到一些东西 不同。除/lib之外的便携式Posix选项为/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 <foo/bar.h>的类似内容。然后你可以 编译时没有特殊的-I选项,并且链接库没有特殊的-L 选项,只是-lfoo