C - 动态链接成功但静态不会

C - dynamic linking suceeds but static will not

我正在 Linux Debian 10 上编译一个 example for IUP 图形工具包。我下载了示例并将其保存在 main.c 下。如您所见,如果您遵循 link #include 预处理器指令,则如下所示:

#include <stdlib.h>
#include <stdio.h>
#include <iup.h>

我写了一个 makefile,用于创建动态 linked 可执行文件或静态 linked 可执行文件:

#############################################################################################################

dynamic:

    gcc -liup -o dynamic.elf main.c

#############################################################################################################

static: static.o

    ld -e main -o static.elf static.o \
        -l:libiup.a \
        -lgtk-3 \
        -lgdk-3 \
        -lpangocairo-1.0 \
        -lX11 \
        -lcairo \
        -lgdk_pixbuf-2.0 \
        -lm \
        -lpango-1.0 \
        -lgobject-2.0 \
        -lglib-2.0 \
        -lpthread \
        -lc

static.o: main.c

    gcc -c -Wall -Wpedantic -o static.o main.c

#############################################################################################################

现在如果我 运行 使用 make dynamic 编译可执行文件并且它可以正常工作。它被 link 编辑到许多共享库:

ziga@ziga-laptop:2020-03-26--example-a$ ldd dynamic.elf 
    linux-vdso.so.1 (0x00007ffd413cf000)
    libiup.so => /lib/libiup.so (0x00007f4ecb4be000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f4ecb2fd000)
    libgtk-3.so.0 => /lib/x86_64-linux-gnu/libgtk-3.so.0 (0x00007f4ecac0c000)
    libgdk-3.so.0 => /lib/x86_64-linux-gnu/libgdk-3.so.0 (0x00007f4ecab10000)
    libpangocairo-1.0.so.0 => /lib/x86_64-linux-gnu/libpangocairo-1.0.so.0 (0x00007f4ecab00000)
    libcairo.so.2 => /lib/x86_64-linux-gnu/libcairo.so.2 (0x00007f4eca9e0000)
    libgdk_pixbuf-2.0.so.0 => /lib/x86_64-linux-gnu/libgdk_pixbuf-2.0.so.0 (0x00007f4eca9b8000)
    libpango-1.0.so.0 => /lib/x86_64-linux-gnu/libpango-1.0.so.0 (0x00007f4eca96d000)
    libgobject-2.0.so.0 => /lib/x86_64-linux-gnu/libgobject-2.0.so.0 (0x00007f4eca918000)
    libglib-2.0.so.0 => /lib/x86_64-linux-gnu/libglib-2.0.so.0 (0x00007f4eca7f9000)
    libX11.so.6 => /lib/x86_64-linux-gnu/libX11.so.6 (0x00007f4eca6b8000)
    libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f4eca535000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f4ecb85f000)
    libgmodule-2.0.so.0 => /lib/x86_64-linux-gnu/libgmodule-2.0.so.0 (0x00007f4eca52d000)
    libXi.so.6 => /lib/x86_64-linux-gnu/libXi.so.6 (0x00007f4eca31d000)
    libXcomposite.so.1 => /lib/x86_64-linux-gnu/libXcomposite.so.1 (0x00007f4eca11a000)
    libXdamage.so.1 => /lib/x86_64-linux-gnu/libXdamage.so.1 (0x00007f4eca115000)
    libXfixes.so.3 => /lib/x86_64-linux-gnu/libXfixes.so.3 (0x00007f4ec9f0f000)
    libcairo-gobject.so.2 => /lib/x86_64-linux-gnu/libcairo-gobject.so.2 (0x00007f4ec9f03000)
    libatk-1.0.so.0 => /lib/x86_64-linux-gnu/libatk-1.0.so.0 (0x00007f4ec9ed8000)
    libatk-bridge-2.0.so.0 => /lib/x86_64-linux-gnu/libatk-bridge-2.0.so.0 (0x00007f4ec9ea3000)
    libxkbcommon.so.0 => /lib/x86_64-linux-gnu/libxkbcommon.so.0 (0x00007f4ec9e61000)
    libwayland-cursor.so.0 => /lib/x86_64-linux-gnu/libwayland-cursor.so.0 (0x00007f4ec9e57000)
    libwayland-egl.so.1 => /lib/x86_64-linux-gnu/libwayland-egl.so.1 (0x00007f4ec9e52000)
    libwayland-client.so.0 => /lib/x86_64-linux-gnu/libwayland-client.so.0 (0x00007f4ec9e41000)
    libepoxy.so.0 => /lib/x86_64-linux-gnu/libepoxy.so.0 (0x00007f4ec9d0d000)
    libgio-2.0.so.0 => /lib/x86_64-linux-gnu/libgio-2.0.so.0 (0x00007f4ec9b4f000)
    libharfbuzz.so.0 => /lib/x86_64-linux-gnu/libharfbuzz.so.0 (0x00007f4ec9a54000)
    libpangoft2-1.0.so.0 => /lib/x86_64-linux-gnu/libpangoft2-1.0.so.0 (0x00007f4ec9a3b000)
    libfontconfig.so.1 => /lib/x86_64-linux-gnu/libfontconfig.so.1 (0x00007f4ec99f5000)
    libfreetype.so.6 => /lib/x86_64-linux-gnu/libfreetype.so.6 (0x00007f4ec9939000)
    libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f4ec9916000)
    libXinerama.so.1 => /lib/x86_64-linux-gnu/libXinerama.so.1 (0x00007f4ec9911000)
    libXrandr.so.2 => /lib/x86_64-linux-gnu/libXrandr.so.2 (0x00007f4ec9706000)
    libXcursor.so.1 => /lib/x86_64-linux-gnu/libXcursor.so.1 (0x00007f4ec96f9000)
    libXext.so.6 => /lib/x86_64-linux-gnu/libXext.so.6 (0x00007f4ec94e7000)
    librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007f4ec94db000)
    libpixman-1.so.0 => /lib/x86_64-linux-gnu/libpixman-1.so.0 (0x00007f4ec9435000)
    libpng16.so.16 => /lib/x86_64-linux-gnu/libpng16.so.16 (0x00007f4ec93fc000)
    libxcb-shm.so.0 => /lib/x86_64-linux-gnu/libxcb-shm.so.0 (0x00007f4ec93f7000)
    libxcb.so.1 => /lib/x86_64-linux-gnu/libxcb.so.1 (0x00007f4ec93cd000)
    libxcb-render.so.0 => /lib/x86_64-linux-gnu/libxcb-render.so.0 (0x00007f4ec93be000)
    libXrender.so.1 => /lib/x86_64-linux-gnu/libXrender.so.1 (0x00007f4ec91b2000)
    libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007f4ec8f94000)
    libthai.so.0 => /lib/x86_64-linux-gnu/libthai.so.0 (0x00007f4ec8f89000)
    libfribidi.so.0 => /lib/x86_64-linux-gnu/libfribidi.so.0 (0x00007f4ec8f6c000)
    libffi.so.6 => /lib/x86_64-linux-gnu/libffi.so.6 (0x00007f4ec8f62000)
    libpcre.so.3 => /lib/x86_64-linux-gnu/libpcre.so.3 (0x00007f4ec8eec000)
    libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f4ec8ee7000)
    libdbus-1.so.3 => /lib/x86_64-linux-gnu/libdbus-1.so.3 (0x00007f4ec8e94000)
    libatspi.so.0 => /lib/x86_64-linux-gnu/libatspi.so.0 (0x00007f4ec8e60000)
    libmount.so.1 => /lib/x86_64-linux-gnu/libmount.so.1 (0x00007f4ec8e01000)
    libselinux.so.1 => /lib/x86_64-linux-gnu/libselinux.so.1 (0x00007f4ec8bd7000)
    libresolv.so.2 => /lib/x86_64-linux-gnu/libresolv.so.2 (0x00007f4ec8bbd000)
    libgraphite2.so.3 => /lib/x86_64-linux-gnu/libgraphite2.so.3 (0x00007f4ec8b90000)
    libexpat.so.1 => /lib/x86_64-linux-gnu/libexpat.so.1 (0x00007f4ec8b53000)
    libuuid.so.1 => /lib/x86_64-linux-gnu/libuuid.so.1 (0x00007f4ec8b4a000)
    libXau.so.6 => /lib/x86_64-linux-gnu/libXau.so.6 (0x00007f4ec8944000)
    libXdmcp.so.6 => /lib/x86_64-linux-gnu/libXdmcp.so.6 (0x00007f4ec873e000)
    libdatrie.so.1 => /lib/x86_64-linux-gnu/libdatrie.so.1 (0x00007f4ec8734000)
    libsystemd.so.0 => /lib/x86_64-linux-gnu/libsystemd.so.0 (0x00007f4ec8693000)
    libblkid.so.1 => /lib/x86_64-linux-gnu/libblkid.so.1 (0x00007f4ec863e000)
    libbsd.so.0 => /lib/x86_64-linux-gnu/libbsd.so.0 (0x00007f4ec8622000)
    liblzma.so.5 => /lib/x86_64-linux-gnu/liblzma.so.5 (0x00007f4ec85fa000)
    liblz4.so.1 => /lib/x86_64-linux-gnu/liblz4.so.1 (0x00007f4ec85db000)
    libgcrypt.so.20 => /lib/x86_64-linux-gnu/libgcrypt.so.20 (0x00007f4ec84bd000)
    libgpg-error.so.0 => /lib/x86_64-linux-gnu/libgpg-error.so.0 (0x00007f4ec849a000)

