- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我想有选择地静态链接 libm.a
,动态链接所有其他库(包括 libc.so
)。但是,如果我使用 math.h
中的数学函数,它几乎总是 无法正确链接。为什么?为什么它有时会起作用? (例如,如果我只使用 sqrt
、fabs
或者奇怪的是 tanh
,它似乎链接正确)
我的脚本.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;
}
如果我运行 myscript.sh
,我可以看到 sqrt
和 tanh
没有问题。 sin
和 tan
链接失败:
$./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
我不明白这些错误信息。有人可以解释发生了什么吗?为什么我不能静态链接 libm.a
(其余的是动态链接)?为什么它有时会起作用?
注意:我对 GCC 使用 -fno-builtin
标志,这样 GCC 就不会使用它的任何内置函数。所以问题不存在。
最佳答案
(对我而言)不是很清楚为什么限制 (libm.a + libc.so) 是必要的,所以它闻起来像一个 XY 问题.
根据 [RedHat.Bugzilla]: Bug 1433347 - glibc: Selective static linking of libm.a fails due to unresolved _dl_x86_cpu_features symbol (@KamilCuk 指出):
This is not supported.
You would be mixing a static libm.a with future libc.so.6 and ld.so and that breaks the interdependencies between the core libraries which form "the implemetnation of the C runtime."
Either the entire implementation of the runtime is statically linked or none of it is statically linked. You can't choose to link parts of it statically and not others because each part depends on the other to form a complete implementation. The math library is not a thin you can link against statically, it happens we have a libm.a, but that's an implementation detail.
Please use '-static' for the entire application.
这似乎是一个不受支持的配置。这是有道理的,但也有点令人困惑:即使 libc 和 libm 是磁盘上的 2 个独立文件(对于每个配置:< em>static, shared), 它们是同一个库的一部分 (glibc) ,所以:
从一开始,我就怀疑是某些代码(检测和)使用(如果存在)某些 CPU 功能(最有可能提高速度或准确性),即:
我使用了这个简单的程序。
main.c:
#include <stdio.h>
#include <math.h>
#if !defined(FUNC)
# define FUNC sqrt
#endif
int main() {
double val = 3.141592;
printf("func(%.06lf): %.06lf\n", val, FUNC(val));
return 0;
}
下面是我在调查问题时遵循的一系列步骤:
环境:
[cfati@cfati-ubtu16x64-0:~/Work/Dev/StackOverflow/q056415996]> ~/sopr.sh
*** Set shorter prompt to better fit when pasted in StackOverflow (or other) pages ***
[prompt]> uname -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
[prompt]> gcc --version
gcc (Ubuntu 5.4.0-6ubuntu1~16.04.11) 5.4.0 20160609
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
[prompt]> ldd --version
ldd (Ubuntu GLIBC 2.23-0ubuntu11) 2.23
Copyright (C) 2016 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Written by Roland McGrath and Ulrich Drepper.
[prompt]> ls
main.c
2 个库部分(libc 和 libm)同步的情况:
[prompt]> gcc -fPIC main.c -DFUNC=sin -o sin_static.out -static -lm
[prompt]> ll sin_static.out
-rwxrwxr-x 1 cfati cfati 1007744 Jun 13 20:08 sin_static.out
[prompt]> ldd sin_static.out
not a dynamic executable
[prompt]> ./sin_static.out
func(3.141592): 0.000001
[prompt]>
[prompt]> gcc -fPIC main.c -DFUNC=sin -o sin_mso.out -l:libm.so
[prompt]> ll sin_mso.out
-rwxrwxr-x 1 cfati cfati 8656 Jun 13 20:09 sin_mso.out
[prompt]> 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)
[prompt]> ./sin_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): In function `__cos':
(.text+0x3542): undefined reference to `_dl_x86_cpu_features'
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/libm.a(s_sin.o): In function `__sin':
(.text+0x3572): undefined reference to `_dl_x86_cpu_features'
collect2: error: ld returned 1 exit status
[prompt]> ll sin_ma.out
ls: cannot access 'sin_ma.out': No such file or directory
[prompt]>
[prompt]> gcc -fPIC main.c -DFUNC=tanh -o tanh_ma.out -l:libm.a
[prompt]> ll tanh_ma.out
-rwxrwxr-x 1 cfati cfati 12856 Jun 13 20:10 tanh_ma.out
[prompt]> 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)
[prompt]> ./tanh_ma.out
func(3.141592): 0.996272
如所见:
从现在开始,我将专注于不起作用的情况。
尝试一下链接器标志 (man ld
( [die.linux]: ld(1) - Linux man page )):
[prompt]> gcc -fPIC main.c -DFUNC=sin -o sin_ma_undefined.out -l:libm.a -Wl,--warn-unresolved-symbols
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/libm.a(s_sin.o): In function `__cos':
(.text+0x3542): warning: undefined reference to `_dl_x86_cpu_features'
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/libm.a(s_sin.o): In function `__sin':
(.text+0x3572): warning: undefined reference to `_dl_x86_cpu_features'
[prompt]> ll sin_ma_undefined.out
-rwxrwxr-x 1 cfati cfati 104088 Jun 13 20:10 sin_ma_undefined.out
[prompt]> ldd sin_ma_undefined.out
linux-vdso.so.1 => (0x00007fff984b0000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f274ad00000)
/lib64/ld-linux-x86-64.so.2 (0x00007f274b0ca000)
[prompt]> ./sin_ma_undefined.out
Segmentation fault (core dumped)
它通过了链接阶段,但在运行时出现了段错误(这是意料之中的)。
遇到 [Amper.Git]: open-source/glibc - Add _dl_x86_cpu_features to rtld_global (注意没有在官方 glibc: [GNU]: Index of /gnu/libc 中)。那里有一些很重的东西。我“借”了一些并保存了它。
_dl_x86_cpu_features.c:
#if defined(_DL_X86_CPU_FEATURES__WORKAROUND)
# define FEATURE_INDEX_MAX 1
enum {
COMMON_CPUID_INDEX_1 = 0,
COMMON_CPUID_INDEX_7,
COMMON_CPUID_INDEX_80000001, // for AMD
// Keep the following line at the end.
COMMON_CPUID_INDEX_MAX
};
struct cpu_features {
enum cpu_features_kind {
arch_kind_unknown = 0,
arch_kind_intel,
arch_kind_amd,
arch_kind_other
} kind;
int max_cpuid;
struct cpuid_registers {
unsigned int eax;
unsigned int ebx;
unsigned int ecx;
unsigned int edx;
} cpuid[COMMON_CPUID_INDEX_MAX];
unsigned int family;
unsigned int model;
unsigned int feature[FEATURE_INDEX_MAX];
};
struct cpu_features _dl_x86_cpu_features;
#endif
#include "_dl_x86_cpu_features.c"
也需要在 main.c 中添加:
[prompt]> gcc -fPIC main.c -DFUNC=sin -D_DL_X86_CPU_FEATURES__WORKAROUND -o sin_ma_workaround.out -l:libm.a
[prompt]> ll sin_ma_workaround.out
-rwxrwxr-x 1 cfati cfati 104088 Jun 13 20:13 sin_ma_workaround.out
[prompt]> ldd sin_ma_workaround.out
linux-vdso.so.1 => (0x00007fff17b6c000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f5a992e5000)
/lib64/ld-linux-x86-64.so.2 (0x00007f5a996af000)
[prompt]> ./sin_ma_workaround.out
func(3.141592): 0.000001
显然,有效(至少在我的环境中)!!!
尽管它对我有用(并且可能对您的情况也是如此),但我仍然认为它是一种解决方法 (gainarie),并且我不知道全部含义。
因此,我的建议是采用推荐的选项(来自步骤#2.)(其中之一)。
但是,看看其他编译器的行为会很有趣。
关于c - GCC 中的链接错误 : selective static linking of libm. a,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56415996/
有没有人试图用glibc编译-march=corei7来查看与默认的Linux x68_64发行版相比是否有性能改进? GCC使用-march=i686编译。我认为(不确定)数学库也是以相同的方式编译
当我尝试编译我的应用程序时,出现以下错误: *** No rule to make target `/mypath/lib/libm.a', needed by `/myPath/bin/appNam
这个问题已经有答案了: 已关闭12 年前。 Possible Duplicate: Why do you have to link the math library in C? 当我编写一个使用 ma
我试图编译一个包含 的源文件.但是我成功地创建了一个可执行文件,没有链接到 libm.a 没有错误. 我输入的命令是 gcc -Wall filename.c -o executablename 我
据我所知,一些数学函数包含在 libc 中,而另一些则包含在 libm 中。我通过实验发现: $ nm --dynamic --defined-only /lib/x86_64-linux-gnu/l
按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the
查看libm中日志操作的实现,有一些数字文字我理解有问题。 从here下载代码 部分代码如下所示。我想知道0x95f64、0x6147a和0x6b851的含义。 if (hx >= 0x7ff0000
我正在编译以下代码: #include #include main() { int x=2, y=3; pow(2,3); pow(x,y); } 如果我将其编译为“gcc
我有一个调用 sin、cos 和 acos 的 c 程序。编译时出现以下错误: /tmp/ccDfW98S.o: In function `zip_search': main.c:(.text+0xf
是否有针对 ARM(v6) 处理器优化的 libm (libmath)? 我正在查看 GNU 实现,它似乎没有优化(但它确实有 x86 的)。似乎 libm 的大多数实现都没有针对 ARM 的优化。
我想编译一些非常基本的测试代码,调用日志函数,然后使用英特尔 C 编译器在 Linux 上的标准输出上打印结果。我希望代码链接到 libimf(英特尔的数学函数库)而不是 GNU libm,这样我就可
我只是想弄明白,为什么 Fedora 没有静态库 libm.a,如果这是事实,我应该使用?如前所述 here在 StackOverflow 中,我可以简单地从 yum 安装 pkg,但认为 Fedor
我想下载并编译 libm(GNU 的 may 库)的源代码。 有人可以指出我正确的位置/存储库吗? 最佳答案 它包含在 C 标准库中:Glibc 关于gnu - gnu lib math (libm)
我想稍微修改 libm 的 sin 函数(来源:s_sin.c)来尝试一些数值。但是,我不知道如何编译修改后的源代码。 我想避免执行“./configure, make”。因此,为了解决所有依赖关系,
我使用以下命令在 shell 中成功编译了我的程序。它生成示例二进制文件并正常工作。 gcc -g -o build/debug/example -Iinclude docs/example.c \
我有一台没有 sudo 权限的 centOS 机器。 我需要使用 librosa python 包,所以我安装了 Anaconda 并通过 conda 安装了该包。 但是,当我导入这个包时,我得到 I
linux下C程序中的.a文件是什么?是库文件吗? To merge with the math library libm.a you would type cc -o program_name p
我正在 pow 上测试极端情况调用( #include ),特别是 pow(-1, Inf) . 在我的桌面 (Ubuntu) 上,我得到结果 1.0,这符合 2008 IEEE 浮点规范。 我在运
我想有选择地静态链接 libm.a,动态链接所有其他库(包括 libc.so)。但是,如果我使用 math.h 中的数学函数,它几乎总是 无法正确链接。为什么?为什么它有时会起作用? (例如,如果我只
在 Android Studio 中使用 NDK Cmake 构建系统时,是否可以链接 platforms\android-XX\arch-arm\usr\lib*.a 版本的库?我正在使用 LLVM
我是一名优秀的程序员,十分优秀!