-->

Linking a C library and its supporting library in

2019-01-28 10:28发布

问题:

I want to use GNU scientific library in Swift, particularly I want to use routines from gsl_rng.h. So I basically follow https://github.com/apple/swift-package-manager/blob/master/Documentation/SystemModules.md (I am using Linux, not OS X)

I create the module as

module CGSL [system] {
  header "/usr/include/gsl/gsl_rng.h"
  link "gsl"
  export *
}

However, I can't build my program, since I get lots of messages of the kind undefined reference to 'cblas_dasum'. And indeed, as the documentation for GSL states

To link against the library you need to specify both the main library and a supporting CBLAS library, which provides standard basic linear algebra subroutines. A suitable CBLAS implementation is provided in the library libgslcblas.a if your system does not provide one. The following example shows how to link an application with the library,

$ gcc -L/usr/local/lib example.o -lgsl -lgslcblas -lm

What shall I do to link both -lgsl and -lgslcblas?

回答1:

Adding a second link line for libgslcblas will do the trick:

module CGSL [system] {
  header "/usr/include/gsl/gsl_rng.h"
  link "gsl"
  link "gslcblas"
  export *
}

You may also need to add link "m", even though I didn't have to do that on my box (Ubuntu 14.04).

I did not find a specific advice on this in Swift documentation and had to make an educated guess, but it worked. Swift on Linux is work in progress and the Package Manager is only available with Swift 3.0 development snapshots, Swift 3.0 being an unstable, actively developed latest version of the language. The very fact that such a common scenario is not well documented should give you an idea of the technology's maturity.

As an alternative to the Package Manager you might want to consider using a bridging header as described in an answer to this question: Compile C code and expose it to Swift under Linux.

Whichever way you do it, a bigger challenge will be calling the GSL API from Swift because the API uses a lot of non-primitive types. To work around that problem consider writing a C wrapper with a simplified interface that can be easily called from Swift. The wrapper can then be called by using a bridging header or system modules.



标签: linux swift gsl