GCC链接libc的静态和其他一些动态库,重新审视? [英] GCC linking libc static and some other library dynamically, revisited?

查看:2910
本文介绍了GCC链接libc的静态和其他一些动态库,重新审视?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

下面的问题是相关但不回答我的问题:

The following questions are relevant but do not answer my question:

<一个href=\"http://stackoverflow.com/questions/26161332/linking-partially-static-and-partially-dynamic-in-gcc\">Linking部分静态和GCC部分动态

<一个href=\"http://stackoverflow.com/questions/10432968/linking-a-dynamic-library-to-a-static-library-that-links-to-other-static-librari\">Linking动态库到静态库链接到其他静态库

GCC:静态链接只有一些库

<一个href=\"http://stackoverflow.com/questions/725472/static-link-of-shared-library-function-in-gcc\">Static在GCC 共享库函数的链接

我问了一个非常类似的问题较早,但由于由我开始了previous问题得到了在注释部分有点混乱,没有完全回答(但我标记它作为回答,因为这是一个很好的努力,至少做部分地回答)我会问一个新问题。现在的问题是具体是怎么联系起来的libc为静态的,而动态链接其它库(例如libm中)。这被认为不能在第一个问题来完成,这是真的?如果因此这将是非常有趣的,知道为什么。

I asked a very similar question earlier, but since the previous question started by me got somewhat cluttered in the comment section and not fully answered (but I flagged it as answered since it was a good effort and did at least partially answer it) I will ask a new question. The question is specifically how to link libc as static, while linking some other library (e.g. libm) dynamically. This was suggested that cannot be done in the first question, is that true? If so it would be very interesting to know why not.

它甚至有可能做到这一点?有人发表了意见(这是出于某种原因删除,也许这是不正确的?),这是可能的,但必须有那么的的存在libc中的动态链接的版本,因为它会被要求动态库(如动态的libm将需要动态的libc(?))。

Is it even possible to do this? Someone made a comment (which was removed for some reason, maybe it was incorrect?) that it is possible, but there must then also exist a dynamically linked version of libc, since it will be required by the dynamic library (e.g. dynamic libm will require dynamic libc (?)).

这是为我好,但并不明显,我怎么告诉GCC要做到这一点,即链接在libc中的静态和动态。我如何做到这一点(我做了几次尝试,有些是后来所示的问题)?或者是有一些其他的方式做我想做什么?

This is fine for me, but it is not obvious to me how to tell GCC to do this, i.e. link in libc as both static and dynamic. How do I do this (I made a couple attempts, some are shown later in the question)? Or is there some other way to do what I want?

我们首先看到,只需运行GCC test.c的-lm,一切都在动态链接如下:

We first see that by simply running gcc test.c -lm, everything is linked in dynamically, as follows:

$ gcc test.c -lm
$ ldd a.out 
        linux-vdso.so.1 (0x00007fffb37d1000)
        libm.so.6 => /lib64/libm.so.6 (0x00007f3b0eeb6000)
        libc.so.6 => /lib64/libc.so.6 (0x00007f3b0eb10000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f3b0f1b0000)

要只链接的libm静态,同时允许libc中才能保持活力,我们可以做(为:Z玻色子在前面提到的问题之一指出):

To link only libm as static, while allowing libc to remain dynamic, we can do (as Z boson pointed out in one of the aforementioned questions):

$ gcc test.c /usr/lib/gcc/x86_64-pc-linux-gnu/4.7.3/../../../../lib64/libm.a

$ ldd a.out 
        linux-vdso.so.1 (0x00007fff747ff000)
        libc.so.6 => /lib64/libc.so.6 (0x00007f09aaa0c000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f09aadb2000)

但是,试图同样的程序链接libc的静态和动态的libm,似乎不工作:

However, attempting the same procedure to link libc static and libm dynamic, does not seem to work:

$ gcc test.c /usr/lib/gcc/x86_64-pc-linux-gnu/4.7.3/../../../../lib64/libc.a -lm
/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

这是什么错误讯息?

What does this error message mean?

其他的一些尝试(大多数也包括在我的第一个问题):

Some other attempts (most were also included in my first question):

$ 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
$ gcc test.c /usr/lib/gcc/x86_64-pc-linux-gnu/4.7.3/../../../../lib64/libc.a /usr/lib/gcc/x86_64-pc-linux-gnu/4.7.3/../../../../lib64/libc.so -lm
/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
$ gcc test.c /usr/lib/gcc/x86_64-pc-linux-gnu/4.7.3/../../../../lib64/libc.so /usr/lib/gcc/x86_64-pc-linux-gnu/4.7.3/../../../../lib64/libc.a -lm

