Linker = gcc-sysroot

#1

I am running into a problem that has me stumped. Rust programs, compiled under yocto, will compile without error and will compile properly for the target.

But when I have move the build outside of yocto, I am running into a hornet’s nest of problems.

The ‘linker’ (for yocto) specified in the rust .cargo/config is:

linker = "gcc-sysroot"

But outside yocto it will produce an error saying it can not find ‘gcc-sysroot’ (and there is no export for it). However there are exports for ${CC} and --sysroot.

One other problem is if I set my ‘default’ for cargo as ‘arm7-unknown-linux-gnueabihf’ (which I have specified in .cargo.config as [target.armv7-unknown-linux-gnueabihf]) it complains can not find the rustc version.

$ rustup default stable-armv7-unknown-linux-gnueabihf
info: using existing install for 'stable-armv7-unknown-linux-gnueabihf’
info: default toolchain set to 'stable-armv7-unknown-linux-gnueabihf’

stable-armv7-unknown-linux-gnueabihf unchanged - (error reading rustc version)

and

$ rustup show
Default host: x86_64-unknown-linux-gnu

installed toolchains
--------------------

stable-armv7-unknown-linux-gnueabihf (default)
stable-x86_64-unknown-linux-gnu

active toolchain
----------------

stable-armv7-unknown-linux-gnueabihf (default)
(error reading rustc version)

And then If I attempt

$ cargo build --target=armv7-unknown-linux-gnueabihf --release

/home//.rustup/toolchains/stable-armv7-unknown-linux-gnueabihf/bin/cargo: 1: /home//.rustup/toolchains/stable-armv7-unknown-linux-gnueabihf/bin/cargo: Syntax error: word unexpected (expecting “)”)

but if I rustup default stable-x86_64-unknown-linux-gnu. It will compile binaries for x86 and not my target which I would expect.

I am fairly new to rust. So if this seems like a noob question (it is !!!)

I feel it has something to do with defining ‘gcc-sysroot’ somewhere else.

#2

Hi!

I have a working workflow with and without yokto on armv7. I am building a shared library, and link it to specific versions of libc to get it working with multiple different environments.

First:
cargo does not look at {CC} at all. Of course, if your build.rs calls other build tools, these might use the {CC} environment variable to build code.

Also:
You probably don not want to set rustup default stable-armv7-unknown-linux-gnueabihf as default.
You have to know. that the llvm based rust compiler in comparison to e.g. gcc is a cross compiler by default.
rustup default stable-armv7-unknown-linux-gnueabihf will set the default toolchain. This toolchain however won`t be able to run on your host.
If you want to compile for arm you have to:

1.) Set back to default toolchain, which is able to run on your system

rustup default set stable-for-your-host-architecture

2.) Install rust standard libraries for architecture (note that the compiler itself already supports armv7 out of the box)

rustup target add armv7-unknown-linux-gnueabihf

3.) now edit .cargo/config:

[build]
# Set default build target to armv7hf
target = "armv7-unknown-linux-gnueabihf"

# Configure linker for your target
[target.armv7-unknown-linux-gnueabihf]
linker = "your-gcc-verion-for-armv7-with-sysroot"
 
#3

Thank you Roland.

OK. set it back to my host (an x86_64 box)

** $ rustup default stable-x86_64-unknown-linux-gnu **

$ rustup show
** Default host: x86_64-unknown-linux-gnu **

installed toolchains
--------------------

stable-armv7-unknown-linux-gnueabihf
stable-x86_64-unknown-linux-gnu (default)

installed targets for active toolchain
--------------------------------------

armv7-unknown-linux-gnueabihf
x86_64-unknown-linux-gnu

active toolchain
----------------

stable-x86_64-unknown-linux-gnu (default)
rustc 1.34.1 (fc50f328b 2019-04-24)

However now it seems the cross compiler has a problem complaining that ‘ld’ can not find some libraries during the build.

The error I see is:

= note: /opt/dey/2.2-r1/sysroots/x86_64-deysdk-linux/usr/libexec/arm-dey-linux-gnueabi/gcc/arm-dey-linux-gnueabi/6.2.0/real-ld: cannot find crti.o: No such file or directory
/opt/dey/2.2-r1/sysroots/x86_64-deysdk-linux/usr/libexec/arm-dey-linux-gnueabi/gcc/arm-dey-linux-gnueabi/6.2.0/real-ld: cannot find crtbeginS.o: No such file or directory
collect2: error: ld returned 1 exit status

error: aborting due to previous error

Sigh…

#4

One moment please, I have to remote login into my working PC. I can dig up an example there.

#5

Note, that I am using the arm-unknown-linux-gnueabihf rust target. There should not
be any issues with the armv7 one.

Okay, here is my .cargo/config:

[build]
target = "arm-unknown-linux-gnueabihf"

[target.arm-unknown-linux-gnueabihf]
linker = "arm-poky-linux-gnueabi-gcc"
ar = "arm-poky-linux-gnueabi-ar"

Cargo.toml:

[package]
...

[profile.release]
lto = true
codegen-units = 1

[lib]
crate-type = ["cdylib"]

...

External build tool (which calls cargo for me):
I converted it to a bash file for you, I can not really show you parts of the real build system.

#!/bin/bash
toolchain_sysroot= "/opt/poky/2.6.1/sysroots/armv7vet2hf-neon-poky-linux-gnueabi"
VERSION="x.x.x"
NAME="XXX"

# Import some enviroment setup from yokto
# This sets up PKG_CONFIG_PATH etc...

source /opt/poky/2.6.1/environment-setup-armv7vet2hf-neon-poky-linux-gnueabi

# Let cargo pass options to the C linker / compiler
# Sets --sysroot for arm-poky-linux-gnueabi-gcc invocation
# Also tweaks the SONAME in the elf file (for yokto style library versioning)
export RUSTFLAGS='-Clink-arg=-Wl,-soname=lib${NAME}.${VERSION} -Clink-arg=--sysroot=${toolchain_sysroot}'

# My crate uses the *cc* crate as a build dependency, which uses pkg-config to hunt down
# some native dependencies
export PKG_CONFIG_ALLOW_CROSS=1
cargo build --release --target=arm-unknown-linux-gnueabihf

# Some post processing / packaging stuff, not really interesting for you.,,

1 Like
#6

Again. Thank you Roland.

Now I am getting clean compiles. Turns out to be a little more simpler than that. But your answer provides most of the ‘meat’, and for my target there are some very slight differences.

My .cargo/config file had
linker ="gcc-sysroot’

After I invoked the ‘source …’ for my target build environment to get to the sdk’s sysroot.

Then I needed to create a ‘gcc-sysroot’ file in the /sysroot of the target’s sdk (this satisfied the cargo build error).

with the contents of

#!/bin/bash
SYSROOT=/opt/dey/2.2-r1/sysroots/cortexa9hf-neon-dey-linux-gnueabi
/opt/dey/2.2-r1/sysroots/x86_64-deysdk-linux/usr/bin/arm-dey-linux-gnueabi/arm-dey-linux-gnueabi-gcc --sysroot=SYSROOT (echo “$@” | sed ‘s/-L /usr/lib //g’)

This works, and what was missing. So now all the .cargo/config files can access the same SDK for the target, and the RUST compiles are completing and all I need is 'linker='gcc-sysroot" in the .cargo/config file.

Now the only mystery to solve is on the target and the rustlib dependencies for the executable(s).