在GCC中链接部分静态和部分动态

时间:2014-10-02 12:56:25

标签: c gcc compilation static-linking

我正在尝试使用GCC的动态和静态链接编译一个非常简单(简单的hello world)C程序。我想知道如何一般地这样做,所以我的最小测试示例只是试图将libc动态地链接为静态和libm。

我至少遇到过关于同一主题的以下其他问题:

GCC: static linking only some libraries

Static link of shared library function in gcc

其中的一些答案提出了诸如使用-Wl,-Bstatic和-Wl,-Bdynamic来指定哪些库分别是静态和动态的。此外,还建议仅指定要链接的静态库的完整路径。

我已经尝试了其中一些建议及其变体。我不明白它给我的错误信息。我知道PIE是什么,但我不知道它与我想做的事情有什么关系。

以下是一些失败的尝试:

$ gcc test.c /usr/lib64/libc.a
linux-gnu/4.7.3/../../../../x86_64-pc-linux-gnu/bin/ld: dynamic STT_GNU_IFUNC symbol `strcmp' with pointer equality in `/usr/lib64/libc.a(strcmp.o)' can not be used when making an executable; recompile with -fPIE and relink with -pie
urned 1 exit status
$ gcc test.c -Wl,-Bdynamic -lm -Wl,-Bstatic -lc
/usr/lib/gcc/x86_64-pc-linux-gnu/4.7.3/../../../../x86_64-pc-linux-gnu/bin/ld: cannot find -lgcc_s
/usr/lib/gcc/x86_64-pc-linux-gnu/4.7.3/../../../../x86_64-pc-linux-gnu/bin/ld: cannot find -lgcc_s
collect2: error: ld returned 1 exit status
$ gcc -Wl,-Bdynamic -lm -Wl,-Bstatic -lc test.c
/usr/lib/gcc/x86_64-pc-linux-gnu/4.7.3/../../../../x86_64-pc-linux-gnu/bin/ld: cannot find -lgcc_s
/usr/lib/gcc/x86_64-pc-linux-gnu/4.7.3/../../../../x86_64-pc-linux-gnu/bin/ld: cannot find -lgcc_s
collect2: error: ld returned 1 exit status
$ gcc -Wl,-Bstatic -lc -Wl,-Bdynamic -lm test.c
/usr/lib/gcc/x86_64-pc-linux-gnu/4.7.3/../../../../x86_64-pc-linux-gnu/bin/ld: dynamic STT_GNU_IFUNC symbol `strcmp' with pointer equality in `/usr/lib/gcc/x86_64-pc-linux-gnu/4.7.3/../../../../lib64/libc.a(strcmp.o)' can not be used when making an executable; recompile with -fPIE and relink with -pie
collect2: error: ld returned 1 exit status

只是没有参数编译,并且-static工作正常,但我需要部分静态编译:

$ gcc test.c -lm
$ gcc -static test.c -lm

但是,以下内容也失败了:

$ gcc test.c /usr/lib64/libc.a /usr/lib64/libm.a

我在这篇文章中遇到了类似的错误:

C++ Statically linked shared library

然而答案似乎不适用于我的问题。

我正在尝试编译的程序就是(作为test.c):

#include <stdio.h>
#include <math.h>

int main(int argc, char **argv)
{
    int i = 0;

    for(i = 0; i < 65535; i++) {
            printf("%f\n", sinf(i));
            printf("%f\n", cosf(i));
            printf("%f\n", tanf(i));
            printf("%f\n", sqrtf(i));
    }


    return 0;
}

编辑:请注意,程序必须足够复杂,实际上需要libm,否则如果不真正需要libm,链接尝试可能会产生误报。在我原来的test.c示例中,我只将sinf()用于常量值,这使得编译器完全优化了sinf()调用。

我正在使用:

$ gcc --version
gcc (Gentoo 4.7.3-r1 p1.4, pie-0.5.5) 4.7.3

1 个答案:

答案 0 :(得分:3)

以下为我工作

ln -s `gcc -print-file-name=libc.a`
gcc -static-libgcc -L. -lc test.c

然后ldd a.out给出:

not a dynamic executable

编辑:

OP希望动态链接一个库,静态链接另一个库。他举了一个动态链接libc静态和libm的示例。那个我无法实现的特殊情况。但是,相反的情况可能是动态链接libc和静态链接libm

ln -s `gcc -print-file-name=libm.a`
gcc test.c -L. -lm

然后ldd a.out给出

libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0x41960000)
/lib/ld-linux.so.2 (0x4193d000)

请注意,链接顺序事项..e gcc -L. -lm test.c不起作用。

这也适用于其他图书馆。例如gomp

gcc -fopenmp test.c

ldd显示libgomp.so.1。我们可以像这样静态链接它

ln -s `gcc -print-file-name=libgomp.a`
gcc -L. -fopenmp test.c

现在ldd a.out未显示libgomp.so.1。但在这种情况下,pthreads仍然是动态链接的。静态链接pthreads requires that libc be linked statically as well