Git Product home page Git Product logo

rust-cross's Introduction

travis-badge

rust-cross

Everything you need to know about cross compiling Rust programs!

If you want to set up your Rust toolchain as a cross compiler, you have come to the right place! I have documented all the necessary steps, plus the gotchas and common problems that you may find along the way.

Dear reader, if you spot a typo, a broken link, or a poorly worded/confusing sentence/paragraph please open an issue pointing out the problem and I'll update the text. Pull requests fixing typos or broken links are, of course, welcome!

TL;DR Ubuntu example

Here are the commands necessary to set up a stable Rust toolchain as a cross compiler for ARMv7 (*) devices on a fresh Ubuntu Trusty install. The goal of this example is to show that cross compilation is easy to setup and even easier to perform.

(*) ARM v7, these instructions won't work to cross compile for the Raspberry Pi (1), that's an ARM v6 device.

# Install Rust. rustup.rs heavily recommended. See https://www.rustup.rs/ for details
# Alternatively, you can also use multirust. See https://github.com/brson/multirust for details
$ curl https://sh.rustup.rs -sSf | sh

# Step 0: Our target is an ARMv7 device, the triple for this target is `armv7-unknown-linux-gnueabihf`

# Step 1: Install the C cross toolchain
$ sudo apt-get install -qq gcc-arm-linux-gnueabihf

# Step 2: Install the cross compiled standard crates
$ rustup target add armv7-unknown-linux-gnueabihf

# Step 3: Configure cargo for cross compilation
$ mkdir -p ~/.cargo
$ cat >>~/.cargo/config <<EOF
> [target.armv7-unknown-linux-gnueabihf]
> linker = "arm-linux-gnueabihf-gcc"
> EOF

