[GSoC 2026] Sysroot Support - Architecture for decoupling corelibs

Hi @Max_Desiatov and @kateinoigakukun

I was checking out the GSoC 2026 ideas list, and the Sysroot Support project in build-script really grabbed my attention. I've been diving deep into SwiftPM and swift-build lately—working on stuff like noneOS platform mapping, Windows MSVC linker flag normalization, and how SPM deals with -print-target-info. So far, I've mostly seen how the build system uses those target environments, and I'd love to use GSoC to dig even deeper into how build-script actually puts them together.

I've been poking around in utils/swift_build_support to understand the current setup, especially how wasmswiftsdk.py bundles the corelibs right now. From what I can tell, the goal is to break those out into their own target-specific build products that can use the --experimental-sysroot flag independently. This seems like a great way to stress-test the mechanism against different architectures, like an Android NDK sysroot or a Linux environment using musl libc.

As I wrap up the technical milestones for my proposal, I just wanted to double-check one thing about the dependency graph in Python: When we split the target-side corelibs into separate products, what's the best way to handle their relationship with the host compiler? Should the design expect the host toolchain to be built in the step right before during the same build-script run, or should it be modular enough to accept an existing, externally provided toolchain path? I'm thinking about how this impacts the build graph's flexibility and the efficiency of running target-side tests without always needing a full host rebuild.

I've got the main part of my implementation plan sketched out already, and I just want to make sure my thinking matches the team's vision before I share the full draft. Any advice here would be super helpful!

1 Like

Hey @Max_Desiatov and @kateinoigakukun

I’ve been spending the last few days refining my draft proposal for GSoC 2026,
and to briefly explain my proposal, Draft : GSoC 2026 Draft

i would use the same Why over the How concept which I did in my recent Post.

I chose Sysroot Support in build-script for Cross-Compilation Targets due to my recent experience with SwiftPM and compiler diagnostics, which underscored the importance of moving from fragmented, target-specific silos toward a modular and unified build pipeline.

For this project, the "Why" is about making Swift truly universal.

Right now, cross-compilation is fragmented. We have bespoke variables like SWIFT_ANDROID_NDK_PATH or SWIFT_WASI_SYSROOT_PATH scattered across CMake. The WebAssembly pipeline, for instance, relies on wasmswiftsdk.py, which acts as a monolith—it bundles Foundation, XCTest, swift-testing, and libxml2 into a single, opaque pipeline using inline private build methods.

If a new target comes along that needs a slightly different setup—perhaps one that requires libdispatch (which is currently disabled in the WASI context)—we shouldn’t have to duplicate that entire monolith just to change one variable.

The goal is to decouple these core components into standalone CMakeProduct classes. By introducing a unified --experimental-sysroot and a centralized SysrootConfig, we can build a modular pipeline that can point at any sysroot and just work.

The following diagram illustrates this architectural shift from the current monolithic pipeline to the proposed decoupled structure:

@ktoso I would dearly appreciate any suggestions or feedback from you as well :)

Apologies for my late feedback. Our ci.swift.org infrastructure does support invoking only a single build-script, so we have to make a single invocation to build products for all cross-compilation targets. Optionally, it would be nice to be able to specify a pre-built toolchain by --native-*-tools-path to allow skipping building compiler itself.
So in short, if we want to generalize the build script fully decoupled from the target platforms, we have to have a way to specify options per target (e.g. Rust toolchain's build system has a way to configure options per target platform rust/bootstrap.example.toml at 4cf5f9580233c36f6bc8db76e282ba8a1c1ea491 · rust-lang/rust · GitHub)

1 Like

Thank you for the feedback @kateinoigakukun I completely overlooked the CI infrastructure.

A single build-script invocation needs to handle building for all targets at once. To solve this, I updated the architecture to move away from single target CLI flags. Instead build-script will accept a config file via a new --cross-compile-config=targets.json flag (very similar to the Rust bootstrap approach you linked), and then the Python layer will parse this file and iterate through the requested targets to execute them in one go.

Regarding your second point about specifying a pre built toolchain via --native-swift-tools-path, I actually just refactored the CMake layer of the proposal this morning based on feedback from Max. He pointed out that we should be generating standard CMake toolchain files instead of passing custom variables.

so now the python script will simply read the --native-swift-tools-path provided in the CLI or JSON and inject it directly as the CMAKE_Swift_COMPILER variable inside the generated <target>-toolchain.cmake file for each target.

I have updated the architecture diagram and proposal doc to reflect this JSON config loop and the native tools path integration. Thank you again for catching the CI constraint. Lemme know if this aligns better with the infrastructure needs.

P.S. GoodNotes is my absolute fav note-taking app. It genuinely helped me survive so many heavy theory subjects during my freshman and sophomore years. I really appreciate the work you and the team have done!

1 Like