3

我正在尝试链接 OSX 中的 BLAS 实现(/System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBLAS.dylib出于好奇),但我不想链接libLAPACK.dylib到同一个目录中的 BLAS 实现,因为我想使用来自 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

从我能找到的有限信息来看,如果用户针对给定的 OSX 版本进行编译,这个前缀似乎会以某种方式指示动态链接器忽略这些符号。libBLAS.dylib如果 Apple 将符号从 10.6移到libLAPACK.dylib10.7 之间,这是有道理的。

我的问题是,我怎样才能通知动态链接器它应该隐藏spotrf等等......在里面libBLAS.dylib

4

1 回答 1

2

首先,您实际上不需要做任何特别的事情来获得您想要的行为,因为您正在动态链接。确保您的 netlib 构建的 LAPACK 出现在链接命令中的 -lblas 之前,并且所有 LAPACK 接口都将从 netlib LAPACK 中提取(ld将所有未定义的符号与按顺序链接的每个库匹配)。

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


当且仅当您同时链接系统 BLAS 和系统 LAPACK 库时, $show$and$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_:
...
于 2013-11-05T16:28:54.830 回答