# Test cross compiling a Cargo project
$ cargo new --bin hello
$ cd hello
$ cargo build --target=armv7-unknown-linux-gnueabihf
   Compiling hello v0.1.0 (file:///home/ubuntu/hello)
$ file target/armv7-unknown-linux-gnueabihf/debug/hello
hello: ELF 32-bit LSB  shared object, ARM, EABI5 version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.32, BuildID[sha1]=67b58f42db4842dafb8a15f8d47de87ca12cc7de, not stripped

# Test the binary
$ scp target/armv7-unknown-linux-gnueabihf/debug/hello me@arm:~
$ ssh me@arm:~ ./hello
Hello, world!

1. 2. 3. You are now cross compiling!

For more examples check the Travis CI builds.

The rest of the guide will explain and generalize each step performed in the previous example.

Table of Contents

This guide is divided in two parts: The "main text" and advanced topics. The main text covers the simplest case: cross compiling Rust programs that depend on the std crate to a "supported target" where official builds are available. The advanced topics section covers no_std programs, target specification files, how to cross compile the "standard crates" and troubleshooting common problems.

The advanced topics section builds on top of the information explained in the main text. So, even if your use case is not the same as the one covered by the main text, you should still read the main text before jumping into the advanced topics section.

Terminology

Let's make sure we are talking the same language by defining some terms first!

In its most basic form, cross compiling involves two different systems/computers/devices. A host system where the program is compiled, and a target system where the compiled program gets executed.

For example, if you cross compile a Rust program on your laptop to execute it on a Raspberry Pi 2 (RPi2). Then your laptop is the host, and the RPi2 is the target.

However, a (cross) compiler doesn't produce a binary that only works on a single system (e.g. the RPi2). The produced binary can also be executed on several other systems (e.g. the ODROIDs) that share some characteristics like their architecture (e.g. ARM) and their Operating System (e.g. Linux). To refer to this set of systems with shared characteristics we use a string called a triple.

Triples are usually formatted as follows: {arch}-{vendor}-{sys}-{abi}. For example, the triple arm-unknown-linux-gnueabihf refers to the systems that share these characteristics:

  • architecture: arm.
  • vendor: unknown. In this case, no vendor was specified and/or is not important.
  • system: linux.
  • ABI: gnueabihf. gnueabihf indicates that the system uses glibc as its C standard library (libc) implementation and has hardware accelerated floating point arithmetic (i.e. an FPU).

And systems like the RPi2, the ODROIDs, and pretty much every ARMv7 dev board that runs GNU/Linux belongs to this triple.

Some triples omit the vendor or the abi component so they are actually "triples". An example of such a triple is x86_64-apple-darwin, where:

  • architecture: x86_64.
  • vendor: apple.
  • system: darwin.

NOTE From now on, I'm going to overload the term target to mean a single target system, and also to refer to a set of systems with shared characteristics specified by some triple.

Requirements

To compile a Rust program we need 4 things:

  • Find out what's the triple for the target system.
  • A gcc cross compiler, because rustc uses gcc to "link" stuff together.
  • C dependencies, usually "libc", cross compiled for the target system.
  • Rust dependencies, usually the std crate, cross compiled for the target system.

The target triple

To find out the triple for your target, you first need to figure out these four bits of information about the target:

  • Architecture: On UNIXy systems, you can find this with the command uname -m.
  • Vendor: On linux: usually unknown. On windows: pc. On OSX/iOS: apple
  • System: On UNIXy systems, you can find this with the command uname -s
  • ABI: On Linux, this refers to the libc implementation which you can find out with ldd --version. Mac and *BSD systems don't provide multiple ABIs, so this field is omitted. On Windows, AFAIK there are only two ABIs: gnu and msvc.

Next you need to compare this information against the targets supported by rustc, and check if there's a match. If you have a nightly-2016-02-14, 1.8.0-beta.1 or newer rustc you can use the rustc --print target-list command to get the full list of supported targets. Here's the list of supported targets as of 1.8.0-beta.1:

$ rustc --print target-list | pr -tw100 --columns 3
aarch64-apple-ios                i686-pc-windows-gnu              x86_64-apple-darwin
aarch64-linux-android            i686-pc-windows-msvc             x86_64-apple-ios
aarch64-unknown-linux-gnu        i686-unknown-dragonfly           x86_64-pc-windows-gnu
arm-linux-androideabi            i686-unknown-freebsd             x86_64-pc-windows-msvc
arm-unknown-linux-gnueabi        i686-unknown-linux-gnu           x86_64-rumprun-netbsd
arm-unknown-linux-gnueabihf      i686-unknown-linux-musl          x86_64-sun-solaris
armv7-apple-ios                  le32-unknown-nacl                x86_64-unknown-bitrig
armv7-unknown-linux-gnueabihf    mips-unknown-linux-gnu           x86_64-unknown-dragonfly
armv7s-apple-ios                 mips-unknown-linux-musl          x86_64-unknown-freebsd
asmjs-unknown-emscripten         mipsel-unknown-linux-gnu         x86_64-unknown-linux-gnu
i386-apple-ios                   mipsel-unknown-linux-musl        x86_64-unknown-linux-musl
i586-unknown-linux-gnu           powerpc-unknown-linux-gnu        x86_64-unknown-netbsd
i686-apple-darwin                powerpc64-unknown-linux-gnu      x86_64-unknown-openbsd
i686-linux-android               powerpc64le-unknown-linux-gnu

NOTE If you are wondering what's the difference between arm-unknown-linux-gnueabihf and armv7-unknown-linux-gnueabihf, the arm triple covers ARMv6 and ARMv7 processors whereas armv7 only supports ARMv7 processors. For this reason, the armv7 triple enables optimizations that are only possible on ARMv7 processors. OTOH, if you use the arm triple you would have to opt-in to these optimizations by passing extra flags like -C target-feature=+neon to rustc. TL;DR For faster binaries, use armv7 if your target has an ARMv7 processor.

If you didn't find a triple that matches your target system, then you are going to need to create a target specification file.

From this point forwards, I'll use the term $rustc_target to refer to the triple you found in this section. For example, if you found that your target is arm-unknown-linux-gnueabihf, then whenever you see something like --target=$rustc_target mentally expand the $rustc_target bit so you end with --target=arm-unknown-linux-gnueaibhf.

Similarly, I'll use the $host term to refer to the host triple. You can find this triple in the rustc -Vv output under the host field. For example, my host system has triple x86_64-unknown-linux-gnu.

C cross toolchain

Here things get a little confusing.

gcc cross compilers only target a single triple. And this triple is used to prefix all the toolchain commands: ar, gcc, etc. This helps to distinguish a tool used for native compilation, e.g. gcc, from a cross compilation tool, e.g. arm-none-eabi-gcc.

The confusing part is that triples can be quite arbitrary, so your C cross compiler will most likely be prefixed with a triple that's different from $rustc_target. For example, in Ubuntu the cross compiler for ARM devices is packaged as arm-linux-gnueabihf-gcc, the same cross compiler is prefixed as armv7-unknown-linux-gnueabihf-gcc in Exherbo, and rustc uses the arm-unknown-linux-gnueabihf triple for that target. None of these triples match, but they refer to the same set of systems.

The best way to confirm that you have the correct cross toolchain for your target system is to cross compile a C program, preferably something not trivial, and test executing it on the target system.

As to where to get the C cross toolchain, that will depend on your system. Some Linux distributions provide packaged cross compilers. In other cases, you'll need to compile the cross compiler yourself. Tools like crosstool-ng can help with that endeavor. For Linux to OSX, check the osxcross project.

Some examples of packaged cross compilers below:

  • For arm-unknown-linux-gnueabi, Ubuntu and Debian provide the gcc-*-arm-linux-gnueabi packages, where * is gcc version. Example: gcc-4.9-arm-linux-gnueabi
  • For arm-unknown-linux-gnueabihf, same as above but replace gnueabi with gnueabihf
  • For OpenWRT devices, i.e. targets mips-unknown-linux-uclibc (15.05 and older) and mips-unknown-linux-musl (post 15.05), use the OpenWRT SDK
  • For the Raspberry Pi, use the Raspberry tools.

Note that the C cross toolchain will ship with a cross compiled libc for your target. Make sure that:

  • The toolchain libc matches the target libc. Example, if your target uses the musl libc, then your toolchain must also use the musl libc.
  • The toolchain libc is ABI compatible with the target libc. This usually means that the toolchain libc must be older than the target libc. Ideally, both the toolchain libc and the target libc should have the exact same version.

From this point forwards, I'll use the term $gcc_prefix to refer to the prefix of the cross compilation tools (i.e. the cross toolchain) you installed in this section.

Cross compiled Rust crates

Most Rust programs link to the std crate, so at the very least you'll need a cross compiled std crate to cross compile your program. The easiest way to get it is from the official builds.

If you are using multirust, as of 2016-03-08, you can install these crates with a single command: multirust add-target nightly $rustc_target. If you are using rustup.rs, use the command: rustup target add $rustc_target. And if you are using neither, follow the instructions below to install the crates manually.

The tarball you want is $date/rust-std-nightly-$rustc_target.tar.gz. Where $date usually matches with the rustc commit date shown in rustc -V, although on occasion the dates may differ by one or a few days.

For example, for a arm-unknown-linux-gnueabihf target and a rustc with version (rustc -V) rustc 1.8.0-nightly (3c9442fc5 2016-02-04) this is the correct tarball:

http://static.rust-lang.org/dist/2016-02-04/rust-std-beta-arm-unknown-linux-gnueabihf.tar.gz

To install the tarball use the install.sh script that's inside the tarball:

$ tar xzf rust-std-nightly-arm-unknown-linux-gnueabihf.tar.gz
$ cd rust-std-nightly-arm-unknown-linux-gnueabihf
$ ./install.sh --prefix=$(rustc --print sysroot)

WARNING The above command will output a message that looks like this: "creating uninstall script at /some/path/lib/rustlib/uninstall.sh". Do not run that script because it will uninstall the cross compiled standard crates and the native standard crates; leaving you with an unusable Rust installation and you won't be able to compile natively.

If for some reason you need to uninstall the crates you just installed, simply remove the following directory: $(rustc --print sysroot)/lib/rustlib/$rustc_target.

NOTE If you are using the nightly channel, every time you update your Rust install you'll have to install a new set of cross compiled standard crates. To do so, simply download a new tarball and use the install.sh script as before. AFAICT the script will also take care of removing the old set of crates.

Cross compiling with rustc

This is the easy part!

Cross compiling with rustc only requires passing a few extra flags to its invocation:

  • --target=$rustc_target, tells rustc we are cross compiling for $rustc_target.
  • -C linker=$gcc_prefix-gcc, instructs rustc to use a cross linker instead of the native one (cc).

Next, an example to test the cross compilation setup so far:

  • Create a hello world program on the host
$ cat hello.rs
fn main() {
    println!("Hello, world!");
}
  • Cross compile the program on the host
$ rustc \
    --target=arm-unknown-linux-gnueabihf \
    -C linker=arm-linux-gnueabihf-gcc \
    hello.rs
  • Run the program on the target
$ scp hello me@arm:~
$ ssh me@arm ./hello
Hello, world!

Cross compiling with cargo

To cross compile with cargo, we must first use its configuration system to set the proper linker and archiver for the target. Once set, we only need to pass the --target flag to cargo commands.

Cargo configuration is stored in a TOML file, the key we are interested in is target.$rustc_target.linker. The value to store in this key is the same we passed to rustc in the previous section. It's up to you to decide if you make this configuration global or project specific.

Let's go over an example:

  • Create a new binary Cargo project.
$ cargo new --bin foo
$ cd foo
  • Add a dependency to the project.
$ echo 'clap = "2.0.4"' >> Cargo.toml
$ cat Cargo.toml
[package]
authors = ["me", "myself", "I"]
name = "foo"
version = "0.1.0"

[dependencies]
clap = "2.0.4"
  • Configure the target linker and archiver only for this project.
$ mkdir .cargo
$ cat >.cargo/config <<EOF
> [target.arm-unknown-linux-gnueabihf]
> linker = "arm-linux-gnueabihf-gcc"
> EOF
  • Write the application
$ cat >src/main.rs <<EOF
> extern crate clap;
>
> use clap::App;
>
> fn main() {
>     let _ = App::new("foo").version("0.1.0").get_matches();
> }
> EOF
  • Build the project for the target
$ cargo build --target=arm-unknown-linux-gnueabihf
  • Deploy the binary to the target
$ scp target/arm-unknown-linux-gnueabihf/debug/foo me@arm:~
  • Run the binary on the target.
$ ssh me@arm ./foo -h
foo 0.1.0

USAGE:
        foo [FLAGS]

FLAGS:
    -h, --help       Prints help information
    -V, --version    Prints version information

Advanced topics

Cross compiling the standard crates

Right now, you can only cross compile the standard crates if your target is supported by the Rust build system (RBS). You can find a list of all the supported targets in the mk/cfg directory (NOTE linked directory is not the latest revision). As of rustc 1.8.0-nightly (3c9442fc5 2016-02-04), I see the following supported targets:

$ ls mk/cfg
aarch64-apple-ios.mk              i686-pc-windows-msvc.mk           x86_64-pc-windows-gnu.mk
aarch64-linux-android.mk          i686-unknown-freebsd.mk           x86_64-pc-windows-msvc.mk
aarch64-unknown-linux-gnu.mk      i686-unknown-linux-gnu.mk         x86_64-rumprun-netbsd.mk
arm-linux-androideabi.mk          le32-unknown-nacl.mk              x86_64-sun-solaris.mk
arm-unknown-linux-gnueabihf.mk    mipsel-unknown-linux-gnu.mk       x86_64-unknown-bitrig.mk
arm-unknown-linux-gnueabi.mk      mipsel-unknown-linux-musl.mk      x86_64-unknown-dragonfly.mk
armv7-apple-ios.mk                mips-unknown-linux-gnu.mk         x86_64-unknown-freebsd.mk
armv7s-apple-ios.mk               mips-unknown-linux-musl.mk        x86_64-unknown-linux-gnu.mk
armv7-unknown-linux-gnueabihf.mk  powerpc64le-unknown-linux-gnu.mk  x86_64-unknown-linux-musl.mk
i386-apple-ios.mk                 powerpc64-unknown-linux-gnu.mk    x86_64-unknown-netbsd.mk
i686-apple-darwin.mk              powerpc-unknown-linux-gnu.mk      x86_64-unknown-openbsd.mk
i686-linux-android.mk             x86_64-apple-darwin.mk
i686-pc-windows-gnu.mk            x86_64-apple-ios.mk

NOTE If your target is not supported by the RBS, then you'll need to add support for your target to it. I won't go over the details of adding support for a new target, but you can use this PR as a reference.

NOTE If you are doing bare metal programming, building your own kernel or, in general, working with #![no_std] code, then you probably don't want to (and probably can't because there is no OS) build all the standard crates, but just the core crate and other freestanding crates. If that's your case, read the Cross compiling no_std code section instead of this one.

The steps for cross compiling the standard crates are not complicated, but the process of building them does take a very long time because the RBS will bootstrap a new compiler, and then use that bootstrapped compiler to cross compile the crates. Hopefully, the upcoming cargo-based build system will open the possibility of making this much faster by letting you use your already installed rustc and cargo to cross compile the standard crates.

Back to the instructions, first you need to figure out the commit hash of your rustc. This is listed under the output of rustc -Vv. For example, this rustc:

$ rustc -Vv
rustc 1.8.0-nightly (3c9442fc5 2016-02-04)
binary: rustc
commit-hash: 3c9442fc503fe397b8d3495d5a7f9e599ad63cf6
commit-date: 2016-02-04
host: x86_64-unknown-linux-gnu
release: 1.8.0-nightly

Has commit hash: 3c9442fc503fe397b8d3495d5a7f9e599ad63cf6.

Next you need to fetch Rust source and check it out at that exact commit hash. Don't omit the checkout or you'll end with crates that are unusable by your compiler.

$ git clone https://github.com/rust-lang/rust
$ cd rust
$ git checkout $rustc_commit_hash
# Triple check the git checkout matches `rustc` commit hash
$ git rev-parse HEAD
$rustc_commit_hash

Next we prepare a build directory for an out of source build.

# Anywhere
$ mkdir build
$ cd build
$ /path/to/rust/configure --target=$rustc_target

configure accepts many other configuration flags, check out configure --help for more information. Do note that by default, i.e. without any flag, configure will prepare a fully optimized build.

Next we kick off the build:

$ make -j$(nproc)

If you hit this error during the build:

make[1]: $rbs_prefix-gcc: Command not found

Don't panic!

This happens because the RBS expects a gcc with a certain prefix for each target, but this prefix may not match the prefix of your installed cross compiler. For example, in my system, the installed cross compiler is armv7-unknown-linux-gnueabihf-gcc, but the RBS, when building for the arm-unknown-linux-gnueabihf target, expects the cross compiler to be named arm-none-gnueabihf-gcc.

This can be easily fixed with some shim binaries:

# In the build directory
$ mkdir .shims
$ cd .shims
$ ln -s $(which $gcc_prefix-ar) $rbs_prefix-ar
$ ln -s $(which $gcc_prefix-gcc) $rbs_prefix-gcc
$ cd ..
$ export PATH=$(pwd)/.shims:$PATH

Now you should be able to call both $gcc_prefix-gcc and $rbs_prefix-gcc. For example:

# My installed cross compiler
$ armv7-unknown-linux-gnueabihf-gcc -v
Using built-in specs.
COLLECT_GCC=armv7-unknown-linux-gnueabihf-gcc
COLLECT_LTO_WRAPPER=/usr/x86_64-pc-linux-gnu/libexec/gcc/armv7-unknown-linux-gnueabihf/5.3.0/lto-wrapper
Target: armv7-unknown-linux-gnueabihf
Configured with: (...)
Thread model: posix
gcc version 5.3.0 (GCC)

# The cross compiler that the RBS expects, which is supplied by the .shims directory
$ arm-linux-gnueabihf-gcc -v
Using built-in specs.
COLLECT_GCC=armv7-unknown-linux-gnueabihf-gcc
COLLECT_LTO_WRAPPER=/usr/x86_64-pc-linux-gnu/libexec/gcc/armv7-unknown-linux-gnueabihf/5.3.0/lto-wrapper
Target: armv7-unknown-linux-gnueabihf
Configured with: (...)
Thread model: posix
gcc version 5.3.0 (GCC)

You can now resume the build with make -j$(nproc).

Hopefully the build will complete successfully and your cross compiled crates will be available in the $host/stage2/lib/rustlib/$rustc_target/lib directory.

# In the build directory
$ ls x86_64-unknown-linux-gnu/stage2/lib/rustlib/arm-unknown-linux-gnueabihf/lib
liballoc-db5a760f.rlib           librand-db5a760f.rlib            stamp.arena
liballoc_jemalloc-db5a760f.rlib  librbml-db5a760f.rlib            stamp.collections
liballoc_system-db5a760f.rlib    librbml-db5a760f.so              stamp.core
libarena-db5a760f.rlib           librustc_bitflags-db5a760f.rlib  stamp.flate
libarena-db5a760f.so             librustc_unicode-db5a760f.rlib   stamp.getopts
libcollections-db5a760f.rlib     libserialize-db5a760f.rlib       stamp.graphviz
libcompiler-rt.a                 libserialize-db5a760f.so         stamp.libc
libcore-db5a760f.rlib            libstd-db5a760f.rlib             stamp.log
libflate-db5a760f.rlib           libstd-db5a760f.so               stamp.rand
libflate-db5a760f.so             libterm-db5a760f.rlib            stamp.rbml
libgetopts-db5a760f.rlib         libterm-db5a760f.so              stamp.rustc_bitflags
libgetopts-db5a760f.so           libtest-db5a760f.rlib            stamp.rustc_unicode
libgraphviz-db5a760f.rlib        libtest-db5a760f.so              stamp.serialize
libgraphviz-db5a760f.so          rustlib                          stamp.std
liblibc-db5a760f.rlib            stamp.alloc                      stamp.term
liblog-db5a760f.rlib             stamp.alloc_jemalloc             stamp.test
liblog-db5a760f.so               stamp.alloc_system

The next section will tell you how to install these crates in your Rust installation directory.

Installing the cross compiled standard crates

First, we need to take a closer look at your Rust installation directory, whose path you can get with rustc --print sysroot:

# I'm using rustup.rs, you'll get a different path if you used rustup.sh or your distro package
# manager to install Rust
$ tree -d $(rustc --print sysroot)
~/.multirust/toolchains/nightly
├── bin
├── etc
│   └── bash_completion.d
├── lib
│   └── rustlib
│       ├── etc
│       └── $host
│           └── lib
└── share
    ├── doc
    │   └── (...)
    ├── man
    │   └── man1
    └── zsh
        └── site-functions

See that lib/rustlib/$host directory? That's where your native crates are stored. The cross compiled crates must be installed right next to that directory. Following the example from the previous section, the following command will copy the standard crates built by the RBS in the right place.

# In the 'build' directory
$ cp -r \
    $host/stage2/lib/rustlib/$target
    $(rustc --print sysroot)/lib/rustlib

Finally, we check that the crates are in the right place.

$ tree $(rustc --print sysroot)/lib/rustlib
/home/japaric/.multirust/toolchains/nightly/lib/rustlib
├── (...)
├── uninstall.sh
├── $host
│  └── lib
│       ├── liballoc-fd663c41.rlib
│       ├── (...)
│       ├── libarena-fd663c41.so
│       └── (...)
└── $target
    └── lib
        ├── liballoc-fd663c41.rlib
        ├── (...)
        ├── libarena-fd663c41.so
        └── (...)

This way you can install crates for as many targets as you want. To "uninstall" the crates simply remove the $target directory.

Target specification files

A target specification file is a JSON file that provides detailed information about a target to the Rust compiler. This specification file has five required fields and several optional ones. All its keys are strings and its values are either strings or booleans. A minimal target spec file for Cortex M3 microcontrollers is shown below:

{
  "0": "NOTE: I'll use these 'numeric' fields as comments, but they shouldn't appear in these files",
  "1": "The next five fields are _required_",
  "arch": "arm",
  "llvm-target": "thumbv7m-none-eabi",
  "os": "none",
  "target-endian": "little",
  "target-pointer-width": "32",

  "2": "These fields are optional. Not all the possible optional fields are listed here, though",
  "cpu": "cortex-m3",
  "morestack": false
}

A list of all the possible keys and their effect on compilation can be found in the src/librustc_back/target/mod.rs file (NOTE: the linked file is not the latest revision).

There are two ways to pass these target specification files to rustc, the first is pass the full path via the --target flag.

$ rustc --target path/to/thumbv7m-none-eabi.json (...)

The other is to simply pass the "file stem" of the file to --target, but then the file must be in the working directory or in the directory specified by the RUST_TARGET_PATH variable.

# Target specification file is in the working directory
$ ls thumbv7m-none-eabi.json
thumbv7m-none-eabi.json

# Passing just the "file stem" works
$ rustc --target thumbv7m-none-eabi (...)

Cross compiling no_std code

When working with no_std code you only want a few freestanding crates like core, and you are probably working with a custom target, e.g. a Cortex-M microcontroller, so there are no official builds for your target nor can you build these crates using the RBS.

A simple solution to get a cross compiled core crate is to make your program/crate depend on the rust-libcore crate. This will make Cargo build the core crate as part of the cargo build process. However, this approach has two problems:

  • Virality: You can't make your crate depend on another no_std crate unless that crate also depends on rust-libcore.

  • If you want your crate to depend on another standard crate then a new rust-lib$crate crate would need to be created.

An alternative solution that doesn't have these problems is to use a "sysroot" that holds the cross compiled crates. I'm implementing this approach in xargo. For more details check the repository.

Troubleshooting common problems

Anything that can go wrong, will go wrong -- Murphy's law

This section: What to do when things go wrong.

can't find crate

Symptom

$ cargo build --target $rustc_target
error: can't find crate for `$crate`

Cause

rustc can't find the cross compiled standard crate $crate in your Rust installation directory.

Solution

Check the Installing the cross compiled standard crates section and make sure the cross compiled $crate crate is in the right place.

crate incompatible with this version of rustc

Symptom

$ cargo build --target $rustc_target
error: the crate `$crate` has been compiled with rustc $version-$channel ($hash $date), which is incompatible with this version of rustc

Cause

The version of the cross compiled standard crates that you installed don't match your rustc version.

Solution

If you are on the nightly channel and installed an official build, you probably got the date of the tarball wrong. Try a different date.

If you cross compiled the crates from source, then you checked out the wrong commit of the source. You'll have the build the crates again, but making sure you check out the repository at the right commit (it must match the commit-hash field of rustc -Vv output).

undefined reference

Symptom

$ cargo build --target $rustc_target
/path/to/some/file.c:$line: undefined reference to `$symbol`

Cause

The scenario goes like this:

  • The standard crates were cross compiled using a C cross toolchain "A".
  • Then you cross compile a Rust program using C cross toolchain "B", this program was also linked to the standard crates produced in the previous step.

The problem occurs when the libc component of toolchain "A" is newer than the libc component of toolchain "B". In this case, the standard crates cross compiled with "A" may depend on libc symbols that are not available in "B"'s libc.

This error will also occur if "A"'s libc is different from "B"'s libc. Example: toolchain "A" is mips-linux-gnu and toolchain "B" is mips-linux-musl.

Solution

If you observe this with a official build, that's a bug. It indicates that the Rust team must downgrade the libc component of the C cross toolchain they are using to build the standard crates.

If you are cross compiling the standard crates yourself, then it would be ideal if you use the same C cross toolchain to build the standard crates and to cross compile Rust programs.

can't load library

Symptom

# On target
$ ./hello
./hello: can't load library 'libpthread.so.0'

Cause

Your target system is missing a shared library. You can confirm this with ldd:

# Or `LD_TRACE_LOADED_OBJECTS=1 ./hello` on uClibc-based OpenWRT devices
$ ldd hello
        libdl.so.0 => /lib/libdl.so.0 (0x771ba000)
        libpthread.so.0 => not found
        libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x77196000)
        libc.so.0 => /lib/libc.so.0 (0x77129000)
        ld-uClibc.so.0 => /lib/ld-uClibc.so.0 (0x771ce000)
        libm.so.0 => /lib/libm.so.0 (0x77103000)

