Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

upon cross-compiling with emerge-cross-wrappers #394

Open
stefson opened this issue Mar 12, 2019 · 14 comments
Open

upon cross-compiling with emerge-cross-wrappers #394

stefson opened this issue Mar 12, 2019 · 14 comments

Comments

@stefson
Copy link
Contributor

stefson commented Mar 12, 2019

recently I did some research into how to to use rust and cargo to cross-compile, especially for armhf.

I found out, it's rather easy to set up rust for that: if rust-bin is your rust-provider, download rust-std-${PN}-${ARCH-TRIPLE}.tar.xz and install it with: ./install.sh --disable-verify --prefix=/opt/${P}/ --mandir="/usr/share/${P}/man" --disable-ldconfig

which gives you a rust-bin with the ability to cross-compile. (since rustc is more or less a frontend to llvm, you should have it emerged with llvm_target_arm?)

also emerge a full cross toolchain with crossdev, since rustc needs the cross-gcc as a linker.

now, it is common practice to cross-compile with emerge-wrappers, so an emerge-armv7a-unknown-linux-gnueabihf -auvND world should bootstrap a base cross system to work with, inheriting @System, and from there on it should be possible to compile individual packages and copy the tbz2 files from the cross environement over to the memory restrained arm device and emerge with the -k option to grab a binary if possible. Done that with sys-devel/gcc, sys-devel/llvm, dev-libs/boost, etc. pp.

Now, with a host where rustc has the foreign rust-std installed it should just work to emerge, for instance, dev-util/cbindgen this way. It does, however, with a bit of a show stopper:

>>> Completed installing cbindgen-0.6.7 into /usr/armv7a-unknown-linux-gnueabihf/tmp/portage/dev-util/cbindgen-0.6.7/image

 * Final size of build directory: 188124 KiB (183.7 MiB)
 * Final size of installed tree:    8072 KiB (  7.8 MiB)

strip: armv7a-unknown-linux-gnueabihf-strip --strip-unneeded -R .comment -R .GCC.command.line -R .note.gnu.gold-version
   /usr/bin/cbindgen
armv7a-unknown-linux-gnueabihf-strip:/usr/armv7a-unknown-linux-gnueabihf/tmp/portage/dev-util/cbindgen-0.6.7/image/usr/bin/cbindgen: file format not recognized
./
./usr/
./usr/bin/
./usr/bin/cbindgen
>>> Done.

the binary is in fact not a cross-compiled one, but for the hosts arch, thus cross-strip can't do anything about it.

@stefson
Copy link
Contributor Author

stefson commented Mar 12, 2019

The build.log itself isn't very usefull, as it hides the actuall compile commands from the user. Therefore, the first thing to do in an attempt to debug this is, to reenable cargo build -v in the cargo.eclass in the local portage tree:

    cargo: reenable cargo build -v for debugging

diff --git a/eclass/cargo.eclass b/eclass/cargo.eclass
index 051d5c499a6..8e92cb86277 100644
--- a/eclass/cargo.eclass
+++ b/eclass/cargo.eclass
@@ -122,7 +122,7 @@ cargo_src_compile() {
 
        export CARGO_HOME="${ECARGO_HOME}"
 
-       cargo build -j $(makeopts_jobs) $(usex debug "" --release) "$@" \
+       cargo build -v -j $(makeopts_jobs) $(usex debug "" --release) "$@" \
                || die "cargo build failed"
 }

which gives a more verbose build.log to read through: cbindgen-0.6.7-cross.log.zip

@stefson
Copy link
Contributor Author

stefson commented Mar 12, 2019

next step would be to find out, wether a build outside of portage would work: I copied the folder src and Cargo.toml from /var/tmp/portage/dev-util/cbindgen-0.6.7/work/cbindgen-0.6.7/ to temporary folder, entered it via the cmd line and made it compile via cargo build --target=armv7-unknown-linux-gnueabihf

here is the build log of that approach: cbindgen-0.6.7-cross-non-portage.log.zip

which gives a valid arm binary: file cbindgen
cbindgen: ELF 32-bit LSB pie executable, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-armhf.so.3, for GNU/Linux 3.2.0, with debug_info, not stripped

which can be striped with cross-strip: file cbindgen
cbindgen: ELF 32-bit LSB pie executable, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-armhf.so.3, for GNU/Linux 3.2.0, stripped

@stefson
Copy link
Contributor Author

stefson commented Mar 12, 2019

one smoking gun I found is, that upon linking during cross-compile cargo has to be told about where the cross-gcc is to be found via ~/.cargo/config

[target.armv7-unknown-linux-gnueabihf] linker = "armv7a-unknown-linux-gnueabihf-gcc"

otherwise the non-portage build would flake out with error: linking with `cc` failed: exit code: 1

and it seems to me that portage sets its own cargo home config during each install, which makes sense as emerge is run via the the user/group portage:portage, and it doesn't have a folder in /home/

but, to be honest, I think the first problem here is that portage doesn't invoke rustc with the correct --target option at all, but simply issues the native rustc command.

How may I change this behavior, for to emerge the package with cross-portage?

@stefson
Copy link
Contributor Author

stefson commented Mar 12, 2019

ok, we're getting closer as I switched on --target option via the cargo.eclass


diff --git a/eclass/cargo.eclass b/eclass/cargo.eclass
index 8e92cb86277..b4b5d86ffcb 100644
--- a/eclass/cargo.eclass
+++ b/eclass/cargo.eclass
@@ -122,7 +122,7 @@ cargo_src_compile() {
 
        export CARGO_HOME="${ECARGO_HOME}"
 
-       cargo build -v -j $(makeopts_jobs) $(usex debug "" --release) "$@" \
+       cargo build -v --target=armv7-unknown-linux-gnueabihf -j $(makeopts_jobs) $(usex debug "" --release) "$@" \
                || die "cargo build failed"
 }

