Cross-compiling for arm using the stable channel?

I've been trying to use the stable channel to cross-compile for Arm, and kept running into libcore not wanting to build on the stable channel because "#[feature] may not be used on the stable release". Google was no help - all it turned up was instructions on building on the nightly channel. But the forum turned up this bit:

1.6 is now out, and has the same problem. Hopefully, what's missing is documentation on building libcore for the stable channel, and someone can point me in the right direction for that. Or is it that the replies were optimistic, and it's either impossible or difficult to use the stable channel for embedded work?

The second reply was a little optimistic, but the last one addressed that optimism: core being stable means it can be used with a stable compiler, but not (necessarily) that it can be built with it. Both it and std use basically every unstable feature internally, and thus can essentially only be built with an appropriate nightly compiler. The distributed compilers get around this because core is pre-built.

That said, you can build your own 1.6 cross-compiler using the --target=... argument to Rust's configure script, but it's probably easier to just use a nightly compiler. (A lot of embedded development probably wants some unstable features anyway, e.g. volatile loads/stores for some types of IO.)

I have actually built Rust 1.5(stable) and 1.6(stable) with respectively Rustc 1.5 and 1.6.
I had no issues with building std.
The most reliable way I think is to cross-compile rust for the target you need.

Well, using --target=thumbv7m-none-eabi - the same triple and target file I use for rustc - gets me back to complaints about an unknown triple. Is there some guidance on where that file needs to be stored?

Is it actually possible to compile std for bare metal? Given the list of things it provides and that all the blog entries for embedded just used core, I had expected that to not be the case.

Most important, if features crucial for writing embedded code aren't stable yet, possibly rust isn't ready for use on a production embedded project?

The target triple should be of the form: <architecture>[sub]-<vendor>-<system>-<abi>
So what you indicate looks like this:
arch = thumb (note that you mentioned previously that you try to cross-compile for ARM. I am not sure that thumb is an architecture)
sub = v7m
vendor = [not indicated](which already will throw the error about unknown triple)
system = none (which is ok since you want to compile for bare metal)
abi = eabi (which is also ok)

If I am not wrong, it will compile, just that you can't use it on bare metal. std is a separate part from the compiler.
The compiler just needs to know how to generate the code for the architecture you need, it doesn't need std for that.

Based on what you said previously, try these flags:
--target=armv7m-unknown-none-eabi or --target=arm-unknown-none-eabi.
Note that Rust's configure script doesn't seem to support armv7m so I doubt that the first one will work.
It does however support armv7l.

And, of course, if you try to cross-compile, have the cross-compilation environment set-up first...(the cross-compiler in the PATH environment variable).

Most probably would fail because configure script doesn't yet define this target triple.
You could try to make a workaround with links.

I'm not sure I'm looking in the right place for the list of supported architectures, but thumb is an architecture recognized by llc:

bhuda% llc --version | grep thumb
    thumb      - Thumb
    thumbeb    - Thumb (big endian)

Thumb is the 16-bit version of the arm architecture instruction set. The 32-bit arm instructions aren't supported by my target CPUs (cortex m3 & m4). This makes me think that while workarounds linking to the "arm" architecture might build, but seems likely to generate code that won't execute on my target platform.

My normal ARM build environment uses arm-none-eabi-gcc, arm-none-eabi-ld, arm-none-eabi-as, etc. That's gcc, not clang, but maybe that offers an easier path?

This seems like a lot of work to get a copy of std - which as noted, I can't use - when all I really need is libcore. From what I understand, the basic issue is that the rust stable channel isn't self-hosting. So another alternative would be to install a nightly channel compiler, use that to build libcore, then install the stable channel release I just built. IIUC, that's what's done for the stable channel now, so it ought to work here as well, right?

You don't need clang to cross-compile. Almost all cross-compiled rustc and std you will see in the wild are actually compiled with gcc.

I haven't looked into it but probably we can compile only the compiler.

You're not in Kansas anymore (llvm) so you either need to use the built-in Rust targets (possibly modified before bootstrapping) or create your own custom target. (or use a json spec)

The list is in src/librustc_back/target, while any new targets need to be added to (ibid.)

Hi Pete,

That's about what I'd figured. Except I need a copy of libcore compiled for that target. Simple compiling libcore doesn't work, as it doesn't build with the stable channel compiler as it uses lots of #[feature]s.The recommended solution seem to be to just build a rust cross-compiler. Creating a target file for that would seem to be the way to go, except that all of them assume you have an OS, whereas my target is bare metal. The file looks like I need to at least choose an OS family. Building the cross compiler also means getting std - which I can't use - to build. So is it possible to create a "built-in" target for bare metal? If so, is there docs on what that should look like somewhere?

I believe I saw a few bare metal ARM threads on reddit not long ago which should help you and anyway, have you tried zinc?

I looked at zinc,and a number of blogs/stackoverflow/etc. threads on cross-compiling to bare metal. All of them used the nightly channel, which means the instructions there don't work for the stable channel since you can't cross-compile libcore with the stable channel. I hadn't planned on using nightly, and that has wider implications than just the compiler. Possibly I can use the stable channel compiler with a libcore built with he nightly channel compiler, but that's not clear. That's the next thing to try.

Interesting if it should work but error E0514 is more likely.

Yes, building your own libcore requires nightly.

To be clear, every Rust compiler is a cross-compiler.

You might be interested in reading Bare Metal Rust 2: Retarget your compiler so interrupts are not evil | Random Hacks which discusses creating a target file for a bare-metal target.

1 Like

Ow, good point. I already forgot that you cross-compile "Rust" basically for the std, not for rustc.