Brainstorming: External build plugin

SwiftPM has gained build plugin support from SE-0303, but one of the biggest problems so far is that a build plugin can only produce source files in a small set of languages, most notably Swift files. The inability to provide C/C++ header files makes it almost unusable to bridge complex C/C++ projects to SwiftPM, which is already a major pain now.

We can patch the existing build tool API to add something like includeHeaderPath, but here is a bigger picture — to design a completely new build tool system, and, if possible, rename the existing one to sourceProcessingTool to clarify their usage.

So what can an empowered build plugin do? I would expect it to build the target directly. Of course, we can integrate a Swift toolchain shortcut in the context, so the plugin can call it easily. It should be able to use external build tools like make, cmake and even nuget, and, either fail and stop the build, or succeed and return the products to SwiftPM.

A build plugin’s return is similar to the output of a regular target, including resources to be copied alongside (including support libraries or files), the real binary products, header search paths, and exclusively, library search paths to apply on dependent targets. If sandbox is enabled, external tools can only read the sources and operate within the provided directory.

There’re even more possibilities with new features like async/await and RegEx. We can parse the output of external build systems in real time, and emit progress updates or messages (warning/note) through an AsyncStream. This can make the UI more like native SwiftPM targets.

This is only an initial idea on the new build plugin system and it’s not implemented or proposed yet. I’m looking forward to get SwiftPM more powerful through the plugin system, which, by overall design, looks really modern and attractive.

6 Likes

Yes, please!

This could be especially useful if you want to interop with languages that aren't C/ObjC in a Swift Package. E.g. Rust-Swift-Interop would be made possible by using UniFFI in such a plugin.

Since it’s brainstorming time, let’s jump in wild. I’m still thinking of how can we define a Settings struct in a plugin and provide it in Package.swift, but this would be awesomely useful.

1 Like

I don't think we should be adding support for external build systems like CMake in the current world of a fairly hard-coded SwiftPM build system, but instead the first step should be moving the current build system to become a plugin itself. That could enable replacing the current build system with something that's CMake-based and after that, we could think about composition.