[Pitch] Remove restrictions on generation of C artifacts

Swift Package Manager build tool plugins are a powerful mechanism to introduce code generators into SwiftPM builds. Currently, however, developers are running into limitations that have been put in place, in particular around the generation of C/C++ header files, module maps and API notes that allow for a code generator to fill out the definition of a C module from the generated code.

An example of this is the Swan library that provides a Swift interface to the Dawn WebGPU library. Dawn has a JSON file that describes its API and Swan generates the API notes that allows this API to be easily consumed from Swift. The API notes needs to be in the same directory as the modulemap which then refers to a generated C header file that brings in the Dawn headers. Ideally these are all generated at build time and incorporated into the SwiftPM build to ensure they line up with the desired version of Dawn. However due to the restrictions, Swan has a command plugin to generate the code which is then checked in. Not ideal.

This pitch is to relax those restrictions and ensure the generated files are properly incorporated into the build. In order to publish the module to downstream targets, they would need to be placed in a public header directory, just as regular source does for a C module. For this next release, we’ll hard code that as the include directory in the plugin output directory. Future work will allow this directory to be named in a build setting associated with the plugin.

It’s not fully clear to me why this restriction was put in place, except for the awkwardness over the public header files. But this short term solution should remove this blocker for those who need to generate these files.

I’m preparing a PR, #9252, and will produce an Evolution proposal based on feedback to this pitch. Your thoughts on this would be greatly appreciated.

14 Likes

Can you clarify: what specifically are the restrictions? Something to do with output directories? It is not clear from this write-up.

Should we be concerned about Chesterton's fence here?

1 Like

You get a warning message and the files are not included in the build, or sometimes treated as resources and included in the resource bundle.

I’m not familiar with that term. Can you elaborate?

Ah, so this is a more general-purpose diagnostic re unexpected files that’s not doing a useful thing when it comes to certain C artifacts? (My impression from the original write-up was that there was some sort of deliberate ruleset drawn up about C artifacts.)

Chesterton’s fence, as I understand it, is the notion that before removing an apparently not useful barrier one ought to identify the use it was intended for. In this case, it would be a matter of figuring out if there could be a reason for the restriction in the first place that is still applicable, which we might worry about unwittingly disturbing if we’re not sure we understand the rationale.

That said, if I understand your description correctly of what the specific ā€œrestrictionā€ is, you’re speaking of a limitation of the current design rather than a deliberate barrier?

2 Likes

Does this apply to build-system native, swift-build, or both?

As I stated in the pitch, I’m not sure why the restriction was put in. I can’t think of an important reason why it would be needed given Swift code generation does not have the same restriction. And we have a clear use case of where the restriction is preventing good architecture with Swan.

For 6.3, all features we add need to be for both to help ensure swiftbuild achieves parity in this release. It’s actually easier in swiftbuild thanks to imparted build settings which will propagate the public header path to all consuming targets.

It was exactly this, we didn’t have a way to provide headers or module maps, so we decided to postpone any support for generating non-Swift code.

1 Like

Thanks Boris! Though someone along the way added support for generating C source files which gets us some of the way.

Not sure if this is the right place or time to do it, but I'd really like to be able to generate .o and/or .a files (eg. by running a compiler for a non-C language) and have them included in the build.

1 Like

This seems like a good step forward in the SwiftPM plugin story. I’m in favor of lifting this restriction.

1 Like

I was involved in supporting a few projects which were facing similar awkwardness as you describe in the OP, so yeah this is definitely showing up here and there. This is a great restriction to lift, thank you for looking into it :slight_smile:

The include/ directory also sounds good, I think that’s a reasonable start.

Funnily enough, swift-java (which generates java sources) wasn’t affected by this because swiftpm just completely ignores them – so we were ā€œluckyā€ in that sense to not hit this issue in that project :sweat_smile:

1 Like

That has come up. It’s at a different level of the build graph though so is a bit more complicated. You’re essentially adding outputs to a target as opposed to inputs. But it’s something I’m looking at longer term.

1 Like