This is of course very unsophisticated, needs more general approach if ever going to the overlay or the tree even. But it makes emerge run into the linker errors, as it should when picking native gcc to link a foreign binary, which shows that cross-compile has happened at some point:

error: linking with `cc` failed: exit code: 1 full log

@stefson
Copy link
Contributor Author

stefson commented Mar 12, 2019

Ok, so let's set up the linker as well:


diff --git a/eclass/cargo.eclass b/eclass/cargo.eclass
index b4b5d86ffcb..73f0dcad9cd 100644
--- a/eclass/cargo.eclass
+++ b/eclass/cargo.eclass
@@ -111,6 +111,10 @@ cargo_gen_config() {
        [source.crates-io]
        replace-with = "gentoo"
        local-registry = "/nonexistant"
+
+       [target.armv7-unknown-linux-gnueabihf]
+       linker = "armv7a-unknown-linux-gnueabihf-gcc"
+
        EOF
 }

this solves the linking error, but still emerge installs the native binary in src_install.

>>> Completed installing cbindgen-0.6.7 into /usr/armv7a-unknown-linux-gnueabihf/tmp/portage/dev-util/cbindgen-0.6.7/image

 * Final size of build directory: 237468 KiB (231.9 MiB)
 * Final size of installed tree:    8072 KiB (  7.8 MiB)

strip: armv7a-unknown-linux-gnueabihf-strip --strip-unneeded -R .comment -R .GCC.command.line -R .note.gnu.gold-version
   /usr/bin/cbindgen
armv7a-unknown-linux-gnueabihf-strip:/usr/armv7a-unknown-linux-gnueabihf/tmp/portage/dev-util/cbindgen-0.6.7/image/usr/bin/cbindgen: file format not recognized
./
./usr/
./usr/bin/
./usr/bin/cbindgen
>>> Done.

@stefson
Copy link
Contributor Author

stefson commented Mar 12, 2019

portage acutally ends up with two binaries now, one native and one cross-compiled one, in seperate folders:

user@tuxbox /usr/armv7a-unknown-linux-gnueabihf/tmp/portage/dev-util/cbindgen-0.6.7/work/cbindgen-0.6.7/target/release $ file cbindgen
cbindgen: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, with debug_info, not stripped

user@tuxbox /usr/armv7a-unknown-linux-gnueabihf/tmp/portage/dev-util/cbindgen-0.6.7/work/cbindgen-0.6.7/target/armv7-unknown-linux-gnueabihf/release $ file cbindgen
cbindgen: ELF 32-bit LSB pie executable, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-armhf.so.3, for GNU/Linux 3.2.0, with debug_info, not stripped

@stefson
Copy link
Contributor Author

stefson commented Mar 12, 2019

Ok, finally got there: rust-lang/cargo#5614 added an option to enable cargo install --target

diff --git a/eclass/cargo.eclass b/eclass/cargo.eclass
index 73f0dcad9cd..75e7f0cf388 100644
--- a/eclass/cargo.eclass
+++ b/eclass/cargo.eclass
@@ -136,7 +136,7 @@ cargo_src_compile() {
 cargo_src_install() {
        debug-print-function ${FUNCNAME} "$@"
 
-       cargo install -j $(makeopts_jobs) --root="${D}/usr" $(usex debug --debug "") "$@" \
+       cargo install --target=armv7-unknown-linux-gnueabihf -j $(makeopts_jobs) --root="${D}/usr" $(usex debug --debug "") "$@" \
                || die "cargo install failed"
        rm -f "${D}/usr/.crates.toml"

@stefson
Copy link
Contributor Author

stefson commented Mar 19, 2019

@l29ah
Copy link

l29ah commented Feb 27, 2020

Do you plan producing thumb targets for rust-std? Also why haven't you pushed it into ::rust?

@stefson
Copy link
Contributor Author

stefson commented Feb 27, 2020

how can you not see the thumb code in the ebuild? https://github.com/gentoo/gentoo-rust/blob/master/dev-lang/rust/rust-1.41.0-r666.ebuild#L102

@l29ah
Copy link

l29ah commented Feb 27, 2020

The ebuild requires you to be on an arm arch or otherwise have arm-none-eabi-gcc to build it.
I mean https://github.com/stefson/gentoo-extras/blob/master/dev-lang/rust-std/rust-std-1.41.0.ebuild

@stefson
Copy link
Contributor Author

stefson commented Feb 27, 2020

You're welcome to use my overlay if you want to, the thumb target is in an extra package named rust-std-neon since I couldn't find a way to make my rust-std ebuild installing both armv7 and thumbv7neon on an amd64 host. You'll need both of them for cross compiling firefox.

Actually I don't think you'll need arm-none-eabi-gcc for compiling the thumbv7neon target. Where did you get that information from?

@l29ah
Copy link

l29ah commented Feb 27, 2020 via email

@stefson
Copy link
Contributor Author

stefson commented Feb 28, 2020

bootstrapping additional rust-std from source requires you to have a suitable gcc cross compiler at hand for linking, and yes some of the crates are so stupid to only look for gcc name paterns matching those of debian based distros. You have no choice but to symlink your own cross compiler to the debian name scheme.

That said, please take the ebuild and modify it for your own case. You're not presenting any usefull information to me for helping you with that. Thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants