【问题标题】:Static linking - working with GTKmm application? - revised静态链接 - 使用 GTKmm 应用程序? - 修改
【发布时间】:2011-11-22 15:13:40
【问题描述】:

是否可以在 Gtk(mm) 程序上进行静态链接(编译)?我需要程序减少对用户系统依赖的中继。

我试试:

g++ -static data/Area.h data/Picture.cpp data/GLScene.cpp data/KBDialog.cpp data/Dialogs.h data/FilePreview.cpp data/MainWindow.cpp prog.cpp -o prog `pkg-config --cflags --libs  gtkmm-2.4 gtkglextmm-1.2 exiv2`

但它失败了:

/usr/bin/ld: cannot find -lgtkmm-2.4
/usr/bin/ld: cannot find -lGL
/usr/bin/ld: cannot find -latkmm-1.6
/usr/bin/ld: cannot find -lgdkmm-2.4
/usr/bin/ld: cannot find -lpangomm-1.4
/usr/bin/ld: cannot find -lgdk_pixbuf-2.0
/usr/lib/gcc/i686-linux-gnu/4.4.5/../../../../lib/libgio-2.0.a(glocalfileinfo.o): In function `lookup_gid_name':
(.text+0x207a): warning: Using 'getgrgid_r' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
/usr/lib/gcc/i686-linux-gnu/4.4.5/../../../../lib/libgio-2.0.a(glocalvfs.o): In function `g_local_vfs_parse_name':
(.text+0x26c): warning: Using 'getpwnam' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
/usr/lib/gcc/i686-linux-gnu/4.4.5/../../../../lib/libglib-2.0.a(gutils.o): In function `g_get_any_init_do':
(.text+0x1244): warning: Using 'getpwuid' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
/usr/lib/gcc/i686-linux-gnu/4.4.5/../../../../lib/libglib-2.0.a(gutils.o): In function `g_get_any_init_do':
(.text+0x1237): warning: Using 'setpwent' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
/usr/lib/gcc/i686-linux-gnu/4.4.5/../../../../lib/libglib-2.0.a(gutils.o): In function `g_get_any_init_do':
(.text+0x124f): warning: Using 'endpwent' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
/usr/lib/gcc/i686-linux-gnu/4.4.5/../../../../lib/libglib-2.0.a(gutils.o): In function `g_get_any_init_do':
(.text+0xf6e): warning: Using 'getpwnam_r' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
/usr/lib/gcc/i686-linux-gnu/4.4.5/../../../../lib/libgio-2.0.a(glocalfileinfo.o): In function `lookup_uid_data':
(.text+0x1eea): warning: Using 'getpwuid_r' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
/usr/lib/gcc/i686-linux-gnu/4.4.5/../../../../lib/libX11.a(xim_trans.o): In function `_XimXTransSocketUNIXConnect':
(.text+0xe23): warning: Using 'getaddrinfo' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
/usr/lib/gcc/i686-linux-gnu/4.4.5/../../../../lib/libgio-2.0.a(gnetworkaddress.o): In function `g_network_address_parse':
(.text+0xe3c): warning: Using 'getservbyname' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
/usr/lib/gcc/i686-linux-gnu/4.4.5/../../../../lib/libgio-2.0.a(gnetworkaddress.o): In function `g_network_address_parse':
(.text+0xe4c): warning: Using 'endservent' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
collect2: ld returned 1 exit status

【问题讨论】:

  • 好了,让我们看看我们能从这个输出中挑选出什么。
  • 我又添加了一个很长的新回复。
  • 你真的应该在你的第一个问题中提供更多的上下文......

标签: c++ linux gtk static-linking gtkmm


【解决方案1】:

我宁愿避免这样做,因为 GTK 依赖于棘手的低级库,这些库确实非常系统特定(可能是libfontconfig.so 等),并且包含系统特定信息(例如字体的内置路径...)。

