Cross Platform System Package That Doesn't Support pkg-config?

I am attempting to make a cross-platform macOS and Linux library that imports the HDF5 C library. HDF5 can be installed on macOS with brew hdf5 or on Ubuntu 18.04 with sudo apt install libhdf5-serial-dev. This installs files in these locations:

On macOS:

  • Library: /usr/local/lib/libhdf5.*
  • Header: /usr/local/include/hdf5.h
  • To build: swift build -Xlinker -L/usr/local/lib/

On Ubuntu:

  • Library: /usr/lib/x86_64-linux-gnu/hdf5/serial/libhdf5.*
  • Headher: /usr/include/hdf5/serial/hdf5.h
  • To build: swift build -Xlinker -L/usr/lib/x86_64-linux-gnu/hdf5/serial

HDF5 does not appear to support pkg-config and hence does not contain a .pc file.

Currently, this is my full module.modulemap:

module CHDF5 [system] {
    // Linux:
    // Lib is at /usr/lib/hdf5/serial/libhdf5.*
    // umbrella header "/usr/include/hdf5/serial/hdf5.h"
    // macOS:
    // Lib is at /usr/local/lib/libhdf5.*
    umbrella header "/usr/local/include/hdf5.h"
    link "hdf5"
    export *
}

To compile on one platform vs the other I have to uncomment the appropriate line.

I attempted to do the following in the module.modulemap:

#if os(Linux)
#else
#endif

But these lines were not recognized as valid tokens.

Is there no way to do a system module import on a library that doesn't have built-in pkg-config support that is cross-platform compatible?

Clone the full code to reproduce here.

All of the above is on Xcode 12's Swift 5.3 release.

The easiest way is to make your umbrella header local to your package and then #include <hdf5.h> in that header. That will achieve your desired outcome, as the C compiler will search the include paths on the system and find that header.

However, you’ll probably then run into SR-12909. I don’t know a good way to work around that at present.

1 Like

Excellent, that's what I was looking for, thanks @lukasa! You're right, the final hurdle to true cross-platform compatibility with a simple swift build is that the linker doesn't find the libraries. I still have to build with either swift build -Xlinker -L/usr/local/lib/ on macOS or swift build -Xlinker -L/usr/lib/x86_64-linux-gnu/hdf5/serial on Linux. Thanks for the link to the bug report.

One solution to this I hadn't thought of is in this article. In the .modulemap, specify two different modules: One for Mac and one for Linux. They have different header paths and the right one is important with an #if canImport.