需要注意的是最后一个编译/链接成功。然而libc中尚未在静态链接,仅动态,因此,它是一个失败的尝试。

Note that the last one compiled/linked successfully. However libc has not been linked in statically, only dynamically, so it is another failed attempt.

测试程序仅仅是以下内容:

The test program is simply the following:

$ cat test.c 
#include <stdio.h>
#include <math.h>

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

        for(i = 0; i < 65535; i++) {
                result = sin(i);
        }

        return 0;
}

编辑:

我也试过statifier和貂皮,在这个问题建议:

I've also tried statifier and ermine, as suggested in this question:

<一个href=\"http://stackoverflow.com/questions/725472/static-link-of-shared-library-function-in-gcc\">Static在GCC 共享库函数的链接

无论是作品。

推荐答案

基本上,你的第一种方法是做到这一点的正确方式:

Basically, your first approach is the correct way to do this:

gcc test.c libc.a -lm

GCC增加了隐性库

在它会看起来(概念上)这样的:

After gcc adds the implicit libraries it'll look (conceptually) like this:

gcc crt1.o test.c libc.a -lm -lc -lgcc -lc

因此​​,这意味着任何libc函数由两种 crt1.o test.c以将在所谓的拉从的libc.a 和链接的静态的,而所谓​​的完全的从的libm 的任何功能或 libgcc中将动态链接(但它会重用静态函数,如果调用的libm已经拉的东西)。

So that means that any libc functions called by either crt1.o or test.c will be pulled in from libc.a and linked statically, whereas any functions called solely from libm or libgcc will be linked dynamically (but it will reuse the static functions if libm calls something already pulled in).

链接器总是从最左边的文件/库和作品向右;它永远不会蜗居。 .C 的.o 文件是在无条件地联系在一起,但 .A 文件和 -l <​​/ code>选项仅用于查找已引用但尚未定义的功能。因此,在左侧库是没有意义的(和 -lc 必须出现两次,因为 -lc 取决于 -lgcc -lgcc 取决于 -lc )。的链接顺序很重要!

The linker always starts at the left-most file/library, and works rightwards; it never goes back. .c and .o files are linked in unconditionally, but .a files and -l options are only used to find functions that are already referenced but not yet defined. Therefore, a library at the left is pointless (and -lc must appear twice because -lc depends on -lgcc, and -lgcc depends on -lc). Link order is important!

不幸的是,你似乎已经被什么可能是在 STRCMP (或者更确切地说,在包含的libc STRCMP )的 STT_GNU_IFUNC 的事情是一个聪明的功能,它允许包括一个函数的多个版本,并且最优化的一个在运行时选择的基础上,哪些硬件是可用的。我不知道,但是看起来这个功能仅在PIE(位置独立的可执行文件)或共享库的构建提供。

Unfortunately, you appear to have been foiled by what might be a bug in strcmp (or rather in the libc that contains strcmp): the STT_GNU_IFUNC thing is a clever feature that allows multiple versions of a function to be included, and the most optimal one to be selected at runtime, based on what hardware is available. I'm not sure, but it looks like this feature is only available in a PIE (Position Independent Executable) or shared library build.

为什么这将是一个静态的libc.a 是一个谜给我,但有一个简单的解决方法:实现自己的 STRCMP (一个基本的,缓慢的实现是C的只有几行),并且在之前的链接它的libc.a

Why that would be in a static libc.a is a mystery to me, but there's an easy workaround: implement your own strcmp (a basic, slow implementation is only a few lines of C), and link it in before libc.a.

gcc test.c mystrcmp.c libc.a -lm


另外,你可以提取的libc.a ,你真正想要的功能,并链接只有那些在静态:


Alternatively, you can extract the functions from libc.a that you really want, and link only those in statically:

ar x libc.a
gcc test.c somefile.o -lm

AR .A 文件,焦油的.tar 文件,虽然命令用法变化了一点,所以这个例子从提取的.o 文件在 .A 文件,然后链接它们明确。

ar is to .a files, as tar is to .tar files, although the command usage varies a bit, so this example extracts the .o files from the .a file, and then links them explicitly.

这篇关于GCC链接libc的静态和其他一些动态库,重新审视?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