Skip to content

Cross compiling Rust (1.37.0 and 1.38.0)

Niels Sascha Reedijk edited this page Mar 31, 2020 · 1 revision

Cross-compiling Rust for Haiku

The best (and maybe only) way to compile Rust for Haiku is to cross-compile. This page documents the way to prepare a cross-compilation environment, so that this can be repeated by other users.

Note: the changes with the previous build environment is that the config.toml is changed to work around rust issue #62558 which makes it impossible to cross-compile rustfmt, clippy and rls.

Setting up the cross-compilation environment

  • The basis for cross-compiling Rust is running Haiku R1 Beta 1.
  • These instructions are based on jessicah's work on dockerizing Haiku builds. See this post

Get the source

Start in a work dir, which we will call WORKDIR here (for me it is /mnt/d/Haiku/)

git clone https://git.haiku-os.org/haiku
cd haiku
git checkout r1beta1
cd ..
git clone https://git.haiku-os.org/buildtools
git checkout btrev43136 # I use this revision
git revert -m 1 35041506a03bcbe38eafdd7cbffba4111c838fdc # revert to binutils 2.16.1. The newer version crashes when linking rust and llvm


cd .. #back in the work dir

Build the cross-compiler and haiku for x86

mkdir build-r1beta1-x86 && cd build-r1beta1-x86
../haiku/configure --build-cross-tools x86_gcc2 ../buildtools --build-cross-tools x86
 jam -q haiku.hpkg haiku_devel.hpkg '<build>package' haiku_x86.hpkg haiku_x86_devel.hpkg
cd .. #back in the work dir

Build the cross-compiler and haiku for x86_64

mkdir build-r1beta1-x86-64 && cd build-r1beta1-x86-64
../haiku/configure --build-cross-tools x86_64 ../buildtools
 jam -q haiku.hpkg haiku_devel.hpkg '<build>package'
cd .. #back in the work dir

Extract the package tool and install it locally

We also extract the package tool and place it in the $HOME/bin directory (so it can be found in path) including libraries that depend on it. On my system the search path does not include the place of the executable, so I do need to explicitly call LD_LIBARY_PATH when running package below.