All the missing libraries are marked with "not found".

Solution

Install the missing shared libraries in your target system. Continuing the previous example:

# target system is an OpenWRT device
$ opkg install libpthread
$ ./hello
Hello, world!

$symbol not found

Symptom

# On target
$ ./hello
rustc: /path/to/$c_library.so: version `$symbol' not found (required by /path/to/$rust_library.so).

Cause

ABI mismatch between the library that was dynamically linked to the binary during cross compilation and the library that's installed in the target.

Solution

Update/change the library on either the host or the target to make them both ABI compatible. Ideally, the host and the target should have the same library version.

NOTE When I say the library on the host, I'm referring to the cross compiled library that the $prefix_gcc-gcc is linking into your Rust program. I'm not referring to the native library that may be installed in the host.

illegal instruction

Symptom

# on target
$ ./hello
Illegal instruction

Causes

NOTE You can also get an "illegal instruction" error if your program reaches an Out Of Memory (OOM) condition. In some systems, you will additionally see an "fatal runtime error: out of memory" message when you hit OOM. If you are sure that's not your case, then this is a cross compilation problem.

This occurs because your program contains an instruction that's not supported by your target system. Among the possible causes of this problem we have:

  • You are compiling for a hard float target, e.g. arm-unknown-linux-gnueabihf, but your target doesn't support hard float operations and it's actually a soft float target, e.g. arm-unknown-linux-gnueabi. Solution: Use the right triple, in this example: arm-unknown-linux-gnueabi.

  • You are using the right soft float triple, e.g. arm-unknown-linux-gnueabi, for your target system. But your C cross toolchain was compiled with hard float support and is injecting hard float instructions into your binary. Solution: Get the correct toolchain, one that was built with soft float support. Hint: look for the flag --with-float in the output of $gcc_prefix-gcc -v.

FAQ

I want to build binaries for Linux, Mac and Windows. How do I cross compile from Linux to Mac?

Short answer: You don't.

It's hard to find a cross C toolchain (and cross compiled C libraries) between different OSes (except perhaps from Linux to Windows). A much simpler and less error prone way is to build natively for these targets because they are tier 1 platforms. You may not have direct access to all these OSes but that's not a problem because you can use CI services like Travis CI and AppVeyor. Check my rust-everywhere project for instructions on how to do that.

How do I compile a fully statically linked Rust binaries?

Short answer: cargo build --target x86_64-unknown-linux-musl

For targets of the form *-*-linux-gnu*, rustc always produces binaries dynamically linked to glibc and other libraries:

$ cargo new --bin hello
$ cargo build --target x86_64-unknown-linux-gnu
$ file target/x86_64-unknown-linux-gnu/debug/hello
target/x86_64-unknown-linux-gnu/debug/hello: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /usr/x86_64-pc-linux-gnu/lib/ld-linux-x86-64.so.2, for GNU/Linux 2.6.34, BuildID[sha1]=a3fa7281e9ded30372b5131a2feb6f1e78a6f1cd, not stripped
$ ldd target/x86_64-unknown-linux-gnu/debug/hello
        linux-vdso.so.1 (0x00007fff58bf4000)
        libdl.so.2 => /usr/x86_64-pc-linux-gnu/lib/libdl.so.2 (0x00007fc4b2d3f000)
        libpthread.so.0 => /usr/x86_64-pc-linux-gnu/lib/libpthread.so.0 (0x00007fc4b2b22000)
        libgcc_s.so.1 => /usr/x86_64-pc-linux-gnu/lib/libgcc_s.so.1 (0x00007fc4b290c000)
        libc.so.6 => /usr/x86_64-pc-linux-gnu/lib/libc.so.6 (0x00007fc4b2568000)
        /usr/x86_64-pc-linux-gnu/lib/ld-linux-x86-64.so.2 (0x00007fc4b2f43000)
        libm.so.6 => /usr/x86_64-pc-linux-gnu/lib/libm.so.6 (0x00007fc4b2272000)

To produce statically linked binaries, Rust provides two targets: x86_64-unknown-linux-musl and i686-unknown-linux-musl. The binaries produced for these targets are statically linked to the MUSL C library. Example below:

$ cargo new --bin hello
$ cd hello
$ rustup target add x86_64-unknown-linux-musl
$ cargo build --target x86_64-unknown-linux-musl
$ file target/x86_64-unknown-linux-musl/debug/hello
target/x86_64-unknown-linux-musl/debug/hello: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), statically linked, BuildID[sha1]=759d41b9a78d86bff9b6529d12c8fd6b934c0088, not stripped
$ ldd target/x86_64-unknown-linux-musl/debug/hello
        not a dynamic executable

License

Licensed under either of

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

rust-cross's People

Contributors

alexcrichton avatar chareice avatar japaric avatar johnthagen avatar lu-zero avatar seeker14491 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

rust-cross's Issues

Cross compile fatal error: 'bits/libc-header-start.h' file not found

I am using the docker environment of debian 10 to cross-compile an Azure project. Everything worked fine in the front, but the following error occurred:
image
I used dpkg -S bits/libc-header-start.h and found that the file exists on my system and it doesn't seem to be recognized by cargo. I'm not familiar with rust. Can anyone help me solve this problem?

read-only file system

I'm not sure if this is a bug or a feature, but the tests which write to the file system don't work when I use rust-cross

# cross test --lib --target i686-unknown-linux-gnu
...
---- cmd::tests::test_fmt::test_fmt stdout ----
        thread 'cmd::tests::test_fmt::test_fmt' panicked at 'called `Result::unwrap()` on an `Err` value: Error(Io(Error { repr: Os { code: 30, message: "Read-only file system" } }), State { next_error: None })'
, /buildslave/rust-buildbot/slave/stable-dist-rustc-linux/build/src/libcore/result.rs:868
thread 'cmd::tests::test_fmt::test_fmt' panicked at 'called `Result::unwrap()` on an `Err` value: Error(Io(Error { repr: Os { code: 30, message: "Read-only file system" } }), State { next_error: None })', /build
slave/rust-buildbot/slave/stable-dist-rustc-linux/build/src/libcore/result.rs:868

openssl dependency

I need a few more steps to build a program depending on openssl-sys (via hyper). These are tested on archlinux:

  1. Fixing openssl/hmac.h not found: copying the target's /usr/include/openssl to /arm-gcc-prefix/include
  2. Fixing linking:
  • Copy the target's libssl.so, libcrypto.so, libz.so to /arm-gcc-prefix/lib
  • Explicitly link to libz, used by libcrypto:
cargo rustc --target=arm-unknown-linux-gnueabihf --release -- -lz -Clinker=arm-linux-gnueabihf-gcc

Cross-compiling from Linux to Mac

Your FAQ says "you don't", but it's totally feasible. It'd be nice to make this easier. I cross-compiled Servo from Linux to Mac:
https://gist.github.com/luser/a33e5070d1c55a7d2c46fe763a9d1543

You need:

  1. clang
  2. cctools (Apple's binutils)
  3. An OS X SDK, you can copy it off of a Mac (this part sucks)

The gist above pulls the first two from Mozilla's tooltool (a content store), and requires you to provide the third yourself.

Getting plain Rust code to build is pretty straightforward, but once you hit a crate with a native code dependency it gets a little tricky, hence most of the stuff in the gist.

I think it would be possible to build a Rust-only OS X SDK that's redistributable since it doesn't need header files, which would make this a lot easier.

Target triple for Windows

I am trying to set up cross-compilation for the first time, and the section “The target triple” seems to be missing some information if the target is a Windows system. More specifically, it says what to use as the vendor field, but not how to find out the architecture, system, or ABI fields. It would be very useful if information about this could be added.

Cross-compiling on windows: howto

Recently I want to compile something to a specific windows target. My development environment is Win10 64-bit, VS 2015 Update 3, with x86_64-pc-windows-msvc rustc/cargo/stdlib. I want to compile my crate for a 32-bit windows environment. Since VS contains both 32-bit and 64-bit linker, I think cross compiling from 64-bit Windows host to 32-bit Windows target is possible. However I don't find something helpful in this repository.

Since the purpose of this repository is

Everything you need to know about cross compiling Rust programs!

, I think adding some document will help those people who is in the same situation with me.

Cross-compiling from macOS to Windows

This article contains some information about how to build Windows binaries in macOS without an Windows environment (you need copy some libraries and header files from a Windows system which has VS/VC++ build tools installed, but don't need a Windows system to build binaries). Maybe we could write a tutorial about this? Actually, I think the steps described in the article also applies to building Windows binaries in Linux distributions.

PS: All files needed to be copied from the Windows environment (as described in the article) are:

  1. A part of WIndows 10 SDK (the import libraries of Win32 User Mode DLLs (um) and the static libraries and import libraries of the Universal C language RunTime (ucrt))
  2. Static libraries, import libraries, and object files of the MSVCRT, which is a part of the MSVC

The building process do not need MSVC (even the linker). All these files could be extracted from the Visual Studio Community version, which could be downloaded freely from the Microsoft official website. A bash/python/ruby script could do that easily and automatically. For the legit problem, I think the situation is basically same with installing Windows fonts in Wine. However, this needs to be confirmed.

x86_64-unknown-linux-musl does not always produce statically linked binaries

This text in the guide is incorrect:
"To produce statically linked binaries, Rust provides two targets: x86_64-unknown-linux-musl and i686-unknown-linux-musl. The binaries produced for these targets are statically linked to the MUSL C library."

The reality is more complex.

$ cargo build --target=x86_64-unknown-linux-musl
Finished dev [unoptimized + debuginfo] target(s) in 0.82s
$ ldd target/x86_64-unknown-linux-musl/debug/danish-rust
linux-vdso.so.1 (0x00007ffc876d5000)
libpcap.so.0.8 => /usr/lib/x86_64-linux-gnu/libpcap.so.0.8 (0x00007fef24af2000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fef24931000)
/lib/ld64.so.1 => /lib64/ld-linux-x86-64.so.2 (0x00007fef24d3f000)
$ file target/x86_64-unknown-linux-musl/debug/danish-rust
target/x86_64-unknown-linux-musl/debug/danish-rust: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib/ld64.so.1, BuildID[sha1]=c39a38306ce6f311f961c3477136f33c1b76bd10, with debug_info, not stripped

This is the project I'm compiling.
https://github.com/smutt/danish-rust

I suspect my problem is the dependency on libpcap. But I don't understand why this also results in libc being dynamically linked. What I would like to do either 1) produce a statically linked binary, or 2) dynamically link to libpcap on the target system.

Instructions for armv6 (Raspberry Pi 1 / Zero)

I could not find much information about how to cross compile Rust for armv6 in order to run on a Raspberry Pi 1 / Zero, so I wrote my own tutorial (in form of a Dockerfile): https://github.com/tiziano88/rust-raspberry-pi/blob/master/Dockerfile . The trick is really just to not use the gcc-arm-linux-gnueabihf package from Ubuntu, because that is tied to armv7. Would you like to somehow merge our instructions? I am happy to send you a PR for your readme adding a section on armv6 if you agree. Thanks for all the work on this!

Build Failed: openssl-sys

Not sure what I am doing wrong, but I can't get cross to work with openssl-sys crate.

I have tried both aarch64-unknown-linux-gnu and aarch64-unknown-linux-musl

Any suggestions?

cross build --target aarch64-unknown-linux-gnu
   Compiling openssl-sys v0.9.54
   Compiling sct v0.5.0
   Compiling webpki v0.19.1
   Compiling futures-util v0.3.4
   Compiling tokio-util v0.2.0
   Compiling serde_urlencoded v0.6.1
   Compiling serde_json v1.0.48
   Compiling failure v0.1.7
   Compiling uuid v0.7.4
   Compiling xsd-types v0.1.0 (https://github.com/lumeohq/xsd-parser-rs?rev=05cd3be1#05cd3be1)
   Compiling flexi_logger v0.15.2
   Compiling tokio v0.1.22
error: failed to run custom build command for `openssl-sys v0.9.54`

Caused by:
  process didn't exit successfully: `/target/debug/build/openssl-sys-5b14a6ca64ca7ff2/build-script-main` (exit code: 101)
--- stdout
cargo:rustc-cfg=const_fn
cargo:rerun-if-env-changed=AARCH64_UNKNOWN_LINUX_GNU_OPENSSL_LIB_DIR
AARCH64_UNKNOWN_LINUX_GNU_OPENSSL_LIB_DIR unset
cargo:rerun-if-env-changed=OPENSSL_LIB_DIR
OPENSSL_LIB_DIR unset
cargo:rerun-if-env-changed=AARCH64_UNKNOWN_LINUX_GNU_OPENSSL_INCLUDE_DIR
AARCH64_UNKNOWN_LINUX_GNU_OPENSSL_INCLUDE_DIR unset
cargo:rerun-if-env-changed=OPENSSL_INCLUDE_DIR
OPENSSL_INCLUDE_DIR unset
cargo:rerun-if-env-changed=AARCH64_UNKNOWN_LINUX_GNU_OPENSSL_DIR
AARCH64_UNKNOWN_LINUX_GNU_OPENSSL_DIR unset
cargo:rerun-if-env-changed=OPENSSL_DIR
OPENSSL_DIR unset
run pkg_config fail: "Cross compilation detected. Use PKG_CONFIG_ALLOW_CROSS=1 to override"

--- stderr
thread 'main' panicked at '

Could not find directory of OpenSSL installation, and this `-sys` crate cannot
proceed without this knowledge. If OpenSSL is installed and this crate had
trouble finding it,  you can set the `OPENSSL_DIR` environment variable for the
compilation process.

Make sure you also have the development packages of openssl installed.
For example, `libssl-dev` on Ubuntu or `openssl-devel` on Fedora.

If you're in a situation where you think the directory *should* be found
automatically, please open a bug at https://github.com/sfackler/rust-openssl
and include information about your system as well as this message.

$HOST = x86_64-unknown-linux-gnu
$TARGET = aarch64-unknown-linux-gnu
openssl-sys = 0.9.54

', /cargo/registry/src/github.com-1ecc6299db9ec823/openssl-sys-0.9.54/build/find_normal.rs:150:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

warning: build failed, waiting for other jobs to finish...
error: build failed

<3

@japaric, I just wanted to send you some love for this work. Wow. You've answered so many of my questions, saving me countless hours as well as for who knows how many others--thank you! ❤️

(Please feel free to close this "issue"...). 🥇

data-layout is required in the target specification file

The text says "The next five fields are required", giving arch, llvm-target, os, target-endian, target-pointer-width. But data-layout is also required.

By the way, how should one figure out the value of data-layout? ("Read LLVM source" is unsatisfactory.) A good method probably should be included in the text.

cross compilation from ubuntu linux to s390

I wrote a rust program 'rustest.rs' and cross-compiled it
rustc --target=s390x-unknown-linux-gnu -C linker=s390x-linux-gnu-gcc rustest.rs

fn main() {
println!("Hello, world!");
}

Following, copied it to target s390 machine, tried to execute it on target machine and got error
((zhangxq@dev))>./rustest
./rustest: /lib64/libc.so.6: version `GLIBC_2.18' not found (required by ./rustest)

