[SPM] PackageDescription 5.3 does not recognize .hpp headers as such and asks for them to be excluded or used as resources

Using SPM to wrap a Swift wrapper around a C wrapper around a C++ library is a hassle. SPM version 5.3 currently makes it even more of a hassle. My Package structure is the following:

Package/
    CXXTarget
        include/ -> *.hpp (with subfolders)
        src/ -> *.cpp
    CTarget
        include/ -> *.h
        src/ -> *.cpp
    SwiftTarget
        file.swift
        resource.txt

My Package manifest contains the following target:

...
.target(
            name: "CXXTarget",
            dependencies: [],
            cxxSettings: [
                .define("SOME_DEFINE"),
                .unsafeFlags(["-std=c++17", // because .cxx17 LanguageStandard is not yet available
                              "-I", "/usr/local/opt/boost/include"
                ])],
            linkerSettings: [
                .linkedLibrary("boost_system-mt"),
                .unsafeFlags(["-L/usr/local/opt/boost/lib"])]
        ),
...

In version 5.2, this compiled without a hitch (had no resources then), but now in version 5.3, SPM requires all files within targets to be explicitly handled (which is a good thing). It recognizes all .h, .cpp and .swift files but fails for all 200+ .hpp files, as if it didn't recognize them anymore. The manifest resolver asks for them to be explicitly handled.
I've tried declaring them with publicHeadersPath: but it still considered them unhandled.
My current workaround is to explicitly declare the sources in the C++ target using ... sources: ["include", "src"], ..., however now I have 200+ warnings that no rule to process file '/path/*.hpp' of type 'file' for architecture 'x86_64' when compiling. Although this compiles successfully, I would like to avoid the warning and declaring headers as "sources" seems semantically wrong.

In short: does SPM v5.3 (as shipped with Xcode 12.0b2) incorrectly recognize .hpp files or have I done something wrong?

4 Likes

Looks like we actually only consider .h as a header file:

We should extend that by other well-known C-family language header file extensions.

PR to fix this is now submitted for review: Support C++ headers in TargetSourcesBuilder.swift by MaxDesiatov · Pull Request #2814 · apple/swift-package-manager · GitHub

1 Like

So it was a bug! Glad I could help uncover it. While we're at it, two follow-up questions:

  1. What would be the correct "manual" implementation then? publicHeadersPath: or sources:?
  2. Nearly unrelated: I see that #2716 added support for newer C++ language standards (e.g. C++17) but hides them under the an availability condition. Is that planned for 5.3?
  1. I don't think either of this will work, because the treatment will still depend on file extensions. You can probably mark the headers as excluded, I don't think that will mess with your ability to include them via header search, but not 100% sure.
  2. This isn't planned for 5.3 at the moment.
  1. I've followed your suggestion and put them as exclude: ["include"] (pun intended?). No need to indicate header search paths, SPM/clang is still smart enough to check for them as they're #included in the cpp files
  2. That's a shame... I'll rely on an unsafeFlag for now!
1 Like