我还认为 GTK 需要动态共享库来实现主题或样式(因此 GTK 本身调用 dlopen,而拥有一个静态链接 libdl 是不合理的)。

我建议至少动态链接 gtk 及其所有依赖项。

【讨论】:

  • 我只需要为 gtkglextmm 做静态链接。有什么想法吗?
  • 您只能静态链接一个库,例如gcc foo.o -Bstatic -lgtkglextmm -Bdynamic -lgtk ...
  • 但不要那样做,即使是对单个库也是如此。请参阅下面的答案
  • 我试过了,但我仍然收到第一篇文章中列出的前 6 行错误。
【解决方案2】:

(你的问题问了两次让我很生气,所以这里有一个更详细的答案,我可能会进一步编辑和完善)


为什么动态链接的共享库很有用?

首先,在当今的 Linux 系统上,几乎每个二进制文件都是动态链接的。在我的 Debian/Sid 系统上,我只有 /sbin/ldconfig /bin/sash/usr/bin/rar 静态链接的可执行文件,但还有大约七千个其他动态链接的可执行文件(在 /bin/usr/bin 下)。即使是像/sbin/init 这样的基本程序现在也可以动态链接。

使用shared libraries 动态链接 ELF 可执行文件有几个好处

  1. 避免浪费磁盘空间。当动态链接的可执行文件不存在时(1986 年,SunOS3.5,因为内核无法mmap 文件段),人们花了很多时间将多个二进制文件混合在一个文件中(我记得textedit 和@ 987654336@ 是同一个二进制文件,在 SunOS3.5 上混合了几个程序)以赢得磁盘空间。好的,今天的磁盘空间更便宜,但是如果我的七千个程序每个都必须静态链接libc,那将消耗几 GB 的磁盘空间(这意味着在安装 Linux 发行版时需要额外的 DVD 或数小时的网络上传)。

  2. 启用更轻松的更新。当打包系统(apt-getdpkg 和 Debian 上的朋友)升级一个公共共享库(如 GLibC 或 Gtk)时,它会替换动态链接的共享库(*.so 文件,称为ELF 共享对象)并且所有使用它们的二进制未来执行都获利。所以如果/usr/lib/libgtk-3.so 更新了,则无需更新/usr/bin/gedit 即可利用libgtk-3.so 中的错误修复;只需重新启动 gedit 将使其受益于 libgtk-3.so 的改进

  3. 更高效的整体 RAM 使用率。像libc.so 这样的文件几乎被每个进程使用,甚至libgtk-3.so 被几十个进程使用。其中大部分是mmap-ed 只读“文本”段(特别是包含可执行二进制机器代码和字符串等只读常量);此映射为使用它的每个进程使用相同的 RAM 单元。所以内存是共享的

  4. 遵守 LGPL 许可的法律 GTK 库的LGPL-2.1 许可证是合法允许您使用 GTK 的唯一原因(即运行 GTK 程序,并将您自己的程序与 GTK 链接)。此许可授予您权利,尤其是改进 GTK 或利用 GTK 改进的权利,但您不应禁止链接 /usr/lib/gtk-3.so 的(例如专有)程序的用户利用 GTK 本身内部的改进。 LGPL2.1 的第 6 节明确提到了动态链接。 您不得分发静态链接的 GTK 二进制文件,除非让用户能够升级其 GTK 库。最方便的方法是让您的 GTK 程序与libgtk-3.so 动态链接。一个不太简单的替代方法是分发静态链接的可执行文件及其对象*.o 文件以及如何针对假设改进的libgtk.a(不存在)静态重新链接它的说明。

    李>
  5. 插件能够动态加载其他库模块 程序可以在运行时使用dlopen 函数加载一些共享对象(基于mmap 系统调用,通过-ldl 库)。这就是在 Linux 上可以使用插件的方式。 GTK 非常积极地使用自己的这种能力:主题、样式和字体可能正在使用dlopen 并由dlopen-ing 实现适当的东西。由于dlopen 是动态加载器/lib64/ld-linux-x86-64.so.2 的公共接口,-ldl 库是一个动态共享对象libdl.so.2 与动态加载器共享功能和代码(它本身在每个动态链接的可执行文件中引用为“ELF 解释器” ”)。静态链接-ldl 是不常见且不明智的。甚至libc.so 库也可能加载其他模块(可能用于DNS 支持等...);某些功能在静态链接的可执行文件中受到限制(参见文件 /etc/nsswitch.conf 等)。

  6. 动态链接在启动时稍微慢一些,因为程序必须在启动时启动并动态加载(这是ld-linux-x86-64.so.2 的角色)它需要的所有动态库。动态库中的代码需要position independent code 否则动态加载的库的重定位部分会太大(并且启动时的重定位工作太长),这可能会花费额外的寄存器(这在 32位 x86 处理器,在 x86-64 或 AMD64 64 位处理器上更少),因此构成稍大的机器代码(在 32 位 x86 机器上,我们所说的大小增加了几个百分比和运行时间减慢;在 64 位机器上,它可以忽略不计)。当然,重新定位数十万个外部调用可能需要一些时间(而且 C++ 代码比 C 代码发生的更多,可能是因为名称混淆问题)。


