diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000000..8d9ed333a5 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,4 @@ +docker +*/*/target +target +.git diff --git a/README.md b/README.md index 8c590d9849..d287af8c21 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,11 @@ safety within the programming language and a sandbox around the virtual devices to protect the kernel from attack in case of an exploit in the devices. +## Building with Docker + +See the [README](docker/README.md) from the `docker` subdirectory to learn how +to build crosvm in enviroments outside of the Chrome OS chroot. + ## Usage To see the usage information for your version of crosvm, run `crosvm` or `crosvm diff --git a/bin/smoke_test b/bin/smoke_test new file mode 100755 index 0000000000..e488e0e712 --- /dev/null +++ b/bin/smoke_test @@ -0,0 +1,19 @@ +#!/bin/bash +# Copyright 2019 The Chromium OS Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +set -ex + +cd "$(dirname "${BASH_SOURCE[0]}")" +cd ../ + +rustup default "$(cat rust-toolchain)" +rustup component add rustfmt-preview +cargo --version && rustc --version && rustfmt --version +echo "Running cargo test" +cargo test --no-fail-fast --features plugin,default-no-sandbox,wl-dmabuf,gpu,tpm,gpu-forward \ + --all --exclude aarch64 $TEST_FLAGS -- \ + --test-threads=1 $TEST_RUNNER_FLAGS +echo "Running cargo fmt" +bin/fmt --check diff --git a/kokoro/Dockerfile b/docker/Dockerfile similarity index 85% rename from kokoro/Dockerfile rename to docker/Dockerfile index b0551817d4..342316269f 100644 --- a/kokoro/Dockerfile +++ b/docker/Dockerfile @@ -61,7 +61,7 @@ WORKDIR /scratch # minijail does not exist in upstream linux distros. RUN git clone https://android.googlesource.com/platform/external/minijail \ && cd minijail \ - && make -j24 \ + && make -j$(nproc) \ && cp libminijail.so /usr/lib/x86_64-linux-gnu/ # The gbm used by upstream linux distros is not compatible with crosvm, which must use Chrome OS's @@ -70,18 +70,20 @@ RUN dpkg --force-depends -r libgbm1 RUN git clone https://chromium.googlesource.com/chromiumos/platform/minigbm \ && cd minigbm \ && sed 's/-Wall/-Wno-maybe-uninitialized/g' -i Makefile \ - && make install -j24 + && make install -j$(nproc) # New libepoxy requires newer meson than is in Debian stretch. +ARG MESON_COMMIT=master RUN git clone https://github.com/mesonbuild/meson \ && cd meson \ - && git checkout 0a5ff338012a00f32c3aa9d8773835accc3e4e5b \ + && git checkout $MESON_COMMIT \ && ln -s $PWD/meson.py /usr/bin/meson # New libepoxy has EGL_KHR_DEBUG entry points needed by crosvm. +ARG LIBEPOXY_COMMIT=master RUN git clone https://github.com/anholt/libepoxy.git \ && cd libepoxy \ - && git checkout 707f50e680ab4f1861b1e54ca6e2907aaca56c12 \ + && git checkout $LIBEPOXY_COMMIT \ && mkdir build \ && cd build \ && meson \ @@ -91,20 +93,22 @@ RUN git clone https://github.com/anholt/libepoxy.git \ RUN git clone https://gitlab.freedesktop.org/virgl/virglrenderer.git \ && cd virglrenderer \ && ./autogen.sh \ - && make install -j24 + && make install -j$(nproc) # Install libtpm2 so that tpm2-sys/build.rs does not try to build it in place in # the read-only source directory. +ARG TPM2_COMMIT=master RUN git clone https://chromium.googlesource.com/chromiumos/third_party/tpm2 \ && cd tpm2 \ - && git checkout 15260c8cd98eb10b4976d2161cd5cb9bc0c3adac \ - && make -j24 \ + && git checkout $TPM2_COMMIT \ + && make -j$(nproc) \ && cp build/libtpm2.a /lib # Install librendernodehost +ARG PLATFORM2_COMMIT=master RUN git clone https://chromium.googlesource.com/chromiumos/platform2 \ && cd platform2 \ - && git checkout 226fc35730a430344a68c34d7fe7d613f758f417 \ + && git checkout $PLATFORM2_COMMIT \ && cd rendernodehost \ && gcc -c src.c -o src.o \ && ar rcs librendernodehost.a src.o \ @@ -140,12 +144,3 @@ RUN git clone https://chromium.googlesource.com/chromiumos/third_party/adhd $THI ENV CARGO_TARGET_DIR=/build RUN mkdir -p $CARGO_TARGET_DIR WORKDIR /platform/crosvm -CMD rustup default "$(cat rust-toolchain)" && \ - rustup component add rustfmt-preview && \ - cargo --version && rustc --version && rustfmt --version && \ - echo "Running cargo test" && \ - cargo test --no-fail-fast --features plugin,default-no-sandbox,wl-dmabuf,gpu,tpm,gpu-forward \ - --all --exclude aarch64 $TEST_FLAGS -- \ - --test-threads=1 $TEST_RUNNER_FLAGS && \ - echo "Running cargo fmt" && \ - bin/fmt --check diff --git a/docker/Dockerfile.crosvm b/docker/Dockerfile.crosvm new file mode 100644 index 0000000000..3a7f293010 --- /dev/null +++ b/docker/Dockerfile.crosvm @@ -0,0 +1,16 @@ +FROM crosvm-base + +COPY . /platform/crosvm + +RUN cargo install --features 'default-no-sandbox wl-dmabuf gpu' --path . --root /usr + +ARG UID=1000 +ARG GID=1000 + +RUN export uid=$UID gid=$GID && \ + mkdir -p /home/chronos && \ + echo "chronos:x:${uid}:${gid}:Developer,,,:/home/chronos:/bin/bash" >> /etc/passwd && \ + echo "chronos:x:${uid}:" >> /etc/group && \ + chown ${uid}:${gid} -R /home/chronos + +ENTRYPOINT ["crosvm"] diff --git a/docker/README.md b/docker/README.md new file mode 100644 index 0000000000..df384487b6 --- /dev/null +++ b/docker/README.md @@ -0,0 +1,47 @@ +# Docker for Building/Running crosvm + +This module contains various pieces of Docker infrastructure for supporting crosvm outside of Chrome +OS environments. This includes the kokoro build environment. + +[TOC] + +## Introduction + +Ordinarily, crosvm is built using the standard `cargo build` command inside of a Chrome OS chroot. +The chroot requirement is there because of various path dependencies in the crosvm `Cargo.toml` are +targeted to paths outside of the crosvm repo itself. If one were to checkout crosvm in isolation, +`cargo build` would be inadequate, failing with an error related to these missing paths. +Additionally, crosvm depends on native packages that are not ordinarily available from an OS package +manager (e.g. minijail) or have been forked in the Chrome OS project in an incompatible fashion +(libusb). + +## `crosvm-base` Docker Image + +To support building crosvm outside of a Chrome OS chroot, this modules contains a `Dockerfile` that +is used to build the `crosvm-base` docker image. Part of that image build process is downloading +various repos, checking out pinned commits (specified in `checkout_commits.env`), and installing +them. For the path dependencies in the `Cargo.toml`, the `Dockerfile` downloads and places the +source code in the correct spot relative to the crosvm source repository. The `crosvm-base` build +step stops short of actually building crosvm. It doesn't even have the source code for crosvm. The +intent here is to use `crosvm-base` for building and running any version of crosvm. + +To build the `crosvm-base` image, run `build_crosvm_base.sh`. The script will automatically use the +checkouts from `checkout_commits.env` which can be reconfigured to point to any commit desired. To +upgrade `checkout_commits.sh` to the HEAD of each remote master branch, run the +`upgrade_checkout_commits.sh` script. + +## `crosvm` Docker Image + +After generating a `crosvm-base`, the system is ready to build crosvm into its own `crosvm` docker +image. The resulting docker image will be capable of running VMs without fear of missing native +dependencies. Run the `build_crosvm.sh` script to build crosvm into a docker image. Once that +completes, use the `crosvm_wrapper.sh` script to run crosvm within the docker image. That script +will pass the arguments given to it verbatim to crosvm. In addition, the current working directory +is bind mounted into the container so that file paths passed to `crosvm_wrapper.sh` should work as +long as they are relative paths to files contained in the working directory. + +## `smoke_test` + +There is a convenience wrapper for `smoke_test` that uses the `crosvm` docker image to execute +all the tests. Run `wrapped_smoke_test.sh` after building `crosvm-base` docker image to run the +`smoke_test` within docker. diff --git a/docker/build_crosvm.sh b/docker/build_crosvm.sh new file mode 100755 index 0000000000..3c6d359120 --- /dev/null +++ b/docker/build_crosvm.sh @@ -0,0 +1,11 @@ +#!/bin/bash +# Copyright 2019 The Chromium OS Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +set -ex +cd "${0%/*}" + +src_root="$(realpath ..)" + +docker build -t crosvm -f Dockerfile.crosvm --build-arg UID --build-arg GID "${src_root}" diff --git a/docker/build_crosvm_base.sh b/docker/build_crosvm_base.sh new file mode 100755 index 0000000000..20413842ad --- /dev/null +++ b/docker/build_crosvm_base.sh @@ -0,0 +1,15 @@ +#!/bin/bash +# Copyright 2019 The Chromium OS Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +set -ex +cd "${0%/*}" + +gen_build_args() { + for arg in $(cat ./checkout_commits.env); do + echo --build-arg "${arg}" + done +} + +docker build $(gen_build_args) -t crosvm-base . diff --git a/docker/checkout_commits.env b/docker/checkout_commits.env new file mode 100644 index 0000000000..bdb8447ac0 --- /dev/null +++ b/docker/checkout_commits.env @@ -0,0 +1,4 @@ +MESON_COMMIT=0a5ff338012a00f32c3aa9d8773835accc3e4e5b +LIBEPOXY_COMMIT=707f50e680ab4f1861b1e54ca6e2907aaca56c12 +TPM2_COMMIT=15260c8cd98eb10b4976d2161cd5cb9bc0c3adac +PLATFORM2_COMMIT=226fc35730a430344a68c34d7fe7d613f758f417 diff --git a/docker/crosvm_wrapper.sh b/docker/crosvm_wrapper.sh new file mode 100755 index 0000000000..33891d6716 --- /dev/null +++ b/docker/crosvm_wrapper.sh @@ -0,0 +1,17 @@ +#!/bin/bash +# Copyright 2019 The Chromium OS Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +set -ex +cd "${0%/*}" + +exec docker run -it --rm \ + --privileged \ + -e DISPLAY=$DISPLAY -e XDG_RUNTIME_DIR=$XDG_RUNTIME_DIR \ + -v /dev/log:/dev/log \ + -v /tmp/.X11-unix:/tmp/.X11-unix \ + --volume "$PWD":/wd \ + --workdir /wd \ + crosvm \ + "$@" diff --git a/kokoro/pkgconfig/libtpm2.pc b/docker/pkgconfig/libtpm2.pc similarity index 100% rename from kokoro/pkgconfig/libtpm2.pc rename to docker/pkgconfig/libtpm2.pc diff --git a/docker/upgrade_checkout_commits.sh b/docker/upgrade_checkout_commits.sh new file mode 100755 index 0000000000..44323a7cba --- /dev/null +++ b/docker/upgrade_checkout_commits.sh @@ -0,0 +1,27 @@ +#!/bin/bash +# Copyright 2019 The Chromium OS Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +set -ex +cd "${0%/*}" + +remotes=( + "https://github.com/mesonbuild/meson" + "https://github.com/anholt/libepoxy.git" + "https://chromium.googlesource.com/chromiumos/third_party/tpm2" + "https://chromium.googlesource.com/chromiumos/platform2" +) + +keys=( + "MESON_COMMIT" + "LIBEPOXY_COMMIT" + "TPM2_COMMIT" + "PLATFORM2_COMMIT" +) + +for remote in "${remotes[@]}"; do + remote_chunk=$(git ls-remote --exit-code "${remote}" refs/heads/master) + commit=$(echo "${remote_chunk}" | cut -f 1 -) + echo $commit +done diff --git a/docker/wrapped_smoke_test.sh b/docker/wrapped_smoke_test.sh new file mode 100755 index 0000000000..324ab7c44e --- /dev/null +++ b/docker/wrapped_smoke_test.sh @@ -0,0 +1,19 @@ +#!/bin/bash +# Copyright 2019 The Chromium OS Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +set -ex +cd "${0%/*}" + +src_root="$(realpath ..)" + +docker run \ + --rm \ + --privileged \ + -e TEST_RUNNER_FLAGS='--format terse' \ + -v /dev/log:/dev/log \ + -v "${src_root}":/platform/crosvm:ro \ + crosvm-base \ + bin/smoke_test + diff --git a/kokoro/README.md b/kokoro/README.md index 70cceb2495..727b74aa70 100644 --- a/kokoro/README.md +++ b/kokoro/README.md @@ -3,7 +3,7 @@ For presubmit testing, each change posted for Gerrit on the master branch of crosvm will be tried by Kokoro. The configuration is found in [`presubmit.cfg`](presubmit.cfg) and the build script is at [`build.sh`](build.sh). A Docker image called `crosvm-base` is used as the testing environment which -is built with a [`Dockerfile`](Dockerfile). +is built with a [`Dockerfile`](../docker/Dockerfile). [TOC] @@ -12,17 +12,17 @@ is built with a [`Dockerfile`](Dockerfile). Assuming a Docker daemon is already running, build the `crosvm-base` image: ```shell -docker build -t crosvm-base path/to/crosvm/kokoro +path/to/crosvm/docker/build_crosvm_base.sh ``` Here is how to use the image to test a crosvm repository located at `$CROSVM_SRC`: ```shell -docker run --privileged -v /dev/log:/dev/log -v "${CROSVM_SRC}":/platform/crosvm:ro crosvm-base +$CROSVM_SRC/docker/wrapped_smoke_test.sh ``` > **WARNING**: -> The `--privileged` is so that the container will have `/dev/kvm` access. +> The `--privileged` flag is used in that script so that the container will have `/dev/kvm` access. ## How to update `crosvm-base` @@ -32,7 +32,7 @@ If an update or new library is needed or any other adjustment is required, a new generated as follows: ```shell -docker build -t crosvm-base path/to/crosvm/kokoro +path/to/crosvm/docker/build_crosvm_base.sh docker save crosvm-base | xz -T 0 -z >crosvm-base.tar.xz ``` diff --git a/kokoro/build.sh b/kokoro/build.sh index e78d9c7459..96028ac9a7 100755 --- a/kokoro/build.sh +++ b/kokoro/build.sh @@ -18,13 +18,7 @@ main() { if [[ "$(docker images -q ${base_image} 2> /dev/null)" == "" ]]; then docker load -i "${base_image_tarball}" fi - docker run \ - --rm \ - --privileged \ - -e TEST_RUNNER_FLAGS='--format terse' \ - -v /dev/log:/dev/log \ - -v "${src_root}":/platform/crosvm:ro \ - ${base_image} + "${src_root}"/docker/wrapped_smoke_test.sh return 0 } diff --git a/kokoro/kokoro_simulator.sh b/kokoro/kokoro_simulator.sh index 5303c5cdf4..08961def13 100755 --- a/kokoro/kokoro_simulator.sh +++ b/kokoro/kokoro_simulator.sh @@ -16,7 +16,7 @@ main() { mkdir -p "${kokoro_simulator_root}" if [[ ! -e "${base_image_tarball}" ]]; then if [[ "$(docker images -q ${base_image} 2> /dev/null)" == "" ]]; then - docker build -t ${base_image} . + ../docker/build_crosvm_base.sh fi docker save ${base_image} | xz -T 0 -z >"${base_image_tarball}" fi