如何使用pkg-config进行静态链接库

16

我想要静态链接通过pkg-config找到的libpng。

pkg-config --libs --static libpng

输出

-L/usr/local/Cellar/libpng/1.6.15/lib -lpng16 -lz

我在该目录中同时拥有 libpng16.alibpng16.dylib,如果我使用这些标志,库会以动态方式链接。

如何告诉 pkg-config 或链接器(最好是一种可移植的方式),我真的希望它以静态方式链接?

我已经尝试在 pkg-config 的标志之前添加 -static,但这会使 clang 的 ld 尝试并失败地链接 "crt0.o"。

5个回答

9

尝试:

-L/usr/local/Cellar/libpng/1.6.15/lib -l:libpng16.a -lz

使用-l和:字符,您可以指定文件名扩展名。
-l:选项在 GNU ld 2.24 手册中有文档记录:
-l namespec 将指定的归档文件或目标文件添加到链接文件列表中。此选项可使用任意次数。如果namespec的格式为:filename,则ld将在库路径中搜索名为filename的文件,否则它将在库路径中搜索名为libnamespec.a的文件。
在支持共享库的系统上,ld也可以搜索除libnamespec.a以外的其他文件。具体来说,在ELF和SunOS系统上,ld将在一个名为libnamespec.so的目录中搜索库,然后再搜索一个名为libnamespec.a的库。(按照惯例,.so扩展名表示共享库。)请注意,此行为不适用于:filename,它总是指定一个名为filename的文件。

3
很有趣。这是一个记录在案的选项吗?我使用的链接器(来自clang?)似乎不支持它:“ld:找不到库-l:libpng16.a”。 - Kornel
@porneL,是的,这已经有文档记录了。我已经编辑了一段来自手册的引用。 - Quip Yowert

9
pkg-config --static选项依赖于.pc文件中的正确标记。如果提供--static选项无法返回链接到libpng存档所需的正确信息,则无法使用pkg-config进行此目的。

我怀疑libpng(以及其他大多数软件包)在libpng 1.2之后的某个时候停止支持静态链接。他们可能仍然提供库存档,但libpng pkg-config文件不再正确标记以支持静态链接。您将不得不手动告诉ld使用静态库。


2
静态库在pc文件中的正确标记是什么样子的?现在我经常看到lib.pclib-static.pc,这肯定不是“正确”的方式,对吧? - Levi Morrison
在很久以前,例如2012年的ruby 1.9版本中,你会看到这样的代码:LIBRUBY_A=lib${RUBY_SO_NAME}-static.aLIBRUBYARG_STATIC=-l${RUBY_SO_NAME}-static,它们为静态库提供了标记。 - David C. Rankin

6

如果你有能力自己编译、修补和安装软件,而不是依赖于某个Linux发行版,那么你可以编辑.pc文件以支持静态链接。

下面是一个同时支持动态链接和静态链接的.pc文件示例。这是从我的Ubuntu系统中的/usr/lib/x86_64-linux-gnu/pkgconfig/xcb.pc文件中提取的:

prefix=/usr
exec_prefix=${prefix}
libdir=${prefix}/lib/x86_64-linux-gnu
includedir=${prefix}/include
xcbproto_version=1.11

Name: XCB
Description: X-protocol C Binding
Version: 1.11.1
Requires.private: pthread-stubs xau >= 0.99.2 xdmcp
Libs: -L${libdir} -lxcb
Libs.private: 
Cflags: -I${includedir}

如果你运行 pkg-config --libs xcb,它会假设你想要动态版本,并且只会给你返回 -lxcb。动态共享对象 xcb.so 将会知道如何加载所有自己的依赖项,因此在链接时不需要指定它们。
如果你运行 pkg-config --libs xcb --static,那么 .private 字段就会发挥作用,你将得到 -lxcb -lXau -lXdmcp
我还没有遇到过许多构建系统知道将 --static 参数传递给 pkg-config 的情况。因此,如果你的 .pc 文件仅用于支持静态链接,最好不要使用 .private 字段,并且无条件地提供所有人所需的所有依赖项。这样,即使他们不知道它是静态的或者不知道要将 --static 传递给 pkg-config,也可以成功地链接库。

但是如果动态库的变体也在库搜索路径中,就像问题中一样,这仍然会导致动态库的链接? - undefined
不,你需要在链接器中传递-static或者其他等效选项,告诉它使用静态库。 - David Grayson
是的,但是当静态库和动态库具有相同的名称并且都在搜索路径上时,动态库将被优先选择。因此,静态库必须具有不同的名称。 - undefined

0

我在我的Makefile中使用这个技巧。

LIBRARIES := $(shell pkg-config --libs libpng | sed -E 's/-l([a-z0-9]*)/-l:lib\1.a/g')

它从pkg config中获取输出并通过在每个项目前缀处添加“:”和库,并在后缀处添加“.a”来扩展它。最终结果正是您所需的。
-l:libpng.a -l:libz.a

0

在 @David Garyson 的帖子中,我想补充一点。如果使用命令 pkg-config --libs 时出现特定的 *.pc 文件不可用的情况,则可能需要将变量添加到您的 PATH 中。

Perhaps you should add the directory containing `nice.pc' to the PKG_CONFIG_PATH environment variable

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接