为什么您(Marco)不应该静态链接您的 GTK 二进制文件

上面的前五点应该让你相信静态链接 GTK 是一件坏事。特别要注意法律方面 (LGPL):故意违反 LGPL 是一个巨大的职业错误,不要那样做。

如果您真的想要,经过数周的努力,您可能在技术上能够(通过重新编译和破解 GTK 源代码)将二进制文件与 GTK 静态链接(具有一些减少的功能,例如没有主题化),但这可能是不道德而且没用。如果您的老板愚蠢到要求您这样做,请尝试说服他(或另找工作)。而您在公共论坛上询问如何静态链接 GTK(我将其理解为“如何违反 LGPL 许可”)这一事实使您处于危险之中。有一些组织——比如gpl-violations——注意到了这一点。

我认为静态链接 GTK 程序没有任何有用的理由。甚至使用 GUI 库的专有程序也是动态链接的(一个很好的例子是 AMD FGLRX 驱动程序及其配套程序,如 amdccle,提供基于 Qt 的图形界面进行安装)。

当然,您可能想要处理依赖关系。把它留给你的 linux 发行版的包管理器。

如果您需要更多帮助,请详细说明您真正想做的事情,并让我们相信您不会因违反许可而寻求帮助。更好的是,尝试使用免费许可证分发您的软件,例如GPLv3

【讨论】:

  • 太棒了!!...涵盖了包括许可证在内的许多方面!
  • 感谢您为发布这么长的答案所做的努力。我想做静态链接,因为我的程序使用 gtkglextmm 库,而在我的发起人的 PC 上没有这样的库(我写的是 BA 论文)。他使用了一些旧的 Ubuntu 版本,遗憾的是 Packet Manager 无法在他的系统上安装该库(它只是找不到它)。所以他建议我做 gtkglextmm 的静态链接并将我的应用程序还给他。你对我有什么建议吗? :(
  • 只需静态链接一个库,正如我在第一次回复的评论中所建议的那样。
  • 删除-static;在终端中运行pkg-config --cflags --libs gtkmm-2.4 gtkglextmm-1.2 exiv2。将-lgdkglextmm-x11-1.2 替换为-Bstatic -lgdkglextmm-x11-1.2 -Bdynamic。将替换后的字符串放入您的Makefile。然后帮助你的推广者在他的机器上升级他的 Ubuntu。
  • 我不应该这样做:-Wl,-Bstatic -lgdkglextmm-x11-1.2 -Wl,-Bdynamic 吗?
猜你喜欢
  • 2011-01-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-04-12
  • 2012-05-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多