当我 运行 make static 它编译但在执行时程序说:

ziga@ziga-laptop:2020-03-26--example-a$ ./static.elf 
bash: ./static.elf: No such file or directory

当程序存在并且拥有 +x 权限时:

ziga@ziga-laptop:2020-03-26--example-a$ ls -la | grep static.elf
-rwxr-xr-x 1 ziga ziga 1072080 Mar 30 22:36 static.elf

这就是程序 static.elf 被 link 编辑到共享对象 的方式(libiup.so 在我们 link 编辑到静态版本 libiup.a):

ziga@ziga-laptop:2020-03-26--example-a$ ldd static.elf 
    linux-vdso.so.1 (0x00007ffc73500000)
    libgtk-3.so.0 => /lib/x86_64-linux-gnu/libgtk-3.so.0 (0x00007f17f7e4d000)
    libgdk-3.so.0 => /lib/x86_64-linux-gnu/libgdk-3.so.0 (0x00007f17f7d51000)
    libpangocairo-1.0.so.0 => /lib/x86_64-linux-gnu/libpangocairo-1.0.so.0 (0x00007f17f7d41000)
    libX11.so.6 => /lib/x86_64-linux-gnu/libX11.so.6 (0x00007f17f7c00000)
    libcairo.so.2 => /lib/x86_64-linux-gnu/libcairo.so.2 (0x00007f17f7ae0000)
    libgdk_pixbuf-2.0.so.0 => /lib/x86_64-linux-gnu/libgdk_pixbuf-2.0.so.0 (0x00007f17f7aba000)
    libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f17f7935000)
    libpango-1.0.so.0 => /lib/x86_64-linux-gnu/libpango-1.0.so.0 (0x00007f17f78ea000)
    libgobject-2.0.so.0 => /lib/x86_64-linux-gnu/libgobject-2.0.so.0 (0x00007f17f7895000)
    libglib-2.0.so.0 => /lib/x86_64-linux-gnu/libglib-2.0.so.0 (0x00007f17f7776000)
    libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f17f7755000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f17f7594000)
    libgmodule-2.0.so.0 => /lib/x86_64-linux-gnu/libgmodule-2.0.so.0 (0x00007f17f758c000)
    libXi.so.6 => /lib/x86_64-linux-gnu/libXi.so.6 (0x00007f17f737c000)
    libXcomposite.so.1 => /lib/x86_64-linux-gnu/libXcomposite.so.1 (0x00007f17f7179000)
    libXdamage.so.1 => /lib/x86_64-linux-gnu/libXdamage.so.1 (0x00007f17f7174000)
    libXfixes.so.3 => /lib/x86_64-linux-gnu/libXfixes.so.3 (0x00007f17f6f6e000)
    libcairo-gobject.so.2 => /lib/x86_64-linux-gnu/libcairo-gobject.so.2 (0x00007f17f6f62000)
    libatk-1.0.so.0 => /lib/x86_64-linux-gnu/libatk-1.0.so.0 (0x00007f17f6f37000)
    libatk-bridge-2.0.so.0 => /lib/x86_64-linux-gnu/libatk-bridge-2.0.so.0 (0x00007f17f6f02000)
    libxkbcommon.so.0 => /lib/x86_64-linux-gnu/libxkbcommon.so.0 (0x00007f17f6ec0000)
    libwayland-cursor.so.0 => /lib/x86_64-linux-gnu/libwayland-cursor.so.0 (0x00007f17f6eb6000)
    libwayland-egl.so.1 => /lib/x86_64-linux-gnu/libwayland-egl.so.1 (0x00007f17f6eb1000)
    libwayland-client.so.0 => /lib/x86_64-linux-gnu/libwayland-client.so.0 (0x00007f17f6ea0000)
    libepoxy.so.0 => /lib/x86_64-linux-gnu/libepoxy.so.0 (0x00007f17f6d6c000)
    libgio-2.0.so.0 => /lib/x86_64-linux-gnu/libgio-2.0.so.0 (0x00007f17f6bae000)
    libharfbuzz.so.0 => /lib/x86_64-linux-gnu/libharfbuzz.so.0 (0x00007f17f6ab3000)
    libpangoft2-1.0.so.0 => /lib/x86_64-linux-gnu/libpangoft2-1.0.so.0 (0x00007f17f6a9a000)
    libfontconfig.so.1 => /lib/x86_64-linux-gnu/libfontconfig.so.1 (0x00007f17f6a54000)
    libfreetype.so.6 => /lib/x86_64-linux-gnu/libfreetype.so.6 (0x00007f17f6998000)
    libXinerama.so.1 => /lib/x86_64-linux-gnu/libXinerama.so.1 (0x00007f17f6991000)
    libXrandr.so.2 => /lib/x86_64-linux-gnu/libXrandr.so.2 (0x00007f17f6786000)
    libXcursor.so.1 => /lib/x86_64-linux-gnu/libXcursor.so.1 (0x00007f17f6779000)
    libXext.so.6 => /lib/x86_64-linux-gnu/libXext.so.6 (0x00007f17f6567000)
    librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007f17f655d000)
    libxcb.so.1 => /lib/x86_64-linux-gnu/libxcb.so.1 (0x00007f17f6531000)
    libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f17f652c000)
    libpixman-1.so.0 => /lib/x86_64-linux-gnu/libpixman-1.so.0 (0x00007f17f6486000)
    libpng16.so.16 => /lib/x86_64-linux-gnu/libpng16.so.16 (0x00007f17f644d000)
    libxcb-shm.so.0 => /lib/x86_64-linux-gnu/libxcb-shm.so.0 (0x00007f17f6448000)
    libxcb-render.so.0 => /lib/x86_64-linux-gnu/libxcb-render.so.0 (0x00007f17f6439000)
    libXrender.so.1 => /lib/x86_64-linux-gnu/libXrender.so.1 (0x00007f17f622d000)
    libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007f17f600f000)
    /lib/ld64.so.1 => /lib64/ld-linux-x86-64.so.2 (0x00007f17f8576000)
    libthai.so.0 => /lib/x86_64-linux-gnu/libthai.so.0 (0x00007f17f6004000)
    libfribidi.so.0 => /lib/x86_64-linux-gnu/libfribidi.so.0 (0x00007f17f5fe7000)
    libffi.so.6 => /lib/x86_64-linux-gnu/libffi.so.6 (0x00007f17f5fdd000)
    libpcre.so.3 => /lib/x86_64-linux-gnu/libpcre.so.3 (0x00007f17f5f67000)
    libdbus-1.so.3 => /lib/x86_64-linux-gnu/libdbus-1.so.3 (0x00007f17f5f14000)
    libatspi.so.0 => /lib/x86_64-linux-gnu/libatspi.so.0 (0x00007f17f5ee0000)
    libmount.so.1 => /lib/x86_64-linux-gnu/libmount.so.1 (0x00007f17f5e81000)
    libselinux.so.1 => /lib/x86_64-linux-gnu/libselinux.so.1 (0x00007f17f5c59000)
    libresolv.so.2 => /lib/x86_64-linux-gnu/libresolv.so.2 (0x00007f17f5c3d000)
    libgraphite2.so.3 => /lib/x86_64-linux-gnu/libgraphite2.so.3 (0x00007f17f5c10000)
    libexpat.so.1 => /lib/x86_64-linux-gnu/libexpat.so.1 (0x00007f17f5bd3000)
    libuuid.so.1 => /lib/x86_64-linux-gnu/libuuid.so.1 (0x00007f17f5bca000)
    libXau.so.6 => /lib/x86_64-linux-gnu/libXau.so.6 (0x00007f17f59c6000)
    libXdmcp.so.6 => /lib/x86_64-linux-gnu/libXdmcp.so.6 (0x00007f17f57be000)
    libdatrie.so.1 => /lib/x86_64-linux-gnu/libdatrie.so.1 (0x00007f17f57b4000)
    libsystemd.so.0 => /lib/x86_64-linux-gnu/libsystemd.so.0 (0x00007f17f5713000)
    libblkid.so.1 => /lib/x86_64-linux-gnu/libblkid.so.1 (0x00007f17f56be000)
    libbsd.so.0 => /lib/x86_64-linux-gnu/libbsd.so.0 (0x00007f17f56a4000)
    liblzma.so.5 => /lib/x86_64-linux-gnu/liblzma.so.5 (0x00007f17f567a000)
    liblz4.so.1 => /lib/x86_64-linux-gnu/liblz4.so.1 (0x00007f17f565b000)
    libgcrypt.so.20 => /lib/x86_64-linux-gnu/libgcrypt.so.20 (0x00007f17f553d000)
    libgpg-error.so.0 => /lib/x86_64-linux-gnu/libgpg-error.so.0 (0x00007f17f551a000)

