How to cross compile Rust program for non-Linux OS with gcc toolchain for aarch64?

Our Rust program mainly targets for aarch64-unknown-linux-gnu

However, we have demands from our partners to cross compile for their own Operating System.

The OS runs on the same hardware, so the CPU is still aarch64.
The OS is not listed anywhere in https://doc.rust-lang.org/rustc/platform-support.html

Gcc cross compile toolchain is provided, with C11/C++17 compiler, linker and Glibc/POSIX compatible headers and libraries, such as libc.so and pthread.so

That OS is UNIX-like, but it does not support Linux specific behavior that is not POSIX compatible.

For C/C++ program, if the code is written according to C/C++/POSIX standard, the migration to the new OS is just changing the path of gcc to the new toolchain.

But how to do that for Rust program?

We use stable toolchain for Linux compilation. It is okay for us to use nightly Rust toolchain for non-linux OS.

Is it still possible to use std?
I do not want to use #![no_std] and write OS specific code all by ourselves,
because that would be too much work.

First off you will have to add a target specification to rustc to describe your target (architecture, linker flags, ...) at compiler/rustc_target/src/spec. You can look at the target specs for similar OSes for inspiration. Then you have to add support for your OS to the libc crate at GitHub - rust-lang/libc: Raw bindings to platform APIs for Rust. This crate contains bindings for libc functions and has a role similar to header files in C. Next if you want libstd support you will have to modify library/std/src/sys/unix as necessary to make it compile. While POSIX specifies many functions, some functions exposed by libstd are not part of POSIX, or simply not available on all UNIX like OSes. For those you have to tell libstd to use the dummy or fallback implementation. And finally you can compile your newly modified rustc using ./x.py dist --host host-triple --target "host-triple target-triple". Make sure to include the triple of the system on which the cross compiler will run in --target` too as otherwise build scripts and proc macros can't be compiled by the cross compiler.

If possible without breaking an NDA and such, you may want to upstream your changes. This is likely to be much easier to maintain than rebasing every time. Be sure to read Target Tier Policy - The rustc book for all requirements for tier 3 targets. As additional benefit this allows you to compile for your target on nightly using cargo build -Zbuild-std=std --target target-triple without having to recompile the entire compiler.

If GCC has already been ported to it, then yes it is generally that simple. If it hasn't yet, you did have to make similar changes to GCC and the C++ STL as you need to make to rustc and the rust standard library. The only extra step is writing bindings for libc in the libc crate.

1 Like

Is it possible to not recompile rustc? Is there a feature so I can just provide a configuration file?

Yes, there is the target spec json feature. You can write the target specification as a json file and then pass the path to this file to --target. You can use rustc -Zunstable-options --print target-spec-json --target some-target to print the target spec for some-target in json format. Make sure to remove the is-builtin key.

The target spec json feature is mostly useful for #![no_std] targets however as it doesn't allow modifying the standard library source code. (You can technically modify the copy of the standard library shipped with the rust toolchain, but you will have to do that every time you update rustc and you won't have any version control this way.)

Thanks. Is it possible to use json file to disable all linux specific code in Rust std?

I have read https://github.com/rust-lang/rust/tree/master/library/std/src/os/linux,
it seems not so such linux specific code out there.
But I still want to avoid modification of any code.

I think, ideally, Rust cross compile for non-linux should be:

  1. -Zbuild-std with json config file
  2. compile Rust crates into static lib
  3. link into shared lib using the ported gnu linker

It is unlikely for me to submit upstream patches for those OS.
Because I am just a user, not the developer of the OS.

Linux specific code will only be included if you set the os field in the target specification to linux. However there are several places where you need to make changes to the standard library to get it to compile:

That doesn't matter. If you are willing to maintain it, that is enough. Many targets are maintained by users rather than the original developer of the OS. If you don't want to maintain it, I completely understand that too.

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.