So I compiled and installed glibc-2.18 on /opt/glibc-2.18 directory, and set it ad LD_LIBRARY_PATH,
but got error when executing the rust program.

((zhangxq@dev))>ll /opt/glibc-2.18/lib/libc.so.6
lrwxrwxrwx 1 root root 12 Apr 2 07:34 /opt/glibc-2.18/lib/libc.so.6 -> libc-2.18.so

((zhangxq@dev))>ldd rustest
./rustest: /lib64/libc.so.6: version `GLIBC_2.18' not found (required by ./rustest)
libdl.so.2 => /lib64/libdl.so.2 (0x000003ffba900000)
librt.so.1 => /lib64/librt.so.1 (0x000003ffba880000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x000003ffba800000)
libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x000003ffba780000)
libc.so.6 => /lib64/libc.so.6 (0x000003ffba580000)
/lib/ld64.so.1 (0x000002aa03680000)
((zhangxq@dev))>export LD_LIBRARY_PATH="/opt/glibc-2.18/lib"
((zhangxq@dev))>echo $LD_LIBRARY_PATH
/opt/glibc-2.18/lib
((zhangxq@dev))>./rustest
./rustest: : : Error 4396612874252

Fix if example code isn't woking

After following the examples I still was running into compilation errors because of these missing files
Scrt1.o: and crti.o`

