我正在尝试链接 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/