GSoC 2024: Interest in building Swift Macros with WebAssembly

Hi there!

I was happy seeing Swift be a mentor organisation for this year's GSoC. I scrolled through the project ideas and found the project "Building Swift Macros with WebAssembly" very interesting! I am writing here to express my interest into the project, to get in contact with my potential mentor @Douglas_Gregor , and to discuss some ideas I have.

I am a Computer Science and Engineering student from Chalmers University of Technology, Sweden. I am doing my first year of masters in Algorithms, Languages and Logic, and I am really enjoying it. I found this particular idea extra interesting since I have used WebAssembly a lot: my bachelor's thesis was to build a markup language where the document gets translated into the target format by different WebAssembly programs that gets dynamically loaded into our compiler. The WebAssembly programs can add support for new features to the markup language, and even add support for new output formats. I very much enjoyed the WebAssembly platform and me and my group really took advantage of the platform-agnostic features of it. The project is available online at https://modmark.org/ .

I also have a genuine interest in Swift, I have used Swift to code some programs in my free time and I really like the design choices of it. When I saw Swift getting Rust-like macro support, I saw that as a big step up for the language, and I want to contribute to the development of this.

Enough about me, let's go to the project idea itself. I find it super interesting, and I agree with the benefits of compiling macros to WebAssembly. I think the integration with the language frameworks itself can be executed seamlessly, as long as we create a good bridging between the compiler running on the host and the macro in the WebAssembly binary (which should be perfectly doable).

My first question is about the distribution of the macros themselves, how would they be distributed? Is the plan to compile them when publishing the library and to import them like .binaryTarget (or rather .wasmMacro/.binaryMacro then)? Going down this road would definitely make things faster and easier for the consumer, but the provider must make their wasm file available somewhere, and that would add complexity on their part.

My proposed solution would be for the consumer to actually download and build the macro to a wasm artifact on their first compilation, and then to check that in to version control, just like they would have done with a locally stored binary target. Then, SwiftPM would find that macro for everyone cloning the repo. For the API, this could simply be a flag to the .macro target, saying that it should look at a locally cached version first. This would have the benefit of it being opt-in for the consumer, making it available for all macros without the provider having to do anything. (We can of course check for timestamps of version releases vs the build time of the cached WebAssembly to re-build whenever necessary)

An alternate solution would be for the provider of the library to upload the macro as a part of their pushes. That would require them to build to generate the targets, and make sure to publish them. Then, the consumer would get the wasm binaries when checking out the repository, and the SwiftPM could locate them from there. This would, in contrast to my proposed solution, require the macro developer to explicitly support wasm macros (and possibly doing some extra work to enable it), and would require the consumer to blindly trust that a provided binary matches the source code given for the macro library. I think this solution isn't as elegant, but it is a solution nevertheless. (Or the provider may be tasked to distribute the binaries in another way, not tied to version control)

A third solution might be to have a central system download and build WebAssembly artifacts and host them online for SwiftPM to download. This would require large infrastructural work and resources from the side of Apple (or whoever hosts the central system), but would certainly make using such macros easy.

These are the three obvious solutions I see, what is your preferred solution @Douglas_Gregor ? Something like solution 1 and 2 could be combined by allowing importing macros in WebAssembly directly if the macro provider supplies a pre-compiled WebAssembly binary, but also allow local caching in WebAssembly and checking that cache in to Version Control.

Sorry for the long-winded post :sweat_smile: but those are my initial thoughts. I have started reading though source code of the compiler and SwiftPM to check where support for this can be added. Are there any resources you recommend me checking though? Do you have any suggestions for next steps before starting with the proposal?

Hope to hear from you,
Jonathan Widén

9 Likes