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
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 crates.io 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
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.