链接错误:GCC中libm.a的选择性静态链接

链接错误:GCC中libm.a的选择性静态链接,c,linux,gcc,compilation,static-linking,C,Linux,Gcc,Compilation,Static Linking,我想有选择地静态链接libm.a,动态链接所有其他库(libc.so)。但是如果我使用math.h中的数学函数,它几乎总是无法正确链接。为什么? 为什么它有时会起作用?(例如,如果我只使用sqrt,fabs或奇怪的是,tanh,它似乎链接正确) myscript.sh: #!/bin/bash for i in sqrt tanh sin tan do echo "-----$i----------" sed "s/ciao/$i/" prova.c >provat

我想有选择地静态链接
libm.a
,动态链接所有其他库(
libc.so
)。但是如果我使用
math.h
中的数学函数,它几乎总是无法正确链接。为什么? 为什么它有时会起作用?(例如,如果我只使用
sqrt
fabs
或奇怪的是,
tanh
,它似乎链接正确)

myscript.sh:

#!/bin/bash
for i in sqrt tanh sin tan  
do
     echo "-----$i----------"
     sed "s/ciao/$i/" prova.c >provat.c
     gcc provat.c -fno-builtin -l:libm.a
     [[ $? -eq 0 ]] && { echo -n "$i(2.0)="; ./a.out; echo " OK!"; }
         echo
done
prova.c:

#include <stdio.h>
#include <math.h>
int main()
{
    printf("%f", ciao(2.0));
    return 0;
}
我不明白这些错误信息。有人能解释一下发生了什么吗? 为什么我不能静态链接
libm.a
(其余的则是动态链接)?为什么它有时会起作用

注意:我使用GCC的
-fno builtin
标志,以便GCC不使用任何内置函数。所以问题不在那里。

我不太清楚为什么需要限制(libm.a+libc.So),所以闻起来像是XY问题

根据(由@KamilCuk指出):

这是不受支持的

您可能会将静态libm.a与未来的libc.so.6和ld.so混合在一起,从而打破了核心库之间的相互依赖关系,这些核心库构成了“C运行时的实现”

运行时的整个实现都是静态链接的,或者没有一个是静态链接的。您不能选择静态链接部分,而不是其他部分,因为每个部分都依赖于其他部分来形成完整的实现。数学库不是一个可以静态链接的瘦库,我们有一个libm.a,但这是一个实现细节

请对整个应用程序使用“-static”

这似乎是一个不受支持的配置。这是有道理的,但也有点混淆:即使libc和libm是磁盘上的两个独立文件(对于每个配置:静态、共享),它们也是同一个库的一部分(glibc),因此:

  • 使用静态构建的库的一半,另一半作为共享对象是不合适的(我想到的一些事情是:gcc的-fPIC标志,以及库的初始化)
  • 当然,大多数情况下,库由单个文件组成,因此上面的项目符号不适用(这就是混淆的原因)
从一开始,我就怀疑是一些代码(检测并)使用(如果存在)一些CPU功能(最有可能提高速度或准确性),即:

  • 仅用于某些(三角)函数(如sin、cos,但nottanh)-我只是在这里猜测:基于函数值的计算方式(例如泰勒级数)
  • 它只在libc(libm)同步时发生
我用了这个简单的程序

主要条款c:

