Linux静态链接已经死了?

时间:2010-08-07 12:25:00

标签: linux gcc glibc static-linking

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

  

2.22。即使是静态链接的程序也需要一些共享库   这对我来说是不可接受的。什么   我可以吗?

     

{AJ} NSS(详情请输入`info   libc“名称服务开关”'不会   没有共享就能正常工作   库。 NSS允许使用不同的   服务(例如NIS,文件,数据库,hesiod)   只需更改一个配置即可   文件(/etc/nsswitch.conf)没有   重新安排任何程序。唯一的   缺点是现在静止   图书馆需要访问共享   库。这是处理   透明地由GNU C库提供。

     

解决方案是配置glibc   --enable-静态NSS。在这种情况下,您可以创建一个静态二进制文件   仅使用服务dns和文件   (为此更改/etc/nsswitch.conf)。   您需要明确链接   所有这些服务。例如:

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

这种方法的问题是   你必须链接每个静态   使用NSS例程的程序   所有这些图书馆    {UD}事实上,人们不能再说使用此选项编译的libc了   正在使用NSS。没有开关   了。因此它高度   建议使用   --enable-static-nss,因为这会使程序的行为发生   系统不一致。

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

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

6 个答案:

答案 0 :(得分:38)

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

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

答案 1 :(得分:24)

  

关于这个事实是否现在有任何合理的方法在Linux上创建一个功能齐全的静态构建,或者静态链接在Linux上完全没用?

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

根据以下内容,该功能被视为无用:

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

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

尝试从10 - 15年前挖掘LKML和glibc邮件列表档案。很久以前我很确定我已经看到了与LKML相关的东西。

答案 2 :(得分:17)

静态链接似乎并没有得到Linux世界的热爱。这是我的看法。

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

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

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

答案 3 :(得分:12)

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

答案 4 :(得分:9)

添加其他答案:

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

来自stali描述:

  

静态linux是基于手工选择的最佳工具集合   为每个任务和每个工具静态链接(包括一些X.   客户如st,surf,dwm,dmenu),

     

它还通过避免glibc来减少二进制大小   和其他可能的膨胀GNU库(早期实验表明   静态链接的二进制文件通常比它们小   动态链接glibc对应!!!)。请注意,这几乎是   与Ulrich Drepper估计的静态连接相反。

     

由于静态链接二进制文件启动速度快的副作用,   该分布还针对性能提升。

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

您可以在this question about static vs dynamic linking中了解更多相关信息。

答案 5 :(得分:8)

静态链接又重新兴起!

  • 许多(最多?) Go 编程语言可执行文件是静态链接的。
    • 便携性和向后兼容性的增强是它们受欢迎的原因之一。
  • 其他编程语言也进行了类似的工作,以使真正的链接变得非常容易,例如 Haskell (我正在研究effort)。
  • 可配置的 Linux发行版 /像NixOS / nixpkgs这样的软件包集使得可以静态链接其大部分软件包(例如,其pkgsStatic软件包集可以提供各种静态链接的可执行文件。
  • 静态链接可以在链接时更好地消除未使用的代码,从而使可执行文件更小。
  • musl之类的libcs​​使静态链接变得容易且正确。
  • 一些大型软件行业领导人对此表示赞同。例如Google is writing new libc targeted at static linking“支持静态非PIE和静态PIE链接” “我们目前不打算投资[动态加载和链接支持“ )。