It seemed I was missing g++ so I had to run the following apt-get

sudo apt-get install g++-arm-linux-gnueabihf

now you should be able to see the files in the right place with

find /usr -name crt1.o

travis: more examples

  • i686-pc-windows-gnu -- default mingw toolchain doesn't work, probably need to install a custom one
  • x86_64-pc-windows-gnu
  • mipsel-unknown-linux-musl.
  • i686-unknown-linux-musl -- waiting for std binaries

Missing header files when cross compiling to windows

When cross compiling to windows, you can run into problems if you depend on a package with C code, since when programming on windows the case of header files makes no difference but it does on windows.

I ran into this problem while using the nfs crate, which uses the header file ShObjIdl.h, but it is called shobjidl.h in the include files from the cross compiler. I believe it would be useful to add a note about this somewhere in the document.

rust cross compile to riscv64gc

I want help, please.
(0)This is my rustc:
rustc 1.34.0 (91856ed52 2019-04-10)

(1) I have installed riscv64gc-unknown-none-elf.
`hyb:~/Rust/riscv64$ rustup show
Default host: x86_64-unknown-linux-gnu

installed targets for active toolchain

armv7-unknown-linux-gnueabihf
riscv64gc-unknown-none-elf
x86_64-unknown-linux-gnu

active toolchain

stable-x86_64-unknown-linux-gnu (default)
rustc 1.34.0 (91856ed52 2019-04-10)
`
(2) This is my ~/.cargo/config