如果有人能告诉我为了 运行 这个程序我在这里缺少什么我会很高兴。我想单独使用ld


按照建议,我添加了 strace:

的输出
ziga@ziga-laptop:2020-03-26--example-a$ strace ./static.elf 
execve("./static.elf", ["./static.elf"], 0x7ffcb3bec860 /* 31 vars */) = -1 ENOENT (No such file or directory)
strace: exec: No such file or directory
+++ exited with 1 +++

readelf

ziga@ziga-laptop:2020-03-26--example-a$ readelf -a static.elf | grep interpreter
      [Requesting program interpreter: /lib/ld64.so.1]

解决方案 - 但不是我想要的

静态 linking 的工作 makefile 部分是这个:

gcc main.c -o static.elf -Wl,-Bstatic -liup -Wl,-Bdynamic \
    -lc \
    -lgtk-3 \
    -lgdk-3 \
    -lpangocairo-1.0 \
    -lX11 \
    -lcairo \
    -lgdk_pixbuf-2.0 \
    -lm \
    -lpango-1.0 \
    -lgobject-2.0 \
    -lglib-2.0 \
    -lpthread

但它不使用 ld 我想知道为什么 ld 无法 link...

使用 gcc 到 link 并使用 -Wl,-Bstatic 告诉 linker 更喜欢 linking 静态库而不是共享库。示例:

gcc main.c -o static.elf -Wl,-Bstatic -lgtk-3 -lgdk-3 ...

您还可以通过使用 -Wl,-Bdynamic:

选择性地 link 仅针对某些静态库
gcc main.c -o static.elf -Wl,-Bstatic -lgtk-3 -lgdk-3 -Wl,-Bdynamic -lX11 ...

这将 link 针对 X11 共享库,但 link gtk 和 gdk 是静态的。您可以随时在 -Wl,-Bstatic-Wl,-Bdynamic 之间切换。

最后,请注意,如果库仅提供 .a 文件而没有 .so,那么您实际上不需要使用 -Wl,-Bstatic。 linker 将自动静态 link .a 文件,因为它是唯一的选择。