diff --git a/.travis.yml b/.travis.yml index c0fd80ab64..67668a1d89 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,37 +1,57 @@ ---- -sudo: false language: rust +sudo: required +dist: trusty +services: + - docker + rust: - 1.1.0 # Oldest supported version - - 1.2.0 - - 1.3.0 - - 1.4.0 - - 1.5.0 - stable - beta - nightly -# Failures on nightly shouldn't fail the overall build. -matrix: - allow_failures: - - rust: nightly +script: + - bash ci/run-travis.sh + +env: + - ARCH=x86_64 os: - linux - osx -env: - - RUST_TEST_THREADS=1 ARCH=x86_64 - - RUST_TEST_THREADS=1 ARCH=i686 - -script: - - curl -sSL https://raw.githubusercontent.com/carllerche/travis-rust-matrix/master/test | RUST_TEST_THREADS=1 bash - - cargo doc --no-deps - -addons: - apt: - packages: - - gcc-multilib +# Failures on nightly shouldn't fail the overall build. +matrix: + fast_finish: true + include: + - os: linux + env: ARCH=i686 + rust: stable + - os: osx + env: ARCH=i686 + rust: stable + - os: linux + env: TARGET=aarch64-unknown-linux-gnu DOCKER_IMAGE=posborne/rust-cross:arm + rust: 1.7.0 + - os: linux + env: TARGET=arm-unknown-linux-gnueabihf DOCKER_IMAGE=posborne/rust-cross:arm + rust: 1.7.0 + - os: linux + env: TARGET=mips-unknown-linux-gnu DOCKER_IMAGE=posborne/rust-cross:mips + rust: 1.7.0 + - os: linux + env: TARGET=mipsel-unknwon-linux-gnu DOCKER_IMAGE=posborne/rust-cross:mips + rust: 1.7.0 + - os: linux + env: TARGET=arm-linux-androideabi DOCKER_IMAGE=posborne/rust-cross:android + rust: 1.7.0 + allow_failures: + - rust: nightly + - env: TARGET=aarch64-unknown-linux-gnu DOCKER_IMAGE=posborne/rust-cross:arm + - env: TARGET=arm-unknown-linux-gnueabihf DOCKER_IMAGE=posborne/rust-cross:arm + - env: TARGET=mips-unknown-linux-gnu DOCKER_IMAGE=posborne/rust-cross:mips + - env: TARGET=mipsel-unknwon-linux-gnu DOCKER_IMAGE=posborne/rust-cross:mips + - env: TARGET=arm-linux-androideabi DOCKER_IMAGE=posborne/rust-cross:android # Deploy documentation to S3 for specific branches. At some # point, it would be nice to also support building docs for diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 3224ad2a29..80c2f04c46 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -72,8 +72,11 @@ environment. We also have [continuous integration set up on Travis-CI][travis-ci], which might find some issues on other platforms. The CI will run once you open a pull request. -[travis-ci]: https://travis-ci.org/nix-rust/nix +There is also infrastructure for running tests for other targets +locally. More information is available in the [CI Readme][ci-readme]. +[travis-ci]: https://travis-ci.org/nix-rust/nix +[ci-readme]: ci/README.md ## Homu, the bot who merges all the PRs diff --git a/README.md b/README.md index da81ed19ce..d10bc0eea0 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ To use `nix`, first add this to your `Cargo.toml`: ```toml [dependencies] -nix = "*" +nix = "0.5.0" ``` Then, add this to your crate root: diff --git a/ci/README.md b/ci/README.md new file mode 100644 index 0000000000..c86fd7157d --- /dev/null +++ b/ci/README.md @@ -0,0 +1,48 @@ +Test Infrastructure +=================== + +The ci directory contains scripts that aid in the testing of nix both +in our continuous integration environment (Travis CI) but also for +developers working locally. + +Nix interfaces very directly with the underlying platform (usually via +libc) and changes need to be tested on a large number of platforms to +avoid problems. + +Running Tests For Host Architecture +----------------------------------- + +Running the tests for one's host architecture can be done by simply +doing the following: + + $ cargo test + +Running Tests Against All Architectures/Versions +------------------------------------------------ + +Testing for other architectures is more involved. Currently, +developers may run tests against several architectures and versions of +rust by running the `ci/run-all.sh` script. This scripts requires +that docker be set up. This will take some time: + + $ ci/run-all.sh + +The list of versions and architectures tested by this can be +determined by looking at the contents of the script. The docker image +used is [posborne/rust-cross][posborne/rust-cross]. + +[posborne/rust-cross]: https://github.com/rust-embedded/docker-rust-cross + +Running Test for Specific Architectures/Versions +------------------------------------------------ + +Suppose we have a failing test with Rust 1.7 on the raspberry pi. In +that case, we can run the following: + + $ DOCKER_IMAGE=posborne/rust-cross:arm \ + RUST_VERSION=1.7.0 \ + RUST_TARGET=arm-unknown-linux-gnueabihf ci/run-docker.sh + +Currently, the docker images only support Rust 1.7. To get a better +idea of combinations that might work, look at the contents of the +[travis configuration](../.travis.yml) or [run-all.sh](run-all.sh). diff --git a/ci/cargo-config b/ci/cargo-config new file mode 100644 index 0000000000..6fee5be7a8 --- /dev/null +++ b/ci/cargo-config @@ -0,0 +1,18 @@ +# Configuration of which linkers to call on Travis for various architectures +[target.arm-linux-androideabi] +linker = "arm-linux-androideabi-gcc" + +[target.arm-unknown-linux-gnueabihf] +linker = "arm-linux-gnueabihf-gcc-4.7" + +[target.mips-unknown-linux-gnu] +linker = "mips-linux-gnu-gcc-5" + +[target.mipsel-unknown-linux-gnu] +linker = "mipsel-linux-gnu-gcc-5" + +[target.aarch64-unknown-linux-gnu] +linker = "aarch64-linux-gnu-gcc-4.8" + +[target.powerpc-unknown-linux-gnu] +linker = "powerpc-linux-gnu-gcc-4.8" diff --git a/ci/run-all.sh b/ci/run-all.sh new file mode 100755 index 0000000000..5c38ca7f76 --- /dev/null +++ b/ci/run-all.sh @@ -0,0 +1,28 @@ +#!/bin/bash +# +# Build nix and all tests for as many versions and platforms as can be +# managed. This requires docker. +# + +set -e + +BASE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +RUN_DOCKER="${BASE_DIR}/ci/run-docker.sh" + +export RUST_VERSION=1.7.0 + +export DOCKER_IMAGE=posborne/rust-cross:base +RUST_TARGET=x86_64-unknown-linux-gnu ${RUN_DOCKER} +RUST_TARGET=x86_64-unknown-linux-musl ${RUN_DOCKER} + +export DOCKER_IMAGE=posborne/rust-cross:arm +RUST_TARGET=aarch64-unknown-linux-gnu ${RUN_DOCKER} +RUST_TARGET=arm-linux-gnueabi test_nix ${RUN_DOCKER} +RUST_TARGET=arm-linux-gnueabihf test_nix ${RUN_DOCKER} + +export DOCKER_IMAGE=posborne/rust-cross:mips +RUST_TARGET=mips-unknown-linux-gnu test_nix ${RUN_DOCKER} +RUST_TARGET=mipsel-unknown-linux-gnu test_nix ${RUN_DOCKER} + +export DOCKER_IMAGE=posborne/rust-cross:android ${RUN_DOCKER} +RUST_TARGET=arm-linux-androideabi test_nix ${RUN_DOCKER} diff --git a/ci/run-docker.sh b/ci/run-docker.sh new file mode 100755 index 0000000000..3ef831c32c --- /dev/null +++ b/ci/run-docker.sh @@ -0,0 +1,15 @@ +#!/bin/bash +# +# Run the nix tests in a docker container. This script expects the following +# environment variables to be set: +# - DOCKER_IMAGE : Docker image to use for testing (e.g. posborne/rust-cross:arm) +# - RUST_VERSION : Rust Version to test against (e.g. 1.7.0) +# - RUST_TARGET : Target Triple to test + +BASE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" + +docker run -i -t \ + -v ${BASE_DIR}:/source \ + -e CARGO_TARGET_DIR=/build \ + ${DOCKER_IMAGE} \ + /source/ci/run.sh ${RUST_VERSION} ${RUST_TARGET} diff --git a/ci/run-travis.sh b/ci/run-travis.sh new file mode 100644 index 0000000000..195881fe3f --- /dev/null +++ b/ci/run-travis.sh @@ -0,0 +1,47 @@ +#!/bin/bash +# +# Entry point for all travis builds, this will set up the Travis environment by +# downloading any dependencies. It will then execute the `run.sh` script to +# build and execute all tests. +# +# Much of this script was liberally stolen from rust-lang/libc +# +# Key variables that may be set from Travis: +# - TRAVIS_RUST_VERSION: 1.1.0 ... stable/nightly/beta +# - TRAVIS_OS_NAME: linux/osx +# - DOCKER_IMAGE: posborne/rust-cross:arm +# - TARGET: e.g. arm-unknown-linux-gnueabihf + +set -ex + +BASE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" + +if [ "$TRAVIS_OS_NAME" = "linux" ]; then + OS=unknown-linux-gnu +elif [ "$TRAVIS_OS_NAME" = "osx" ]; then + OS=apple-darwin +else + echo "Unexpected TRAVIS_OS_NAME: $TRAVIS_OS_NAME" + exit 1 +fi + +export HOST=$ARCH-$OS +if [ "$TARGET" = "" ]; then + TARGET=$HOST +fi + +if [ "$TARGET" = "i686-unknown-linux-gnu" ]; then + sudo apt-get -y update + sudo apt-get install -y gcc-multilib +fi + +if [ "$DOCKER_IMAGE" = "" ]; then + export RUST_TEST_THREADS=1 + curl -sSL "https://raw.githubusercontent.com/carllerche/travis-rust-matrix/master/test" | bash + cargo doc --no-deps +else + export RUST_VERSION=${TRAVIS_RUST_VERSION} + export RUST_TARGET=${TARGET} + export DOCKER_IMAGE=${DOCKER_IMAGE} + ${BASE_DIR}/ci/run-docker.sh +fi diff --git a/ci/run.sh b/ci/run.sh new file mode 100755 index 0000000000..71c91cd9d6 --- /dev/null +++ b/ci/run.sh @@ -0,0 +1,135 @@ +#!/bin/bash + +# Builds and runs tests for a particular target passed as an argument to this +# script. + +set -e + +# This should only be run in a docker container, so verify that +if [ ! -f /.dockerinit ]; then + echo "run.sh should only be executed in a docker container" + echo "and that does not appear to be the case. Maybe you meant" + echo "to execute the tests via run-all.sh or run-docker.sh." + echo "" + echo "For more instructions, please refer to ci/README.md" + exit 1 +fi + +BASE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +MANIFEST_PATH="${BASE_DIR}/Cargo.toml" +BUILD_DIR="." + +VERSION="$1" +TARGET="$2" + +export RUST_TEST_THREADS=1 + +# +# Tell cargo what linker to use and whatever else is required +# +configure_cargo() { + mkdir -p .cargo + cp -b "${BASE_DIR}/ci/cargo-config" .cargo/config +} + +# +# We need to export CC for the tests to build properly (some C code is +# compiled) to work. We already tell Cargo about the compiler in the +# cargo config, so we just parse that info out of the cargo config +# +cc_for_target() { + awk "/\[target\.${TARGET}\]/{getline; print}" .cargo/config | + cut -d '=' -f2 | \ + tr -d '"' | tr -d ' ' +} + +cross_compile_tests() { + case "$TARGET" in + *-apple-ios) + cargo test --no-run --manifest-path="${MANIFEST_PATH}" --target "$TARGET" -- \ + -C link-args=-mios-simulator-version-min=7.0 + ;; + + *) + cargo test --no-run --verbose \ + --manifest-path="${MANIFEST_PATH}" \ + --target "$TARGET" + ;; + esac +} + +# This is a hack as we cannot currently +# ask cargo what test files it generated: +# https://github.com/rust-lang/cargo/issues/1924 +find_binaries() { + target_base_dir="${BUILD_DIR}/${TARGET}/debug" + + # find [[test]] sections and print the first line and + # hack it to what we want from there. Also "nix" for + # tests that are implicitly prsent + for test_base in $( awk '/\[\[test\]\]/{getline; print}' "${MANIFEST_PATH}" | \ + cut -d '=' -f2 | \ + tr -d '"' | \ + tr '-' '_' | \ + tr -d ' '; echo "nix" ); do + for path in ${target_base_dir}/${test_base}-* ; do + echo "${path} " + done + done +} + +test_binary() { + binary=$1 + + case "$TARGET" in + arm-linux-gnueabi-gcc) + qemu-arm -L /usr/arm-linux-gnueabihf "$binary" + ;; + + arm-unknown-linux-gnueabihf) + qemu-arm -L /usr/arm-linux-gnueabihf "$binary" + ;; + + mips-unknown-linux-gnu) + qemu-mips -L /usr/mips-linux-gnu "$binary" + ;; + + aarch64-unknown-linux-gnu) + qemu-aarch64 -L /usr/aarch64-linux-gnu "$binary" + ;; + + *-rumprun-netbsd) + rumprun-bake hw_virtio /tmp/nix-test.img "${binary}" + qemu-system-x86_64 -nographic -vga none -m 64 \ + -kernel /tmp/nix-test.img 2>&1 | tee /tmp/out & + sleep 5 + grep "^PASSED .* tests" /tmp/out + ;; + + *) + echo "Running binary: ${binary}" + ${binary} + ;; + esac +} + +echo "=======================================================" +echo "TESTING VERSION: ${VERSION}, TARGET: ${TARGET}" +echo "=======================================================" + +configure_cargo +export CC="$(cc_for_target)" +if [ "${CC}" = "" ]; then + unset CC +fi + +# select the proper version +multirust override ${VERSION} + +# build the tests +cross_compile_tests + +# and run the tests +for bin in $(find_binaries); do + test_binary "${bin}" +done