cp build-r1beta1-x86/objects/linux/x86_64/release/tools/package/package ~/bin/
cp build-r1beta1-x86/objects/linux/lib/* ~/bin

Set up the x86 sysroot

The compiler finds the Haiku files in the sysroot. The sysroot is hardcoded to be the sysroot directory in the place where the compiled cross-tools can be found. I chose to put the packages in a different location, and link these into the sysroot. This is a stylistic choice: the packages could be unpacked directly under build-r1beta1-x86/cross-tools-x86/sysroot/boot.

We also create links to the gcc x86 (not x86_gcc2!) toolset in ~/bin

# create dirs
mkdir build-r1beta1-x86/cross-tools-x86/sysroot
mkdir build-r1beta1-x86/cross-tools-x86/sysroot/boot
mkdir system-r1beta1-x86
ln -s `pwd`/system-r1beta1-x86 build-r1beta1-x86/cross-tools-x86/sysroot/boot/system

# create links to the compiler
find `pwd`/build-r1beta1-x86/cross-tools-x86/bin/ -type f -exec ln -s {} ~/bin/ \;

# get additional required packages
wget https://eu.hpkg.haiku-os.org/haikuports/r1beta1/x86_gcc2/current/packages/openssl_x86-1.0.2q-1-x86_gcc2.hpkg -P system-r1beta1-x86/download
wget https://eu.hpkg.haiku-os.org/haikuports/r1beta1/x86_gcc2/current/packages/openssl_x86_devel-1.0.2q-1-x86_gcc2.hpkg -P system-r1beta1-x86/download

# extract packages
LD_LIBRARY_PATH=~/bin package extract -C system-r1beta1-x86/ build-r1beta1-x86/objects/haiku/x86_gcc2/packaging/packages/haiku.hpkg
LD_LIBRARY_PATH=~/bin package extract -C system-r1beta1-x86/ build-r1beta1-x86/objects/haiku/x86_gcc2/packaging/packages/haiku_devel.hpkg
LD_LIBRARY_PATH=~/bin package extract -C system-r1beta1-x86/ build-r1beta1-x86/objects/haiku/x86_gcc2/packaging/packages/haiku_x86.hpkg
LD_LIBRARY_PATH=~/bin find build-r1beta1-x86/download/ -name "*.hpkg" -exec package
extract -C system-r1beta1-x86/ {} \;

# Fix libgcc_s and other libraries so we can link to it
cd system-r1beta1-x86/develop/lib/x86
ln -s ../../../lib/x86/libgcc_s.so libgcc_s.so
ln -s ../../../lib/x86/libgcc_s.so.1 libgcc_s.so.1
rm libroot.so && ln -s ../../../lib/x86/libroot.so  libroot.so
rm libbsd.so && ln -s ../../../lib/x86/libbsd.so libbsd.so
rm libnetwork.so && ln -s ../../../lib/x86/libnetwork.so libnetwork.so

# Fix sysexits.h, comment out line 38 (#ifdef _BSD_SOURCE) and line 121 (#endif)
cd ../../headers/bsd/
vi sysexits.h

# return to the start dir
cd ../../../..

Set up the x86_64 sysroot

Like the previous sysroot

# create dirs
mkdir build-r1beta1-x86_64/cross-tools-x86_64/sysroot
mkdir build-r1beta1-x86_64/cross-tools-x86_64/sysroot/boot
mkdir system-r1beta1-x86_64
ln -s `pwd`/system-r1beta1-x86_64 build-r1beta1-x86_64/cross-tools-x86_64/sysroot/boot/system

# create links to the compiler
find `pwd`/build-r1beta1-x86_64/cross-tools-x86_64/bin/ -type f -exec ln -s {} ~/bin/ \;

# get additional required packages
wget https://eu.hpkg.haiku-os.org/haikuports/r1beta1/x86_64/current/packages/openssl-1.0.2q-1-x86_64.hpkg -P build-r1beta1-x86_64/download/
wget https://eu.hpkg.haiku-os.org/haikuports/r1beta1/x86_64/current/packages/openssl_devel-1.0.2q-1-x86_64.hpkg -P build-r1beta1-x86_64/download/

# extract packages
LD_LIBRARY_PATH=~/bin package extract -C system-r1beta1-x86_64/ build-r1beta1-x86_64/objects/haiku/x86_64/packaging/packages/haiku.hpkg
LD_LIBRARY_PATH=~/bin package extract -C system-r1beta1-x86_64/ build-r1beta1-x86_64/objects/haiku/x86_64/packaging/packages/haiku_devel.hpkg
LD_LIBRARY_PATH=~/bin find build-r1beta1-x86_64/download/ -name "*.hpkg" -exec package extract -C system-r1beta1-x86_64/ {} \;

# Fix libgcc_s so we can link to it
cd system-r1beta1-x86_64/develop/lib/
ln -s ../../lib/libgcc_s.so libgcc_s.so
rm libroot.so && ln -s ../../libroot.so libroot.so
rm libbsd.so && ln -s ../../libbsd.so libbsd.so
rm libnetwork.so && ln -s ../../libnetwork.so libnetwork.so

# Fix sysexits.h, comment out line 38 (#ifdef _BSD_SOURCE) and line 121 (#endif)
cd ../../headers/bsd/
vi sysexits.h

# return to the start dir
cd ../../..

Preparing special dependencies

There might be some Rust dependencies that need to be patched before they can be used. To patch them, we make a local checkout of the source of the package, and then alter the source, and then add it to ~/.cargo/config under the paths directive, so that Cargo will pick up our customized package.

That ~/.cargo/config will have at least the following line:

paths = ["/mnt/d/Rust/libz-sys"]

Libz-sys

There is an issue with linking libz-sys into the cargo binary during the build process. The linker complains about a hidden symbol that is referenced by a DSO (dynamic shared object). I don't know what the issue is, or why this is specifically an issue for Haiku. We solve it by having the build script of libz-sys expose all symbols.

To get the source, do the following:

cd /mnt/d/Rust   # or wherever you want to keep your customized packages
git clone https://github.com/alexcrichton/libz-sys
cd libz-sys
git checkout 1.0.22
git submodule init && git submodule update

Then open the build.rs file and comment out line 103 so that it reads:

    if !target.contains("windows") {
        cfg.define("STDC", None);
        cfg.define("_LARGEFILE64_SOURCE", None);
        cfg.define("_POSIX_SOURCE", None);
 //       cfg.flag("-fvisibility=hidden");
    }

Getting the Rust source

Get the modified Rust repository from github.

git clone https://github.com/nielx/rust rust-haiku
cd rust-haiku
git checkout rust-haiku-1.38.0 # see other options below

Available tags and branches for this configuration:

  • rust-haiku-1.37.0
  • rust-haiku-1.38.0

Configuration

Place the following configuration as config.toml in the root of the Rust source.

[llvm]
targets = "X86"
experimental-targets = ""

[build]
host = ["i686-unknown-haiku", "x86_64-unknown-haiku"]
target = ["i686-unknown-haiku", "x86_64-unknown-haiku"]
extended = true
verbose = 2
tools = ["cargo"]

[install]
prefix = "/boot/system"

[rust]
channel = "stable"
rpath = false
deny-warnings = false

[target.i686-unknown-haiku]
cc = "i586-pc-haiku-gcc"
cxx = "i586-pc-haiku-g++"
ar = "i586-pc-haiku-ar"
linker = "i586-pc-haiku-gcc"

[target.x86_64-unknown-haiku]
cc = "x86_64-unknown-haiku-gcc"
cxx = "x86_64-unknown-haiku-g++"
ar = "x86_64-unknown-haiku-ar"
linker = "x86_64-unknown-haiku-gcc"

[dist]
missing-tools = true

WARNING: Rust 1.37.0 and up has a known issue where the tools rls, clippy and rustfmt do not cross-compile. In the configuration (above) you need to set tools to ['cargo'] only, and we add the missing-tools option to tell the build system to continue compiling even when individual tools fail.

Building Rust

After all the preparations it is time to build rust. For a full overview of Rust build instructions, see the Readme's and the source. This page will show the specifics needed for cross-compilation.

The customized environment variables needed to build are:

  • *_OPENSSL_LIB_DIR needs to point to the location of the openssl libraries within our Haiku build system for each platform.
  • *_OPENSSL_INCLUDE_DIR needs to point to the location of the openssl headers within our Haiku build system for each platform.

That makes my invocation for the x.py script look as follows:

I686_UNKNOWN_HAIKU_OPENSSL_LIB_DIR=/mnt/d/Haiku/system-r1beta1-x86/develop/lib/x86 \
I686_UNKNOWN_HAIKU_OPENSSL_INCLUDE_DIR=/mnt/d/Haiku/system-r1beta1-x86/develop/headers/ \
X86_64_UNKNOWN_HAIKU_OPENSSL_LIB_DIR=/mnt/d/Haiku/system-r1beta1-x86_64/develop/lib/ \
X86_64_UNKNOWN_HAIKU_OPENSSL_INCLUDE_DIR=/mnt/d/Haiku/system-r1beta1-x86_64/develop/headers/ \
./x.py dist