Reputation: 7050
I'm trying to link against the BLAS implementation in OSX (/System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBLAS.dylib
, for the curious) but I don't want to link against the libLAPACK.dylib
in that same directory, as I want to use my own build of LAPACK from netlib, as it is much more recent and up to date.
My problem is that there are symbols in the BLAS library that are typically stored in an LAPACK library, and as such are causing name clashes. As a concrete example, the spotrf
function is defined in 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
Those first two symbols made me a little suspicious, so to double-check, I check out libLAPACK.dylib
as well:
$ 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
From what limited information I have been able to find, it seems that this prefix somehow instructs the dynamic linker to ignore these symbols if the users is compiling against a given OSX version. This makes sense if Apple moved symbols from libBLAS.dylib
to libLAPACK.dylib
between 10.6 and 10.7.
My question is, how can I inform the dynamic linker that it SHOULD hide spotrf
etc... that are inside libBLAS.dylib
?
Upvotes: 4
Views: 493
Reputation: 106267
First off, you don’t actually need to do anything special to get your desired behavior, as you’re linking dynamically. Ensure that your netlib-built LAPACK appears before -lblas in the link command, and all LAPACK interfaces will be picked up from the netlib LAPACK (ld
matches all the undefined symbols it can against each of the libraries being linked against in order).
Alternatively, assuming that your netlib LAPACK is linked against the system BLAS, you should be able to configure the link of LAPACK so that it reexports all of the BLAS symbols. Then you can simply link against your LAPACK and leave -lblas out of your link command entirely.
The $show$
and $hide$
symbols come into play if and only if you are linking against both the system BLAS and the system LAPACK libs. A simple example will show how they work in that case:
Kronecker:~ scanon$ cat foo.c
void dgetrf_(void);
int main(void) { dgetrf_(); return 0; }
Building this on 10.9 and breaking on dgetrf_
, we see that the symbol was picked up from libLAPACK.dylib
, even though -lblas
appears first in the build command. This is because the symbol is hidden in libBLAS.dylib
when targeting 10.9:
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:
...
If we specify -mmacosx-version-min=10.6
(telling the compiler and linker that we want to produce an executable that can run on 10.6 Snow Leopard), we will see that the symbol is picked up from libBLAS.dylib
instead. This is because the symbol doesn’t exist in libLAPACK.dylib
on 10.6, so our executable wouldn’t be able to run on that platform if the symbol in libLAPACK.dylib
were used:
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_:
...
Upvotes: 3