1

我认为业内应该有关于这个问题的最佳实践,所以我在这里问它。

这个问题是关于在 Linux 上使用 gcc 将共享库(.so)链接到可执行文件。但让我从 Windows 开始。

假设我正在开发 A.EXE 、 B.DLL 、 C1.DLL 。依赖是

A -> B -> C1

这意味着:A从B调用API,B通过调用C1的API实现自己。A 不直接调用 C1 中的 API。

您知道,在链接 A.EXE(使用 Visual C++)时,我只需将 B.lib(导入 lib)列为 A 的链接组件(在 makefile 中);C1 不必出现在 A 的生成文件中。所以有一天我想用 C2 替换 C1 以更好地实现 B,我不必因为 C1 的替换而更改 A 的 makefile。

这很好,因为它遵循理性的想法:makefile 只引用它直接相关的东西。有了这种便利,人们倾向于在 Windows 上编写 DLL 而不是 LIB——我认为是这样。

现在我转向 linux 上的 gcc。对于相同的依赖场景,在 A 的 makefile 中,我必须将 C1 或 C2 显式列为链接组件,如下所示:

gcc -o A a1.o a2.o -lB -lC1 

如此令人沮丧,假设您有十个项目 A1、A2、... A10 调用到 B,您必须修改十个 makefile 才能从 C1 转移到 C2。

如何获得解脱?

4

2 回答 2

3

链接某些共享库libfoo.so时,您可以将其与另一个共享库链接libbar.so

  gcc -fPIC -g -Wall -c foo1.c
  gcc -fPIC -g -Wall -c foo2.c
  gcc -shared -o libfoo.so foo1.o foo2.o -lbar

然后当您使用时-lfoolibbar.so将自动链接而不要求它。

因此,您不必在 A 的 makefile 中明确列出 C1 或 C2 作为链接组件。

如果您只有静态库,您将不得不这样做lib*.a

所以你可以用

  gcc -Wall -g prog.c -lfoo

单独(未libbar.so明确提及)。

例如尝试ldd在 GTK 共享库上运行(在我的 Debian 系统上):

  ldd /usr/lib/x86_64-linux-gnu/libgtk-3.so.0

我建议阅读Levine 的链接器和加载器一书.dll以了解 Windows和 Linux之间的区别.so;他们是不同的野兽。另请阅读程序库 HowTo

您可能想要(或不想要)使用GNU libtool

顺便说一句,您也可以使用pkg-config,这将提供依赖项......

于 2013-02-25T08:02:32.100 回答
1

确保您libB依赖libC( ldd libB.so) ;libB应该用类似的东西编译gcc -o libB.so -shared -fPIC *.c -L/path/to/libC -lC -Wl,-rpath,/path/to/libC

注意libB.so需要编译-rpath才能定位libC.so,或者使用LD_LIBRARY_PATH环境变量(ldd上面提到的命令一定不能显示libC.so => not found

于 2013-02-25T08:13:27.543 回答