关于gcc:Linux静态链接已经死了?

Linux static linking is dead?

事实上,Linux上的-static gcc标志现在不起作用。 让我引用GNU libc FAQ:

2.22. Even statically linked programs need some shared libraries
which is not acceptable for me. What
can I do?

{AJ} NSS (for details just type `info
libc"Name Service Switch"') won't
work properly without shared
libraries. NSS allows using different
services (e.g. NIS, files, db, hesiod)
by just changing one configuration
file (/etc/nsswitch.conf) without
relinking any programs. The only
disadvantage is that now static
libraries need to access shared
libraries. This is handled
transparently by the GNU C library.

A solution is to configure glibc with
--enable-static-nss. In this case you can create a static binary that will
use only the services dns and files
(change /etc/nsswitch.conf for this).
You need to link explicitly against
all these services. For example:

1
2
 gcc -static test-netdb.c -o test-netdb \
   -Wl,--start-group -lc -lnss_files -lnss_dns -lresolv -Wl,--end-group

The problem with this approach is
that you've got to link every static
program that uses NSS routines with
all those libraries.
{UD} In fact, one cannot say anymore that a libc compiled with this option
is using NSS. There is no switch
anymore. Therefore it is highly
recommended not to use
--enable-static-nss since this makes the behaviour of the programs on the
system inconsistent.

关于这个事实,现在有什么合理的方法可以在Linux上创建一个功能齐全的静态构建,或者静态链接在Linux上完全没用? 我的意思是静态构建:

  • 表现完全相同
    动态构建做(static-nss with
    不一致的行为是邪恶的!);
  • 适用于glibc环境和Linux版本的合理变体;


我认为这非常烦人,我认为将一个功能称为"无用"是很傲慢的,因为它在处理某些用例时遇到了问题。 glibc方法的最大问题在于它硬编码到系统库(gconv以及nss)的路径,因此当人们尝试在不同于它的Linux发行版上运行静态二进制文件时,它会中断。

无论如何,您可以通过将GCONV_PATH设置为指向适当的位置来解决gconv问题,这允许我在Ubuntu上构建二进制文件并在Red Hat上运行它们。


Concerning that fact is there any reasonable way now to create a full-functioning static build on Linux or static linking is completely dead on Linux?

我不知道在哪里可以找到历史性的引用,但是,静态链接在GNU系统上已经死了。 (我相信它在从libc4 / libc5过渡到libc6 / glibc 2.x期间死亡)

根据以下情况,该功能被视为无用:

  • 安全漏洞。静态链接的应用程序甚至不支持libc的升级。如果app在包含lib漏洞的系统上链接,那么它将在静态链接的可执行文件中保持不变。

  • 代码臃肿。如果在同一系统上运行许多静态链接的应用程序,则不会重用标准库,因为每个应用程序都包含其自己的所有内容副本。 (尝试du -sh /usr/lib了解问题的严重程度。)

尝试从10 - 15年前挖掘LKML和glibc邮件列表档案。我很确定很久以前我见过LKML的相关内容。


静态链接似乎并没有在Linux世界中获得太多爱。这是我的看法。

没有看到静态链接的吸引力的人通常在内核和低级操作系统的领域中工作。许多* nix库开发人员花了一辈子时间处理不可避免的问题,试图将一百个不断变化的库连接在一起,这是他们每天都在做的任务。如果你想知道他们喜欢的后空翻,请看一下autotools。

但是不应该让其他人花大部分时间在这上面。静态链接将为您从图书馆流失中缓冲带来很长的路要走。开发人员可以根据软件的计划升级其软件的依赖关系,而不是在出现新的库版本时被迫执行此操作。这对于面向用户的应用程序非常重要,这些应用程序具有复杂的用户界面,需要控制它们不可避免地依赖的许多低级库的流量。这就是为什么我将永远是静态链接的粉丝。如果您可以静态链接交叉编译的可移植C和C ++代码,那么您几乎可以将世界变成您的牡蛎,因为您可以更快地向世界上不断增长的设备提供复杂的软件。

从其他角度来看,有许多不同意的地方,并且开源软件允许所有这些都很好。


仅仅因为您必须动态链接到NSS服务并不意味着您无法静态链接到任何其他库。所有常见问题解答都说,即使是"静态"链接的程序也有一些动态链接的库。这并不是说静态链接是"不可能的"或它"不起作用"。


静态链接正在回升!

  • 许多(大多数?)Go编程语言可执行文件是静态链接的。

    • 增加的可移植性和向后兼容性是它们受欢迎的一个原因。
  • 其他编程语言也有类似的努力使静态链接变得非常简单,例如Haskell(我正在努力)。
  • 像NixOS / nixpkgs这样的可配置Linux发行版/软件包集可以静态链接大部分软件包(例如,它的pkgsStatic软件包集可以提供各种静态链接的可执行文件)。
  • 静态链接可以在链接时消除更好的未使用代码,从而使可执行文件更小。
  • 像musl这样的libcs??使静态链接变得容易和正确。
  • 一些大型软件行业领导者对此表示赞同。例如,Google正在编写针对静态链接的新libc("支持静态非PIE和静态PIE链接","我们不打算在此时投资动态加载和链接支持")。


添加其他答案:

由于其他答案中提到的原因,它不推荐用于大多数Linux发行版,但实际上有一些发行版专门用于运行静态链接的二进制文件:

  • stali
  • 睡眠
  • starchlinux
  • bifrost

来自stali描述:

static linux is based on a hand selected collection of the best tools
for each task and each tool being statically linked (including some X
clients such as st, surf, dwm, dmenu),

It also targets binary size reduction through the avoidance of glibc
and other bloated GNU libraries where possible (early experiments show
that statically linked binaries are usually smaller than their
dynamically linked glibc counterparts!!!). Note, this is pretty much
contrary to what Ulrich Drepper reckons about static linking.

Due to the side-benefit that statically linked binaries start faster,
the distribution also targets performance gains.

静态链接也有助于减少依赖性。

您可以在有关静态与动态链接的问题中阅读更多相关信息。