2011-11-22 72 views
-3

是否可以在Gtk(mm)程序上进行静态链接(编译)?我需要该程序减少用户系统中的依赖性。静态链接 - 使用GTKmm应用程序? - 修订

我尝试:

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 
+1

* <争吵和名称调用已移除> * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * – BoltClock

+0

我添加了另一个长的新答复。 –

+0

你真的应该在第一个问题中给出更多的上下文....... –

回答

5

我宁愿避免这样做,因为GTK取决于这真的是非常系统的具体(或许libfontconfig.so等棘手的底层库),并包含特定于系统的信息(例如字体的内置路径...)。

我也认为GTK需要动态共享库来实现主题化或造型(所以GTK本身是调用dlopen,并具有静态链接libdl是不合理的)。

我建议至少动态链接gtk和它的所有依赖。

+0

我只需要为gtkglextmm做静态链接。有任何想法吗? – Marco

+0

您只能静态链接一个单独的库,例如'gcc foo.o -Bstatic -lgtkglextmm -Bdynamic -lgtk ...' –

+0

但是不要那样做,即使是单个库。请参阅下面的答案 –

8

(你的问题问两次让我懊恼,所以这里是我可能会修改并完成进一步更详细的解答)


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

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

有使用shared libraries

  1. 避免浪费磁盘空间几个胜在有大部分动态链接的ELF可执行文件。当动态链接的可执行文件不存在时(1986年代,SunOS3.5,因为内核无法使用mmap文件段),人们花费大量时间在单个文件中混合多个二进制文件(我记得texteditcmdtool是相同的二进制文件,在SunOS3.5上混合使用几个程序)来赢得磁盘空间。好的,今天磁盘空间更便宜,但是如果我的七千个程序每个都必须静态链接libc,这会消耗几千兆字节的磁盘空间(这意味着在安装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实现 - 适当的东西。由于dlopen是动态加载程序/lib64/ld-linux-x86-64.so.2的公共接口,因此-ldl库是一个动态共享对象libdl.so.2,它与动态加载程序(本身在每个动态链接的可执行文件中作为“ELF解释程序”引用)共享功能和代码。将-ldl静态链接是不常见也是不明智的。即使是libc.so库也可能会加载其他模块(可能用于DNS支持等)。一些功能在静态链接的可执行文件中受到限制(请参阅文件​​等)。

  6. 动态链接在启动时稍微慢一点,因为程序必须在启动它所需的所有动态库时启动并动态加载(这是ld-linux-x86-64.so.2的作用)。动态库内的代码需要为position independent code,否则动态加载的库的重定位部分将会太大(并且启动时的重定位工作太长),这可能需要额外的寄存器(这在32位x86处理器,在x86-64或AMD64 64位处理器上少得多)因此构成稍微更大的机器代码(在32位x86机器上,我们谈到了几个百分点的尺寸增加和运行时减速;在64位机器上,这是微不足道的)。当然,重新部署数十万个外部调用可能需要一些时间(对于C++代码而言,使用C代码的情况比使用C代码的情况更多,这可能是因为名称修改问题)。


为什么你(马可)不应该静态链接你的GTK二进制

上面的五个第一点应该让你相信,静态链接GTK是一件邪恶的事情。尤其要注意法律方面(LGPL):明知故犯LGPL违规是一个巨大的职业错误,不要这样做。如果你真的想要,经过数周的努力,你可能在技术上能够(通过重新编译和黑客GTK源代码)静态链接你的二进制文件与GTK(有一些缩减的功能,如没有主题),但这是可能不道德和无用。如果你的老板足够愚蠢地要求你这么做,试着说服他(或者找另一份工作)。而且,您在公共论坛上要求如何静态链接GTK(我理解为“如何违反LGPL许可证”),这一事实使您处于危险之中。有一些组织 - 如gpl-violations - 它们会关注这一点。

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

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

如果您需要更多帮助,请解释更多您真正想要做的事情,并说服我们您不要求违反许可协议。更好的是,尝试使用免费许可证来分发您的软件,例如GPLv3

+1

辉煌!!涵盖许多方面,包括许可证! –

+0

我很感谢你在发布这个长答案时的努力。我想做静态链接,因为我的程序使用了gtkglextmm库,在我的启动者的PC上没有这样的库(我写了BA论文)。他使用了一些旧的Ubuntu版本,可悲的是Packet Manager无法在系统上安装该库(它只是没有找到它)。所以他建议我做一下gtkglextmm的静态链接,然后让他回到我的应用程序。你有什么建议吗? :( – Marco

+0

只需静态链接一个库,就像我在第一个回复的评论中建议的那样。 –