The libstd Unsupported Target Quagmire

Rust is pretty great as a C replacement, even for unusual targets. I've done two projects, one to compile homebrew for the 3DS, the other for the PlayStation Vita, and provided you are not using the standard library libstd, it is relatively painless to built for these unsupported targets via the homebrew community's own toolchains.

However, there is one sizable pain point: invoking any extern function is an unsafe operation, and it is not very idiomatic Rust. A lot of the code you're going to write in these targets is implementing stuff that libstd provides for you (abstracting syscall io into Read and Write, both traits of which are constrained to libstd, etc...), if you want to write Rust Rust. This sucks, to put it simply.

In an ideal world, we could implement libstd using our target's available system calls with relative ease, to avoid having to rewrite this boilerplate, and to leverage the full ecosystem.

In my opinion, the ideal solution is that libstd would be modularized to allow for providing backend implementations independent of the abstraction layer (for example, std::thread needs a backend). Currently libstd's backends exist in the sys and os modules and what gets built and exported is dependent on target_os and other config flags. This is a bit of a non-starter because of how much refactoring would be needed.

A second solution to this problem would be splitting off libstd from the main rust repository so it can be easily forked and have backends implemented by third-parties as they are currently implemented. Having a separate repository would ease the process of maintaining libstd with upstream changes significantly.

The second approach is roughly how Redox does their standard library. They have to manually maintain their fork with upstream updates, however; no git magic here. This sort makes sense given they also build their own compiler and sysroot manually.

In both situations, we would still need a better way of building sysroots for unsupported targets without forking and rebuilding the rust toolchain. xargo serves us well for the free-standing crates, such as core, but it is very difficult to build std here regardless of where it comes from.

At the moment, even if the device in question has all the (proprietary) library support necessary to have libstd, it is very difficult to provide implementations for it to use them. Even for legitimate uses, like using an official SDK for a game console, this is still just as difficult. The Vita has all the OS support for threading, file systems, etc. But pushing implementations for them into upstream does not make sense, since homebrew toolchains are unofficial and in some cases legally murky. We see in the real-world case of SDL where all unofficial targets using devkitPro were dropped from the repository for 2.0. So it leaves us in a quagmire without a straight-forward path to providing libstd for our targets. I hope the story for std-implementation improves in the future, but the current situation leaves us rather limited.

That all said, it's an absolute blessing that we have a modern systems-level language that can target basically anything provided you have a gcc for it.


There is some additional discussion in RFC 1502, RFC 1734 and PR 37133 regarding alternative libstd implementations.