静态链接 - 使用 GTKmm 应用程序? - 修改

发布于 2024-12-17 08:43:50 字数 3312 浏览 1 评论 0原文

是否可以在 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

Is it possible to make a static linking (compilation) on Gtk(mm) program? I need the program to be less relaying on dependences in user's system.

I try:

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`

but It fails:

/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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

雾里花 2024-12-24 08:43:50

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

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

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

I would rather avoid doing that, because GTK depends on tricky low level libraries which are really very system specific (perhaps libfontconfig.so etc), and contains system-specific information (e.g. builtin paths for fonts...).

I also think that GTK needs dynamic shared libraries to implement theming or styling (so GTK itself is calling dlopen, and having a statically linked libdl is not reasonable).

I suggest at least linking dynamically gtk and all its dependencies.

掩耳倾听 2024-12-24 08:43:50

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

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

动态链接 ELF 可执行文件有几个好处

  1. 使用 共享库

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

  2. 实现更轻松的更新。当打包系统(apt-getdpkg 和 Debian 上的朋友)升级通用共享库(如 GLibC 或 Gtk)时,它会替换动态链接的共享库( *.so 文件,称为 ELF 共享对象)以及所有未来的二进制执行使用他们获利。因此,如果更新了 /usr/lib/libgtk-3.so,则无需更新 /usr/bin/gedit 即可利用 /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 支持等);某些功能在静态链接的可执行文件中受到限制(请参阅文件 /etc/nsswitch.conf 等)。

  6. 动态链接在启动时稍微慢一些,因为程序必须在启动时启动并动态加载(这是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-violations - 对此表示关注。

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

当然,您可能想要处理依赖关系。将其留给您的 Linux 发行版的包管理器。

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

Why dynamically linked shared libraries are useful?

First, almost every binary is dynamically linked on today's Linux systems. On my Debian/Sid system, I only have /sbin/ldconfig /bin/sash and /usr/bin/rar statically linked executables, but about seven thousand other dynamically linked executables (under /bin & /usr/bin). Even essential programs like /sbin/init are today dynamically linked.

There are several wins in having mostly dynamically linked ELF executables using shared libraries

  1. Avoid wasting disk space. When dynamically linked executables did not exist (1986 era, SunOS3.5, because the kernel was not able to mmap file segments), people took a lot of time mixing several binaries in a single one (I remember textedit and cmdtool being the same binary, a mix of several programs on SunOS3.5) to win disk space. Ok, disk space is cheaper today, but if my seven thousand programs each had to link statically libc that would consume several gigabytes of disk space (and that would mean an extra DVD or hours of networking upload when installing a Linux distribution).

  2. Enabling an easier update. When the packaging system (apt-get, dpkg and friends on Debian) upgrades a common shared library (like the GLibC or Gtk), it replaces the dynamically linked shared libraries (*.so files, called ELF shared objects) and all the future executions of binary using them take profit. So if /usr/lib/libgtk-3.so is updated, there is no need to update /usr/bin/gedit to take advantage of the bug fixes inside libgtk-3.so; just restarting gedit will make it profit of improvements in libgtk-3.so

  3. More efficient overall RAM usage. A file like libc.so is used by almost every process, and even libgtk-3.so is used by dozens of processes. Most of it is mmap-ed read-only "text" segment (notably containing the executable binary machine code and read-only constants like string); this mapping is using the same RAM cells for every process using it. So the memory is shared

  4. Legal compliance with LGPL license
    The LGPL-2.1 license of GTK libraries is the only reason why you are legally allowed to use GTK (i.e. run GTK programs, and link your own program with GTK). This license gives you rights, in particular the one to improve GTK or take advantage of GTK improvements, but you should not prohibit users of your (e.g. proprietary) program linking /usr/lib/gtk-3.so to take advantage of improvements inside GTK itself. The section 6 of LGPL2.1 mention explicitly dynamic linking. You are not allowed to distribute statically linked GTK binaries without giving the user the mean to upgrade his GTK library. The most convenient way is having your GTK program dynamically linked against libgtk-3.so. A less easy alternative would be to distribute your statically linked executable with its object *.o files and instructions on how to re-link it statically against an hypothetical improved libgtk.a (which don't exist).

  5. Plugin ability to dynamically load other library modules
    A program can load some shared object at run time using the dlopen function (based upon the mmap system call, thru the -ldl library). This is how plugins are possible on Linux. GTK uses itself very actively this ability: theming, styling, and perhaps fonts are using dlopen and implemented by dlopen-ing appropriate stuff. Since dlopen is a public interface to the dynamic loader /lib64/ld-linux-x86-64.so.2, the -ldl library is a dynamically shared object libdl.so.2 sharing functionality and code with the dynamic loader (itself referenced in every dynamically linked executable as the "ELF interpreter"). It is uncommon and unwise to link -ldl statically. Even the libc.so library may load other modules (perhaps for DNS support, etc...); some functionalities are restricted in statically linked executables (see file /etc/nsswitch.conf etc.).

  6. dynamic linking is slightly slower at startup time, since a program has to initiate and dynamically load (this is the role of ld-linux-x86-64.so.2) at startup all the dynamic libraries it needs. Code inside a dynamic library needs to be position independent code otherwise the relocation part of dynamically loaded libraries would be too big (and the relocation effort at start-up too long), which may cost an extra register (and this is mostly true on 32 bits x86 processors, much less on x86-64 or AMD64 64 bits ones) so makes up slightly bigger machine code (on 32 bits x86 machines, we are speaking of a few percents of size increase and runtime slowdown; on 64 bits machines, it is negligible). Of course, relocating hundred of thousands of external calls may take some time (and happens more with C++ code than with C code, perhaps because of name mangling issues).


Why you (Marco) should not statically link your GTK binary?

The five first points above should convince you that linking statically GTK is an evil thing to do. In particular, take attention of the legal aspects (LGPL): making knowingly an LGPL violation is a huge professional mistake, don't do that.

If you really wanted, with weeks of effort, you probably could be technically able (by recompiling and hacking GTK source code) to link statically your binary with GTK (with some reduced functionalities, like no theming), but that is probably unethical and useless. If your boss is stupid enough to require you that, try to convince him (or else find another job). And the very fact that you've asked on a public forum how to link statically GTK (which I am understanding as "how to violate the LGPL license") put you at risk. There are organizations -like gpl-violations- which take attention to that.

I don't see any useful reason to statically link a GTK program. Even proprietary programs using a GUI library are dynamically linked (a good example is AMD FGLRX driver and its companion programs like amdccle providing a Qt based graphical interface for installation).

Of course, you may want to deal with dependencies. Leave that to the package manager of your linux distribution.

If you want more help, please explain much more what you really want to do, and convince us that you don't ask help in violating a license. Better yet, try to distribute your software with a free license like e.g. GPLv3

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文