Specify custom modulemap exported by a Swift target

Once again I am evaluating whether I can build a project with SwiftPM or we need our own build system.

This time, it's a project that is mostly cross-platform C, (and in fact cross-compiles to weird architectures outside the scope of this problem).

Generally it's desirable for the Swift clients to use the C types directly. I have been annotating the C headers with swift_name to get a more modern-feeling API. In rare cases, we implement some behavior in Swift directly if it's not interesting to the other platforms (.description on the C types is a good example).

SwiftPM seems to want separate targets for C and Swift:

    targets: [
package depends on.
        .target(
            name: "lib-c",
            dependencies: []),
        .target(
            name: "lib",
            dependencies: ["lib-c"],
        ),
        .testTarget(
            name: "libTests",
            dependencies: ["lib"]),
    ]

This is not the end of the world from a build perspective. However, this seems to also imply callers will need to import lib-c and import lib in order to get both the C types and e.g. .description, which is not a good end experience.

In other build systems we can specify a custom modulemap for our built products, as to cause import lib to pull in lib-c as well. I looked and did not see a similar mechanism in SwiftPM, and wanted to double-check that this sort of case is not supported before I went off in a different direction.

1 Like

You can use @_exported import to achieve your goal. Note that this is technically a non-stable feature whose spelling may change at any time, or may even be entirely removed.

It sounds like what you may also want is some kind of "apinotes". This is something the Swift compiler supports, but has never been "productized" for use in either Xcode or SwiftPM.

In the past it is something @Douglas_Gregor and I have talked about, is whether or not .apinotes should be supported natively by SwiftPM (see https://github.com/apple/swift/tree/master/apinotes for examples). I'm not sure if his thinking has changed on this, from my perspective it would be a fairly natural thing for SwiftPM to gain support for. Sadly I no longer remember much of the context on exactly how much work it is.