[Solved] Issues integrating a C-based library with nested header files

I’m running into a problem integrating a C-based library with our project using Tuist.

Right now, the library is included in our project as a Swift Package, and it works as expected. When using Tuist though, I’m getting some errors related to importing headers. The problem seems to revolve around the headers being contained within a subdirectory.

Here’s the package’s current structure:

CoolLibrary/
├── Package.swift
└── Sources/
    └── CoolLibrary/
        ├── include/
        │   └── coollib/
        │       └── <a bunch of '.h' header files>
        └── library/
            └── <a bunch of '.c' code files and '.h' header files>

The problem is that with this current structure, the build fails because it the code within the library directory can’t seem to find the headers in the coollib directory. The headers are imported like this:

#include "coollib/important_header.h"

If I remove the coollib/ part from the import, things work as expected, so it seems to be not correctly finding things in that subdirectory.

Does anyone have advice on how to resolve this?

P.S. I’d prefer to find a solution that does not include modifying the directory structure, but if that’s the only way, then I can make that work if necessary.

1 Like

Oh, and here is how I’m currently trying to build the library out in the Tuist manifests:

.target(
    name: "CoolLibrary",
    destinations: .iOS,
    product: .staticLibrary,
    bundleId: "com.example.CoolLibrary",
    sources: "Packages/CoolLibrary/Sources/CoolLibrary/**/*.c",
    headers: .headers(
        public: "Packages/CoolLibrary/Sources/CoolLibrary/include/coollib/*.h",
        project: "Packages/CoolLibrary/Sources/CoolLibrary/library/*.h"
    )
)

Hey @hisaac :wave:

What if you add the following build setting:

HEADER_SEARCH_PATHS: ["$SRCROOT/Packages/CoolLibrary/Sources/CoolLibrary/include"]

If you only add the C header files, you can’t import the header files with the coollib/ prefix, just without it, as you mentioned.

Bingo, that was it! Thanks for the tip @marekfort. :pray:

@marekfort, Any tips for how one would then import this C library into an Xcode target correctly in the Tuist manifests? The library now builds correctly, but whenever I try to import it into a Swift target, it says “No such module”. :thinking:

For a C library, you need to manually provide a modulemap (see here) which should be the missing piece. You will also need to instruct Swift where to find the modulemap file by adding -Xcc -fmodule-map-file $SRCROOT/path-to-your-modulemap. Alternatively, wrap the C library in a module and provide a MODULEMAP_FILE.

Other useful resource is our modulemap mapper where we translate MODULEMAP_FILE to compiler flags for downstream targets (which is something that would happen automatically in a pure SPM setup)

Fantastic, thank you! I’ll dig into this soon and see if I can get it sorted out.

I’ve got it all sorted now. Thank you once again :pray: