是否可以在Gtk(mm)程序上进行静态链接(编译)? 我需要程序减less对用户系统依赖的中继。
我尝试:
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
我宁愿避免这样做,因为GTK依赖于棘手的低级库,它们实际上是非常libfontconfig.so
(也许是libfontconfig.so
等),并包含特定于系统的信息(例如内置的字体路径…)。
我也认为,GTK需要动态共享库来实现主题或样式(所以GTK本身调用dlopen
,并有一个静态链接的 libdl
是不合理的)。
我建议至少动态链接gtk及其所有的依赖关系。
(你的问题问了我两次,所以这里是一个更详细的答案,我可能会编辑和进一步完成)
为什么动态链接共享库是有用的?
首先, 几乎每个二进制文件都是在今天的Linux系统上动态链接的。 在我的Debian / Sid系统中,我只有/sbin/ldconfig
/bin/sash
和/usr/bin/rar
静态链接的可执行文件,但是大约有七千个动态链接的可执行文件(位于/bin
/usr/bin
)。 即使像/sbin/init
这样的重要程序也是今天动态链接的。
使用共享库大部分动态链接的ELF可执行文件有几个胜利
避免浪费磁盘空间 。 当动态链接的可执行文件不存在时(1986年,SunOS3.5,因为内核无法映射文件段),人们花了很多时间在单个文件中混合了几个二进制文件(我记得textedit
和cmdtool
是相同的二进制文件,在SunOS3.5上混合使用几个程序)来赢得磁盘空间。 好的,今天磁盘空间比较便宜,但是如果我的七千个程序每个都需要静态链接libc
,这会消耗几千兆字节的磁盘空间(这意味着在安装Linux发行版时需要额外的DVD或网络上传时间)。
启用更简单的更新 。 当包装系统(Debian上的apt-get
, dpkg
和friends)升级一个公共的共享库(如GLibC或者Gtk)时,它将替换动态链接的共享库( *.so
文件,称为ELF共享对象)以及所有未来二进制的执行使用它们获利。 因此,如果/usr/lib/libgtk-3.so
被更新,那么不需要更新/usr/bin/gedit
来利用libgtk-3.so
中的错误修复; 只要重新启动gedit
就会使其在libgtk-3.so
获得改进
整体RAM使用效率更高 。 几乎每个进程都使用像libc.so
这样的文件,甚至libgtk-3.so
也被几十个进程使用。 它大部分是mmap
-ed只读“文本”段(特别是包含可执行二进制机器码和只读常量,如字符串); 这个映射对于使用它的每个进程使用相同的RAM单元。 所以内存是共享的
遵从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
(不存在)进行静态链接。
插件能够动态加载其他库模块程序可以在运行时使用dlopen函数(基于mmap
系统调用,通过-ldl
库)加载一些共享对象。 这就是Linux上可能的插件。 GTK使用自己非常积极的这种能力:主题,造型,也许字体正在使用dlopen
并通过适当的东西来实现。 由于dlopen
是动态加载器/lib64/ld-linux-x86-64.so.2
的公共接口, -ldl
库是一个动态共享对象libdl.so.2
与动态加载器共享功能和代码(本身被引用在每个动态链接的可执行文件中作为“ELF解释器”)。 静态链接-ldl
是不常见也是不明智的。 即使是libc.so
库也可能加载其他模块(也许是为了支持DNS等)。 一些功能在静态链接的可执行文件中受到限制(请参阅文件/etc/nsswitch.conf
等)。
动态链接在启动时稍微慢一点,因为程序必须在启动所有需要的动态库时启动并动态加载(这是ld-linux-x86-64.so.2
的作用)。 动态库中的代码需要位置独立的代码,否则动态加载的库的重定位部分将会太大(并且启动时的重定位工作太长),这可能花费额外的寄存器(并且在32位x86处理器,在x86-64或AMD64 64位处理器上少得多),所以构成稍微大一些的机器代码(在32位x86机器上,我们谈到了几个百分点的尺寸增加和运行时减速;在64位机器上,可以忽略不计)。 当然,重新部署数以万计的外部调用可能需要一些时间(对C ++代码而言,发生的事情要比使用C代码更多,也许是因为名称改变的问题)。
为什么你 (Marco) 不应该静态链接你的GTK二进制文件 ?
上面的五个第一点应该说服你,静态链接GTK是一个邪恶的事情。 尤其要注意法律方面(LGPL):明知LGPL违规是一个巨大的职业错误,不要这样做。
如果你真的想要,经过数周的努力,你可能会在技术上(通过重新编译和黑客GTK源代码)静态链接你的二进制文件与GTK(一些减少的功能,如没有主题),但这可能是不道德的和无用的。 如果你的老板很愚蠢,要求你这么做,就试着说服他(或者找另外一份工作)。 而且你们在公共论坛上要求如何静态链接GTK(我理解为“ 如何违反LGPL许可证 ”),这一事实使你处于危险之中。 有组织,如gpl违规 ,这是注意到这一点。
我没有看到任何有用的理由来静态链接一个GTK程序。 即使使用GUI库的专有程序也是动态链接的(一个很好的例子是AMD FGLRX驱动程序及其配套程序,如提供基于Qt的图形界面进行安装的amdccle
)。
当然,你可能想要处理依赖关系。 把它留给你的linux发行版的包管理器。
如果您需要更多的帮助,请更多地解释您真正想要做的事情,并说服我们您不要求帮助违反许可证。 更好的是,尝试使用像GPLv3这样的免费许可来发布你的软件