【问题标题】:Is it possible to compile statically with gcc or g++ on Linux based systems?是否可以在基于 Linux 的系统上使用 gcc 或 g++ 进行静态编译?
【发布时间】:2015-11-20 08:48:47
【问题描述】:

我正在从事一个项目,我希望能够将其作为一个完整的可执行文件“运送”到其他基于 Linux 的计算机,并且没有依赖关系。 (为了我可以只将 1 个文件复制到其他系统,然后在这些系统上运行该文件。)

在 Windows 世界中,我认为静态链接只需将 -static 传递给编译器即可完成,如果您使用的是 Visual Studio,也许还可以为特定库提供一些其他选项*。

*eg: 使用 SFML 时您还必须出于某种原因定义 SFML_STATIC?

这可以使用 gcc / g++ 吗?如果可以,怎么做?我试图搜索这个,但没有找到任何东西。我之前听说这可能是一项艰巨的任务。

编辑:

BasileStarynkevitch 建议使用标志 -static 进行编译。

我不知道这是否是我想要的,但我写了一个测试程序来尝试一下:

#include <iostream>

int main()
{
    std::cout << "Link statically please" << std::endl;

    return 0;
}

然后编译为:

g++ main.cpp -o a.out -static
g++ main.cpp -o b.out

结果是:

-rwxr-xr-x  1  1653098  a.out
-rwxr-xr-x  1     9167  b.out

所以看起来它可能工作了?

TonyD 提出了一种检查方法:

ldd a.out 
not a dynamic executable

ldd b.out
linux-vdso.so.1 =>  (0x00007fff3d5ac000)
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007fce5e34a000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fce5df85000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fce5dc7e000)
/lib64/ld-linux-x86-64.so.2 (0x00007fce5e677000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007fce5da67000)

【问题讨论】:

  • 有可能,但可能不合理。你试过在 Linux 上使用 g++ -static 吗?
  • @BasileStarynkevitch 你能详细说明这一点吗?
  • 恐怕这是不可能的,因为像 glibc 这样的一些系统绑定库在不同的 linux 系统上可能会有所不同。通常的方法是发送源包并在目标系统上配置和编译它们。
  • 这是一个很好的问题,但没有研究工作....
  • @BasileStarynkevitch 为什么要将我的代码作为免费软件发布?对任何人都没有用?这是一个荒谬的问题。我想在我的组织内将我的代码形式机器移动到机器 - 不出售它。

标签: c++ linux gcc g++


【解决方案1】:

是否可以在基于 Linux 的系统上使用 gcc 或 g++ 进行静态编译?

视情况而定。

您可以尝试使用gcc -staticg++ -static 编译和链接所有代码。在某些情况下(例如纯命令行应用程序,比如你的 hello world),它会起作用。

Linux 发行版像很多共享库。他们中的大多数都广泛使用共享库(尤其是图形应用程序)。阅读 Drepper 的 How to Write Shared Libraries 论文了解更多信息。

您可能会遇到一些许可问题。为了简化,将代码静态链接到某些 LGPL(或 GPL)库可能是非法的(违反 LGPL 许可证)。邪恶在于细节。

一些核心功能,特别是与 DNS 相关的(例如 getaddrinfo(3)getnameinfo(3))在内部使用插件技术 à la dlopen(3),所以排序需要 动态 libc.so(请参阅nsswitch.conf(5) 了解更多)。

一些X11 的东西,特别是字体相关的东西,也期待插件相关的东西(IIRC,Xft);也许 SFML 使用它们。顺便说一句,SFML 很可能是作为共享库安装的,所以你需要从源代码重建 SFML...

最后,静态链接的程序可能比动态链接的程序更依赖于某个特定的内核版本(原则上,情况并非如此)。您可能会遇到与非常旧的或未来的内核不兼容的情况(但通常不会)。

另见ldd(1)file(1)pmap(1)proc(5)vdso(7)

将源代码发送到目标系统实际上可能更简单,让系统管理员安装所需的依赖项,然后在远程目标上构建代码(例如使用ssh

您可以尝试使用GCC linking options 静态链接大多数库,但不是全部(例如静态链接libstdc++.a 和动态链接libc.so)。见this & that

也许您应该首先尝试静态链接一些 SFML 演示......或者只是 scp 您的(动态链接的)二进制程序并尝试远程运行它(它可能能够运行)。

【讨论】:

  • 好问题...疯狂的地方。得到我的反对票。
【解决方案2】:

使用-static 编译似乎适用于基本的 c++ 程序,可能适用于所有标准库?

但是,当与其他库一起使用时,这可能不再有效。

【讨论】:

    猜你喜欢
    • 2021-10-27
    • 2015-11-08
    • 1970-01-01
    • 1970-01-01
    • 2011-01-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多