Running Rust code on the 3DS 2: Electric Boogaloo

A few months ago I wrote a guide on compiling rust code to the 3DS, and an accompanying wrapper library for libctru. Unfortunately, that didn't work beyond trivial examples. However, months later I have figured out how to get the libcompiler-rt intrinsics built for the Nintendo 3DS.

Updated September 17, 2015: alloc crate now works, meaning collections now works as well.

Without further adieu, I present rust3ds-template and the previous ctru-rs.

As mentioned in the readme for rust3ds-template, several system libraries in the rust compiler source will compile for 3DS perfectly fine. I've added a sysroot target to do this. However, alloc doesn't link, which means collections won't work, so don't get your hopes up too soon. A forked implementation of these libraries may be necessary to get things fully up and running. Does that mean you can't do much right now? Not necessarily, though things like Vec which you might be used to, you'll have to reimplement in some fashion, without Box. That's a tough call, but the work to get alloc working shouldn't be that hard. In addition, a simple implementation of alloc_system is added as a dependency to the template so that collections, alloc, etc. all work.

How it works

rustc invokes llc on its bitcode output and then the specified assembler, which we can control a little bit using target json files. Those target files can be passed to cargo. We use a modified cargo-build to ensure that the other necessary flags to rustc are passed to every invocation rather than simply the bottom level one. This is because stack unwinding is not available on the 3DS (and probably doesn't need to be). Linker issues are dealt with through this target json as well.

What about all the C libraries?

If you have C library dependencies, you can use rust's normal FFI facilities to declare symbols that will be linked by arm-none-eabi-gcc. Naturally, these require unsafe code; you should expect at this point to use a lot of that in order to work on the 3DS.

Conveniently, you will not have to have these symbols available until you link the binary, so you can use tools like racer to get completions on ctru-rs even though there is no desktop libctru, and the compiler itself to get validation.

alloc_system is implemented in terms of libc's memory allocation functions, so it will not interfere with that allocation system.

What are the benefits?

Rust is a much, much more expressive language than C. A lot of quirky constructs that you have to make in C aren't necessary in Rust because the language provides things like generic types and pattern matching. Even without the safety and concurrency features, you stand to gain a net benefit in productivity when developing your homebrew software if you use Rust's language features well. Heck, even without collections, it's still much easier to write complex data structures. This is made even better now that collections work! Easy data structures!

However, while it is Rust, it is still harder than if you had libstd at your disposal. There are challenges left to overcome, but hopefully in the coming months we can solve them and have mostly everything that you would expect in the rust standard library available in the 3DS. libstd is still not available because of missing unwinding and threads support, but this will hopefully be overcome soon.