macos - 在 OSX 中链接到带有 $ld$hide$os10.X$ 符号的库

标签 macos linker

我正在尝试链接 OSX 中的 BLAS 实现(/System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBLAS.dylib,出于好奇)但我不想链接到同一目录中的 libLAPACK.dylib,因为我想使用我自己构建的来自 netlib 的 LAPACK,因为它是最近的并且是最新的。

我的问题是 BLAS 库中有一些符号通常存储在 LAPACK 库中,因此会导致名称冲突。举个具体的例子,spotrf函数定义在libBLAS.dylib中:

$ nm /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBLAS.dylib | grep spotrf
0000000000010c05 T $ld$hide$os10.7$_spotrf
0000000000010c05 T $ld$hide$os10.8$_spotrf
000000000000746e T _spotrf

前两个符号让我有点怀疑,所以为了仔细检查,我也检查了 libLAPACK.dylib:

$ nm /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libLAPACK.dylib | grep spotrf
00000000000010c8 T $ld$hide$os10.4$_spotrf
00000000000010c8 T $ld$hide$os10.5$_spotrf
00000000000010c8 T $ld$hide$os10.6$_spotrf
000000000000765b T _spotrf

从什么limited information我已经能够找到,如果用户正在针对给定的 OSX 版本进行编译,那么这个前缀似乎以某种方式指示动态链接器忽略这些符号。如果 Apple 在 10.6 和 10.7 之间将符号从 libBLAS.dylib 移动到 libLAPACK.dylib,这是有道理的。

我的问题是,我如何通知动态链接器它应该隐藏 libBLAS.dylib 中的 spotrf 等?

最佳答案

首先,您实际上不需要做任何特殊的事情来获得您想要的行为,因为您是动态链接的。确保您的 netlib 构建的 LAPACK 出现在链接命令中的 -lblas 之前,并且所有 LAPACK 接口(interface)都将从 netlib LAPACK 中获取(ld 匹配所有 undefined symbol 它可以针对每个库按顺序链接)。

或者,假设您的 netlib LAPACK 链接到系统 BLAS,您应该能够配置 LAPACK 的链接,以便它重新导出所有 BLAS 符号。然后,您可以简单地链接到您的 LAPACK,并将 -lblas 完全排除在您的链接命令之外。


当且仅当您链接系统 BLAS 和系统 LAPACK 库时,$show$$hide$ 符号才会起作用。一个简单的例子将展示它们在这种情况下是如何工作的:

Kronecker:~ scanon$ cat foo.c
void dgetrf_(void);
int main(void) { dgetrf_(); return 0; }

在 10.9 上构建它并在 dgetrf_ 上中断,我们看到该符号是从 libLAPACK.dylib 中提取的,即使 -lblas首先出现在构建命令中。这是因为当目标为 10.9 时,该符号隐藏libBLAS.dylib 中:

Kronecker:~ scanon$ clang foo.c -lblas -llapack
Kronecker:~ scanon$ lldb a.out 
Current executable set to 'a.out' (x86_64).
(lldb) b dgetrf_
Breakpoint 1: 2 locations.
(lldb) run
...
frame #0: 0x00007fff89237b70 libLAPACK.dylib`dgetrf
libLAPACK.dylib`dgetrf:
...

如果我们指定 -mmacosx-version-min=10.6(告诉编译器和链接器我们想要生成可以在 10.6 Snow Leopard 上运行的可执行文件),我们将看到符号是改为从 libBLAS.dylib 获取。这是因为该符号不存在于 10.6 的 libLAPACK.dylib 中,因此如果 libLAPACK.dylib 中的符号,我们的可执行文件将无法在该平台上运行被使用:

Kronecker:~ scanon$ clang foo.c -lblas -llapack -mmacosx-version-min=10.6
Kronecker:~ scanon$ lldb a.out 
Current executable set to 'a.out' (x86_64).
(lldb) b dgetrf_
Breakpoint 1: 2 locations.
(lldb) run
...
frame #0: 0x00007fff8c9d6841 libBLAS.dylib`DGETRF_
libBLAS.dylib`DGETRF_:
...

关于macos - 在 OSX 中链接到带有 $ld$hide$os10.X$ 符号的库,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17180964/

相关文章:

macos - 有谁知道 OSX 将系统偏好设置 > 键盘 > 修饰键中的设置存储在哪里?

c# - 首次使用 Visual Studio 2017 for Mac 时出现“System.web.HttpException 找不到资源”错误

c++ - 使用带有 mingw-w64 的 Allegro 5 的未定义引用

c++ - 链接器命令失败,退出代码为 1 - Xcode

macos - 如何在 macOS 上完全卸载(重新安装)fabric8?

macos - Mac OS X/RSS低吼通知

c++ - qt命令行应用程序编译

c++ - C++98 中的自定义 dynamic_pointer_cast 实现

c - 无法链接 MongoDB C 驱动程序?

c++ - 模板方法的 undefined reference 错误