【问题标题】:How to static link libexpat.so.1 with GCC?如何将 libexpat.so.1 与 GCC 静态链接?
【发布时间】:2017-05-06 13:53:01
【问题描述】:

我想用 GCC/G++ 构建静态程序,没有共享依赖项。但我不知道该怎么做。

在 Netbeans IDE 中使用以下命令,我可以使用共享依赖项进行构建,但在某些操作系统中找不到该库(我不想在新系统上安装)

-Wl,--dynamic-linker=/usr/lib/libexpat.so.1

【问题讨论】:

  • 你不能静态链接.so库,你需要得到一个.a
  • 你的“下面的命令”没有做你认为它做的事情;它应该生成一个无法运行的可执行文件根本(我希望它在启动时崩溃)
  • @Barmar 感谢您的快速回复。我在 '/usr/lib/libexpat.a' 路径中找到了 libexpat 库,现在用 gcc/g++ 编译和链接 .a 的开关是什么?
  • @MehdiH。-L 的参数是目录,而不是文件名。当您使用 -lexpat 时,这些选项会添加到它搜索库的目录中
  • 对于/usr/lib 中的库,您不需要使用-L,它位于默认库搜索路径中。因此,只需与-lexpat 进行静态链接即可。

标签: linux gcc netbeans g++


【解决方案1】:

要静态链接程序,您需要一个静态库,它是一个文件名以.a 结尾的库。

默认情况下,链接器如果使用默认搜索路径(就像您使用 /usr/lib 所做的那样),将选择 .so 库版本并将对其进行动态链接,所以如果您想要指定你想要一些静态的library你需要指定它的完整路径名,而不是使用-l 选项。所以,

gcc -o your_program mod_a.o mod_b.o ... /usr/lib/libexpat.a

优于

gcc -o your_program mod_a.o mod_b.o ... -lexpat

(后者会选择文件/usr/lib/libexpat.so,它应该是指向/usr/lib/libexpat.so.1的链接,通常是库的soname,也是/usr/lib/libexpat.so.1.xx.xx的符号链接)

注意

在示例中,我试图通过编译器调用链接器,因为默认的 c 运行时和库是在以这种方式调用时由编译器自动选择的。如果您喜欢直接调用链接器,过程不会改变,但您必须自己添加 C 运行时模块和标准 c 库。

注意 2

如果你想静态链接所有东西,那么你必须使用你将要使用的所有库的静态版本(它们通常安装在与动态库相同的目录中,所以你必须在命令行中指定 all 的完整路径名)为了在永久开发系统中解决这个问题,您可以从另一个路径创建指向它们的符号链接,然后将该目录指定为您的项目的搜索路径,该路径必须是静态的链接。

如果您总是希望某个库静态链接,只需删除/usr/lib 中的.so 链接(不是.so.X.so.X.YY 链接,编译器不会尝试它们)和@编译器默认选择 987654335@ 文件。当然,如果你想为每个库都做这个,你可以删除所有的 .so 链接,但你会得到比原始动态链接版本更大的可执行文件(大得多)。

【讨论】:

  • 谢谢,我现在可以静态构建,但它的可执行文件大小很吓人,在 Ubuntu 13 中相同的命令是 2-MB,在 Ubuntu 7 上相同的是 5-MB,似乎链接器全部插入函数可执行,如何编译和链接只需要的函数
  • 当然,所有库现在都包含在您的可执行文件中......就是这样!!!
  • 你有什么建议让我只链接必要的功能?
  • 我建议您静态链接那些不应该安装在目标系统中的库。无论如何,最好将库安装为共享而不是安装静态二进制文件......这通常只在引导时未安装主库的嵌入式系统上才需要,并且您需要在这些库可用之前运行一些可执行文件(例如在 initrd 图像中)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多