Mar*_*rco -2 c++ linux gtk gtkmm static-linking
是否可以在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`
Run Code Online (Sandbox Code Playgroud)
但它失败了:
/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
Run Code Online (Sandbox Code Playgroud)
(你的问题让我两次生气,所以这里有一个更详细的答案,我可以编辑并进一步完成)
为什么动态链接共享库很有用?
首先,几乎每个二进制文件都在当今的Linux系统上动态链接.在我的Debian/Sid系统上,我只有/sbin/ldconfig /bin/sash和/usr/bin/rar静态链接的可执行文件,但大约有七千个其他动态链接的可执行文件(在/bin&下/usr/bin).即使像/sbin/init今天这样的基本程序也会动态链接
使用共享库主要动态链接ELF可执行文件有几个胜利
避免浪费磁盘空间.当动态链接的可执行文件不存在时(1986年,SunOS3.5,因为内核无法mmap文件段),人们花了很多时间将几个二进制文件混合在一起(我记得textedit并且cmdtool是相同的二进制文件,在SunOS3.5上混合使用多个程序来赢得磁盘空间.好吧,磁盘空间今天更便宜,但如果我的七千个程序每个都必须静态链接libc,这将消耗几千兆字节的磁盘空间(这意味着安装Linux发行版时需要额外的DVD或数小时的网络上传).
实现更轻松的更新.当包装系统(apt-get,dpkg和朋友在Debian)升级一个共享库(如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适当的东西.由于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驱动程序及其配套程序,如amdccle提供基于Qt的图形界面进行安装).
当然,您可能想要处理依赖项.把它留给linux发行版的包管理器.
如果您需要更多帮助,请解释更多您真正想做的事情,并说服我们您不会在违反许可证方面寻求帮助.更好的是,尝试使用免费许可证(例如GPLv3)分发您的软件
我宁愿避免这样做,因为GTK依赖于棘手的低级库,这些库实际上是非常特定于系统的(可能是libfontconfig.so等等),并且包含系统特定的信息(例如字体的内置路径......).
我还认为GTK需要动态共享库来实现主题或样式(因此GTK本身就是调用dlopen,并且静态链接 libdl是不合理的).
我建议至少动态链接gtk及其所有依赖项.