#!/usr/bin/env bash set -e -x # Abort the script with an error message abort() { echo $1 >&2 exit 1 } # Extract some info from rustc rustc_info() { rustc -Vv | grep $1 | awk '{print $2}' } is_lib() { grep -q '\[lib\]' Cargo.toml || [ -e src/lib.rs ] } # Check that the rustc command exists command -v rustc > /dev/null || abort "rustc cannot be found on path" # Ensure that $ARCH has been specified [ -z $ARCH ] && abort 'no $ARCH specified' SOURCE_HOST=$(rustc_info "host") SOURCE_ARCH=$(echo $SOURCE_HOST | cut -d - -f 1) SOURCE_OS=$(echo $SOURCE_HOST | cut -d - -f 2-) TARGET_HOST=$ARCH-$SOURCE_OS RUSTC_ROOT=$(rustc --print sysroot) RUSTC_LIB="$RUSTC_ROOT/lib/rustlib" RUSTC_DATE=$(rustc_info "commit-date") BCK_FILE="Cargo.toml.cross-compile-bck" [ $ARCH != $SOURCE_ARCH ] && { # Ensure supported arch [[ "i686 x86_64" =~ $ARCH ]] || abort "unsuported ARCH $ARCH" # Make sure that the target arch's lib is present [ -d "$RUSTC_LIB/$TARGET_HOST" ] || { RELEASE=$(rustc_info "release") if echo $RELEASE | grep -q beta; then VERSION="beta" elif echo $RELEASE | grep -q nightly; then VERSION="nightly" else VERSION=$RELEASE fi DIST_URL=https://static.rust-lang.org/dist/rust-$VERSION-$TARGET_HOST.tar.gz RUST_STD=rust-std-$TARGET_HOST LIB_SUBDIR=lib/rustlib/$TARGET_HOST echo "Installing alternate rust for arch=$ARCH" # Download curl $DIST_URL | tar -zxf - pushd rust-$VERSION-$TARGET_HOST # If the new stdlib directory exists, copy files out of there, otherwise # fallback to the old location if [ -d "$RUST_STD" ]; then # rust-std-i686-unknown-linux-gnu/lib/rustlib/i686-unknown-linux-gnu/lib mv $RUST_STD/$LIB_SUBDIR $RUSTC_LIB/ else mv rustc/$LIB_SUBDIR $RUSTC_LIB/ fi popd } # Cargo does not currently support doc tests when cross compiling nor a way # to disable doc tests via the CLI, so doc tests must be disabled in the # manifest. # # The strategy is pretty hacky. If there is already a lib section, then just # add doctest=false to the section. If there is no lib section, then the # package name needs to be determined and a lib section created. # # See: rust-lang/cargo#1789 is_lib && { mv Cargo.toml $BCK_FILE if grep -q '\[lib\]' $BCK_FILE; then cat $BCK_FILE | grep -vE 'doctest *=' | # Remove the current doctest value awk '/\[lib\]/ { print; print "doctest=false"; next }1' > Cargo.toml else # First, extract the name of the lib, assume it is the first value LIB_NAME=$(cat $BCK_FILE | grep 'name *=' | head -n 1 | awk -F '"' '{print $2}') # Second, normalize the name by converting dashes to underscores. # This is required by the [lib] directive (see issue #4) LIB_NAME="$(echo "$LIB_NAME" | tr - _)" cp $BCK_FILE Cargo.toml echo "[lib]" >> Cargo.toml echo "name=\"$LIB_NAME\"" >> Cargo.toml echo "doctest=false" >> Cargo.toml fi } } reset_manifest() { if [ -e "$BCK_FILE" ]; then rm -f Cargo.toml mv $BCK_FILE Cargo.toml fi } # Finally run the tests cargo test $CARGOOPTS --target $TARGET_HOST || { reset_manifest exit 1 } reset_manifest