#包括
#包括
#如果!已定义(FUNC)
#定义FUNC sqrt
#恩迪夫
int main(){
双val=3.141592;
printf(“func(%.06lf):%.06lf\n”,val,func(val));
返回0;
}
下面是我在研究问题时遵循的一系列步骤:

  • 环境:

    [cfati@cfati-ubtu16x64-0:~/Work/Dev/StackOverflow/q056415996]>~/sopr.sh
    ***设置较短的提示,以便粘贴到StackOverflow(或其他)页面时更适合***
    [提示]>联阿援助团-a
    Linux cfati-ubtu16x64-0 4.15.0-51-generic#55~16.04.1-Ubuntu SMP-Thu May 16 09:24:37 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux
    [提示]>gcc--版本
    gcc(Ubuntu 5.4.0-6ubuntu1~16.04.11)5.4.0 20160609
    版权所有(C)2015免费软件基金会。
    这是自由软件;有关复制条件,请参见源。没有
    担保甚至不是为了适销性或适合某一特定目的。
    [提示]>ldd--版本
    ldd(UbuntuGlibc2.23-0ubuntu11)2.23
    版权所有(C)2016免费软件基金会。
    这是自由软件;有关复制条件,请参见源。没有
    担保甚至不是为了适销性或适合某一特定目的。
    由罗兰·麦格拉斯和乌尔里希·德雷珀撰写。
    [提示]>ls
    main.c
    
  • 两个库部件(libc和libm)同步时的情况:

    [prompt]>gcc-fPIC main.c-DFUNC=sin-o sin_static.out-static-lm
    [提示]>ll sinu static.out
    -RWXR-x 1 cfati cfati 1007744 Jun 13 20:08 sin_static.out
    [提示]>ldd sin_static.out
    不是动态可执行文件
    [提示]>。/sin\u static.out
    func(3.141592):0.000001
    [提示]>
    [prompt]>gcc-fPIC main.c-DFUNC=sin-o sin_mso.out-l:libm.so
    [提示]>ll sin_mso.out
    -RWXR-x 1 cfati cfati 8656 Jun 13 20:09 sin_mso.out
    [提示]>ldd sin_mso.out
    linux vdso.so.1=>(0x00007ffc80ddd000)
    libm.so.6=>/lib/x86_64-linux-gnu/libm.so.6(0x00007f999636b000)
    libc.so.6=>/lib/x86_64-linux-gnu/libc.so.6(0x00007f9995fa1000)
    /lib64/ld-linux-x86-64.so.2(0x00007f9996674000)
    [提示]>。/sin\u mso.out
    func(3.141592):0.000001
    
    在这两种情况下,一切都很好

  • 切换到libm.a(用于sin和tanh):

    [prompt]>gcc-fPIC main.c-DFUNC=sin-o sin_ma.out-l:libm.a
    /usr/lib/gcc/x86_64-linux-gnu/5/./../../../x86_64-linux-gnu/libm.a(s_sin.o):在函数`\u cos'中:
    (.text+0x3542):未定义对“dl\U x86\U cpu\U功能”的引用
    /usr/lib/gcc/x86_64-linux-gnu/5/./../../../x86_64-linux-gnu/libm.a(s_sin.o):在函数`_sin'中:
    (.text+0x3572):对“dl\U x86\U cpu\U功能”的未定义引用
    collect2:错误:ld返回了1个退出状态
    [提示]>ll sin_ma.out
    ls:无法访问“sin_ma.out”:没有这样的文件或目录
    [提示]>
    [prompt]>gcc-fPIC main.c-DFUNC=tanh-o tanh_ma.out-l:libm.a
    [提示]>我要出去了
    -RWXR-x 1 cfati cfati 12856 Jun 13 20:10 tanh_ma.out
    [提示]>ldd tanh_ma.out
    linux vdso.so.1=>(0x00007ffcfa531000)
    libc.so.6=>/lib/x86_64-linux-gnu/libc.so.6(0x00007f124625c000)
    /lib64/ld-linux-x86-64.so.2(0x00007f1246626000)
    [提示]>。/谭胡妈
    func(3.141592):0.996272
    
    如图所示:

      $./myscript.sh -----sqrt---------- sqrt(2.0)=1.414214 OK! -----tanh---------- tanh(2.0)=0.964028 OK! -----sin---------- /usr/lib/x86_64-linux-gnu/libm-2.27.a(s_sin.o): In function `__sin_ifunc': (.text+0x4d42): undefined reference to `_dl_x86_cpu_features' /usr/lib/x86_64-linux-gnu/libm-2.27.a(s_sin.o): In function `__cos_ifunc': (.text+0x4da2): undefined reference to `_dl_x86_cpu_features' collect2: error: ld returned 1 exit status -----tan---------- /usr/lib/x86_64-linux-gnu/libm-2.27.a(s_tan.o): In function `__tan_ifunc': (.text+0x5782): undefined reference to `_dl_x86_cpu_features' collect2: error: ld returned 1 exit status