Does pkg-config get used? Struggling to wrap a system library, "import libtiff no such module"

I'm trying to wrap libtiff (my reposo I can call it from my Swift code. I've done this successfully before with a different library (libmodbus), but in that case, the header and library files were in /usr/local/include/modbus, but in this case, they're in /opt/homebrew/Cellar/libtiff/4.6.0/include/.

I thought pkg-config was supposed to take care of that. On my system it returns:

% pkg-config --cflags --libs libtiff-4
-I/opt/homebrew/Cellar/libtiff/4.6.0/include -I/opt/homebrew/opt/zstd/include -I/opt/homebrew/Cellar/xz/5.4.6/include -I/opt/homebrew/Cellar/jpeg-turbo/3.0.3/include -L/opt/homebrew/Cellar/libtiff/4.6.0/lib -ltiff

Note that it needs to have libtiff-4 specified. I do that in my Pacakge.swift:

.systemLibrary(name: "libtiff", pkgConfig: "libtiff-4", providers: [.brew(["libtiff"]), .apt(["libtiff-dev"])]),

But when I try to import libtiff in the package’s SwiftTIFF.swift file, it says it can't be found.

One really odd thing I notice. If I import libmodbus instead, something it should know nothing about, it says "could not build Objective-C module 'libmodbus'".

Moreover if I introduce an error in the system library module by attempting to include <tiff1.h>, which does not exist, I get an error, but only if I’m attempting to import libmodbus. If I attempt to import libtiff, it does not fail on the tiff1.h include, and just says "no such module 'libtiff'". If I fix the header include but leave import libmodbus, it builds without error, so long as I don't try to import libtiff. WTF.

This behavior is true for Xcode 16b2, and for swift build on the command line.

This is astonishingly frustrating. There’s not enough information to really understand why it’s failing, and the symptoms make no sense.

What does your module map for libtiff look like? Is it literally named module.modulemap? (It should be.)

I'm so sorry, I thought I had included a link to my repo so people could see exactly what I have.

% tree
.
β”œβ”€β”€ Package.swift
β”œβ”€β”€ Sources
β”‚   β”œβ”€β”€ SwiftTIFF
β”‚   β”‚   └── SwiftTIFF.swift
β”‚   └── libtiff
β”‚       β”œβ”€β”€ libtiff.h
β”‚       └── module.modulemap
└── Tests
    └── SwiftTIFFTests
        └── SwiftTIFFTests.swift

(I’ve updated the original post to include the link.)

1 Like

I have some bad but also good news for you:

2 Likes

Haaaahahahaha I'm laughing as I die of embarrassment.

That was the problem. Sigh.

I wish Swift would've said something like "libtiff not found, did you mean libmodbus?"

1 Like

Yeah, there are still reasonable takeaways here:

  • Is a systemLibrary target allowed to have a module map that does not declare the same name? (Module maps can declare multiple top-level modules, even though they usually don't.)

  • If a dependency is declared, could compiling the dependent target know that the module ("libtiff" in this case) was expected? I'm not sure what it would do with this information.

  • I'm not sure how to do the specific thing you suggest, that would require passing down information about which target provides which module names. But maybe it would be possible, along with the other explicit module work.

2 Likes

At the very least, a warning like "no module libtiff defined in libtiff/module.modulemap. Defined modules: libmodbus[, …]"

1 Like