[target.riscv64gc-unknown-none-elf] linker="riscv64-unknown-elf-gcc"
(3) Then, i run this command
cargo build --target=riscv64gc-unknown-none-elf

(4)But it shows this:
Compiling riscv64 v0.1.0 (/home/hyb/Rust/riscv64) error[E0463]: can't find crate for std| = note: theriscv64gc-unknown-none-elf` target may not be installed

error: aborting due to previous error

For more information about this error, try rustc --explain E0463.
error: Could not compile riscv64.

To learn more, run the command again with --verbose.
`
I want to know why? linker or std or rustc version?

Can't compile for OpenWRT

Hi, I'm trying to cross compile a Rust app for LEDE (fork of OpenWRT) but I'm stuck.

The application is just an hello_world example:

fn main() {
    println!("Hello, world");
}

These are the steps I performed:

  1. In first place I downloaded the LEDE SDK and compiled successfully the image and the toolchain for my device (mips-openwrt-linux-musl-gcc).

  2. Install the Rust std using rustup add mips-unknown-linux-musl.

  3. Create a .cargo/config file in my project with the following content:

    [target.mips-unknown-linux-musl]
    linker = "mips-openwrt-linux-musl-gcc"
    
  4. Build the app using cargo build --release --target=mips-unknown-linux-musl.

  5. Deploy the executable to the device using scp.

  6. Got Illegal instruction

On target

$ ldd hello_world
/lib/ld-musl-mips-sf.so.1 (0x558c2000)                                                 
libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x77cc4000)                                       
libc.so => /lib/ld-musl-mips-sf.so.1 (0x558c2000)  

$ ldd --version
musl libc (mips-sf)
Version 1.1.15
Dynamic Program Loader
Usage: ldd [options] [--] pathname

On host

$ mips-openwrt-linux-musl-gcc -v
Reading specs from /opt/lede/staging_dir/toolchain-mips_mips32_gcc-5.4.0_musl-1.1.15/bin/../lib/gcc/mips-openwrt-linux-musl/5.4.0/specs
COLLECT_GCC=mips-openwrt-linux-musl-gcc
COLLECT_LTO_WRAPPER=/opt/lede/staging_dir/toolchain-mips_mips32_gcc-5.4.0_musl-1.1.15/bin/../libexec/gcc/mips-openwrt-linux-musl/5.4.0/lto-wrapper
Target: mips-openwrt-linux-musl
Configured with: /home/diego/source/build_dir/toolchain-mips_mips32_gcc-5.4.0_musl-1.1.15/gcc-5.4.0/configure --with-bugurl=http://www.lede-project.org/bugs/ --with-pkgversion='LEDE GCC 5.4.0 r2032' --prefix=/home/diego/source/staging_dir/toolchain-mips_mips32_gcc-5.4.0_musl-1.1.15 --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=mips-openwrt-linux-musl --with-gnu-ld --enable-target-optspace --disable-libgomp --disable-libmudflap --disable-multilib --disable-libmpx --disable-nls --without-isl --without-cloog --with-host-libstdcxx=-lstdc++ --with-float=soft --with-gmp=/home/diego/source/staging_dir/host --with-mpfr=/home/diego/source/staging_dir/host --with-mpc=/home/diego/source/staging_dir/host --disable-decimal-float --with-mips-plt --with-diagnostics-color=auto-if-env --disable-libssp --enable-__cxa_atexit --with-headers=/home/diego/source/staging_dir/toolchain-mips_mips32_gcc-5.4.0_musl-1.1.15/include --disable-libsanitizer --enable-languages=c,c++ --enable-shared --enable-threads --with-slibdir=/home/diego/source/staging_dir/toolchain-mips_mips32_gcc-5.4.0_musl-1.1.15/lib --enable-lto --with-libelf=/home/diego/source/staging_dir/host
Thread model: posix
gcc version 5.4.0 (LEDE GCC 5.4.0 r2032)

Disabling jemalloc

If I use rust nightly and disable jemalloc as following:

#![feature(alloc_system)]
extern crate alloc_system;

fn main() {
    println!("Hello, world");
}

Then it works! But as I keep adding code the application eventually crashes with another Illegal instruction. For example:

Works

TcpStream::connect("130.206.193.115:80").unwrap();

Does not work

TcpStream::connect("google.com:80").unwrap();'

I don't know what I'm doing wrong. Any help will be appreciated.

CloudABI support

Now that we have some more examples of building CloudABI Rust binaries, could rust-cross get CloudABI support as well?

Elaborate on ABI and gcc

Thank you for taking the time to create this awesome resource!

Here are two initial suggestions coming from the perspective of a programmer used to higher level languages:

  1. Please explain the significance and meaning of an ABI some more. It was not obvious to me that the whole (programming) world depends on libc. Why are there several libc implementations per platform? Also shouldn't the implementation be irrelevant at this stage because the libc interface is the same per platform (is it?).

  2. Why the sudden dependency on GCC in the rust toolchain? When learning rust it is explained that it uses llvm under the hood. This would imply the use of clang/lld , wouldn't it?

Cross compiling from Windows to Linux

Because of work I needed to switch to a Windows laptop and now look into a good way to build linux executables on Windows 10. Basicall I'd like to build the binaries in IntelliJ (or Visual Studio), so on Windows itself and not in the Linux Subsystem (which I could but then I'd have the wrong "environment" in my IntelliJ and would get suggestions for Windows instead of Linux specific features)

Now, I'm stuck on the "C cross toolchain": I've looked into crosstool-ng but that seems linux only. It also supports cygwin but that sounds a) like a very old method and b) looking at this stackoverflow thread sounds that I need to compile in the cygwin environment

On the other hand I found targeting the windows subsystem for Linux from Visual Studio which looks like it's going into the right direction but it's Visual Studio specific.

Generally I'm a bit lost as cross compilers are new ground for me. If anybody could just give me some directions I could figure out the nitty gritty details myself.

missing gcc-multilib

Hello,

i had to install: gcc-multilib

to fix the following errors:
/usr/bin/ld: cannot find Scrt1.o: No such file or directory
/usr/bin/ld: cannot find crti.o: No such file or directory
/usr/bin/ld: cannot find -lutil
/usr/bin/ld: cannot find -lutil
/usr/bin/ld: cannot find -ldl
/usr/bin/ld: cannot find -lrt
/usr/bin/ld: cannot find -lpthread
/usr/bin/ld: cannot find -lpthread
/usr/bin/ld: skipping incompatible /usr/lib/gcc/x86_64-linux-gnu/5/libgcc_s.so when searching for -lgcc_s
/usr/bin/ld: cannot find -lgcc_s
/usr/bin/ld: cannot find -lc
/usr/bin/ld: cannot find -lm
/usr/bin/ld: cannot find -lrt
/usr/bin/ld: cannot find -lpthread
/usr/bin/ld: cannot find -lutil
/usr/bin/ld: cannot find crtn.o

conttributing

I'd like to possibly contribute to this project - is it still actively maintained?

Can't install on Ubuntu 15.10

I'm on a rpi 1, so I am using the arm6... trying to otherwise follow along:

Following your "TL;DR Ubuntu example" in your README.md, when I get to

$ curl -sf https://raw.githubusercontent.com/brson/multirust/master/quick-install.sh | sh
$ sudo aptitude install gcc-arm-linux-gnueabi
$ multirust add-target nightly armv6-rpi-linux-gnueabi

leads to: multirust: toolchain 'nightly' is not installed; so I tried stable: multirust add-target stable armv6-rpi-linux-gnueabi
rustup: no channel manifest at '/home/mjf/.multirust/toolchains/stable/lib/rustlib/channel-manifest.toml'

I tried a few other variations: arm-rpi-linux-gnueabi arm-generic-linux-gnueabi, no go.

Thanks

Change default --target?

Is there any way to change the default compile target?

I've built a rustc that can compile to i586, but it still defaults to i686. I would like the default to be i586 because I have tooling that currently does not handle the target/i586-unknown-linux-gnu/xxx dir layout nicely.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.