You may fall into a trap thinking that adding support for a "simple" platform is going to be a simple task. In my experience of working with SwiftWasm, that's not the case. If you're interested in learning, you should either look into how current platform support works, digging into the existing build system, infrastructure, runtime, etc, or look at a platform that's as close as possible to already supported platforms.
32-bit platforms are quite far from what upstream Swift supports. Good news is that you aren't targeting a 16-bit platform. As far as I know, none of the PRs upstream are tested on 32-bit platforms before merging, and looking at community CI, 32-bit Android had last successful build more than a month ago. I also frequently see Raspberry Pi people trying to keep the 32-bit build maintained saying it breaks with almost every release. SwiftWasm is (partially) 32-bit, but we had to make and still maintain plenty of changes from upstream to seemingly make it work.
Unfortunately, Swift wasn't designed (at least initially) with embedded platforms or bare metal support in mind. This doesn't mean it won't ever support such platforms, it's obviously up to the core team to decide when/if that's going to happen. In the meantime you'll have to resolve or work around a few major roadblocks that don't have good solutions in the upstream codebase yet.
This is exacerbated by the fact that GBA has (looking at Wikipedia ) 32 KB internal, 256 KB external RAM. It's going to be quite hard to get a binary produced by Swift that fits into memory, never mind making the rest of the things work.
The best place to start is probably existing C/C++ toolchains for GBA, especially if there are any based on LLVM. In the end, if LLVM, clang, and related tools don't fully support your target platform, I don't think there's much point to start looking at Swift until all the dependencies work well.
When you're ready to switch from C/C++ toolchains to Swift, here's an incomplete list of things I'd start looking at:
- The series of articles by @jrose about Swift runtime and metadata: Archive for “Swift runtime” // -dealloc. This other article about porting Swift to other platform is also a must read: Swift on Mac OS 9 // -dealloc
- The issue of relative/absolute pointers in the runtime. You need to check if upstream implementation of relative pointers works on GBA IRGen & Runtime: Add a flag to disable relative pointer for some object formats by kateinoigakukun · Pull Request #39259 · apple/swift · GitHub and Wasm Support - #16 by kateinoigakukun
- Turning multi-threading off, especially if you're targeting bare metal. ARC and probably the whole runtime assume the presence of atomics and thread-local storage. You may need some shims for that, or rely on LLVM's
-femulated-tls
Runtime: emulate TLS with a map for WASI target by MaxDesiatov · Pull Request #31694 · apple/swift · GitHub
- What libc are you going to use? Will you provide your own shims, or does some barebones libc port exist already for your platform? That's why testing existing C/C++ toolchains for GBA is crucial. The presence of WASI libc simplified a lot of things for SwiftWasm, but has some significant amount of overhead. There's also an undocumented "freestanding" configuration that was recently introduced to upstream Swift, which may be relevant. We plan to investigate its feasibility for Wasm builds, but haven't done that yet. Here are a few sparsely documented test cases to start digging: swift/check_freestanding_dependencies.py at 83484f85163bdfbe743f0a840451982268644d3c · apple/swift · GitHub and swift/check_freestanding_size.py at 0bf1389863193cf4a397234dbf15d65dafd7c4b7 · apple/swift · GitHub
- The last link above to
check_freestanding_size.py
may also be a good pointer for reducing the binary size to make it fit into the minuscule amount of memory you have. Looks like 640 KiB on x86_64 Darwin is the smallest you can get right now, and I'd assume that doesn't even link libc statically. But in the end this may be the biggest issue overall. Even though ICU dependency was removed from the toolchain, it didn't reduce the final binary size that much, since Unicode tables still need to be embedded. You'll probably have to disable all Unicode stuff with the String
type in stdlib altogether for things to work. For example, StringUTF8.swift
test is completely disabled in the freestanding configuration.
The other problem is that cross-compilation isn't supported very well (if at all) outside of Apple's platforms. You'll have to gain some good knowledge of the current toolchain build system to make it fully work. The fact that the build system is spread across shell scripts, Python, and CMake, makes cross-compilation particularly hard.
Having at least some basic knowledge of CMake is highly recommended. This article is a good place to start It’s Time To Do CMake Right | Pablo Arias, but may not be sufficient. Have a look at awesome-cmake list, and maybe Professional CMake book, or any other widely recommended book (like "Effective CMake" or "Modern CMake") if you want to dig deeper. Unfortunately, the official CMake reference does not seem to be a good intro, at least it didn't work that way for me.
I don't want to discourage you from working on GBA support, but you may also consider porting Swift to musl/Alpine Linux as a better place to start. This isn't too different from Linux distributions supported already, but is something that would be quite useful to support in upstream Swift, and as a learning project that may help you with GBA support in the future. For example, musl libc needs to be statically linked, which is probably going to be the case for GBA as well. I started working on that here, but got stuck on trying to make LLVM/clang work with musl: GitHub - MaxDesiatov/swift-alpine: Swift on Alpine Linux using musl instead of glibc (work in progress). Any help with that would be highly appreciated.
I also encourage you to have a CI setup as early as possible. This will help you get reproducible builds and will get you something to come back to later. GitHub Actions + Docker with hardcoded image versions may be a good option, especially as it's free for open-source projects.
I hope this helps!