Add docker builds for x86 crosvm binaries
Cleaning up:
-- renamed --x86_instance, --x86_user --> --gce_instance, --gce_user;
-- renamed --arm_system to --arm_instance for consistency with
option -- gce_instance;
-- added top-level --gce, --arm, --docker toggles, all false by default;
these now need to be specified to trigger the respective type of
build, e.g:
./device/google/cuttlefish_vmm/rebuild.sh --gce
./device/google/cuttlefish_vmm/rebuild.sh --arm \
--arm_instance 192.168.0.6 --arm_user cf
-- fixed typo: rebuild-internal.sh, not rebuild_internal.sh;
-- put in checks to ensure --arm_system and --arm_user aren't empty when
option --arm is specified;
-- invoke rebuild-internal.sh with install_packages separately from
rebuild-internal.sh to actually build crosvm, since
rebuild-internal.sh no longer directly invokes install_packages;
-- Rename option --custom_manifest to --manifest; make --manifest take
the default value of ./devices/google/cuttlefish_vmm/$(uname
-m)-linux-gnu/manifest.xml;
-- Always pass the manifest flag to the build script. The implication
is that you no longer have to specify the manifest. Previously,
failing to specify explicitly a manifest file meant that the entire
Android tree would be synced, which was an enormous waste of time.
Added support for x86 docker images:
-- New option --docker that enables a docker build;
-- New options --docker_source, --docker_working, and --docker_output to
specify external paths to contain respectively the sources, working
directory, and output directory for the finished binary artifacts;
-- Option --docker_output defaults to
./device/google/cuttlefish_vmm/$(uname -m)-linux-gnu, meaning the
docker build will put the built images in the right place;
-- If options --docker_source and --docker_working are left unspecified,
the container will pull the sources internally and stash its
intermediate object files internally as well;
-- Options --reuse and --reuse_resync work with the docker build;
-- The .dockerignore file is meant to prevent the entire directory from
being copied to the docker deamon as context, except for the three
files (rebuild-internal.sh, and *-linux-gnu/manifest.xml) that we
care about.
Test: built crosvm for gce, arm, and docker
Bug: 148642775 Clean up the crosvm build
Change-Id: I861c5ee8f1d7c7e1b1048380af6b49ea7834ca88
Signed-off-by: Iliyan Malchev <malchev@google.com>
diff --git a/.dockerignore b/.dockerignore
new file mode 100644
index 0000000..f33aa59
--- /dev/null
+++ b/.dockerignore
@@ -0,0 +1,7 @@
+.*
+*
+*/*
+*/*/*
+!rebuild-internal.sh
+!x86_64-linux-gnu/manifest.xml
+!aarch64-linux-gnu/manifest.xml
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..2d56f74
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,45 @@
+FROM debian:buster-slim
+
+ENV container docker
+ENV LC_ALL C.UTF-8
+ENV DEBIAN_FRONTEND noninteractive
+
+# Set up the user to be the same as the user creating the container. Not
+# strictly necessary, but this way all the permissions of the generated files
+# will match.
+
+ARG USER
+ARG UID
+
+ENV USER $USER
+ENV HOME /home/$USER
+ENV CUSTOM_MANIFEST ""
+
+RUN apt update \
+ && apt install -y sudo
+
+RUN useradd -m -s /bin/bash $USER -u $UID -d $HOME \
+ && passwd -d $USER \
+ && echo "$USER ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers
+
+RUN mkdir /source && chown -R $USER /source
+RUN mkdir /output && chown -R $USER /output
+RUN mkdir /working && chown -R $USER /working
+RUN mkdir /static && chown -R $USER /static
+
+SHELL [ "/bin/bash", "-c" ]
+
+USER $USER
+WORKDIR /working
+
+COPY --chown=$USER x86_64-linux-gnu/manifest.xml /static/x86_64-linux-gnu/manifest.xml
+COPY --chown=$USER aarch64-linux-gnu/manifest.xml /static/aarch64-linux-gnu/manifest.xml
+COPY --chown=$USER rebuild-internal.sh /static/rebuild-internal.sh
+
+RUN TOOLS_DIR=/static/tools /static/rebuild-internal.sh install_packages
+
+VOLUME /source
+VOLUME /working
+VOLUME /output
+
+ENTRYPOINT ["/static/rebuild-internal.sh"]
diff --git a/rebuild.sh b/rebuild.sh
index 13c693a..9678d2a 100755
--- a/rebuild.sh
+++ b/rebuild.sh
@@ -11,21 +11,39 @@
source "${ANDROID_BUILD_TOP}/external/shflags/src/shflags"
DIR="${ANDROID_BUILD_TOP}/device/google/cuttlefish_vmm"
-DEFINE_string arm_system \
- "" "IP address or DNS name of an ARM system to do the secondary build"
-DEFINE_string arm_user \
- "vsoc-01" "User to invoke on the ARM system"
-DEFINE_string custom_manifest "" "Custom manifest to use for the build"
-DEFINE_string project "$(gcloud config get-value project)" "Project to use" "p"
-DEFINE_string source_image_family debian-10 "Image familty to use as the base" \
- "s"
-DEFINE_string source_image_project debian-cloud \
- "Project holding the base image" "m"
-DEFINE_string x86_instance \
- "${USER}-build" "Instance name to create for the build" "i"
-DEFINE_string x86_user cuttlefish_crosvm_builder \
- "User name to use on GCE when doing the build"
-DEFINE_string zone "$(gcloud config get-value compute/zone)" "Zone to use" "z"
+# ARM-board options
+
+DEFINE_boolean arm false "Build on an ARM board"
+DEFINE_string arm_instance "" "IP address or DNS name of an ARM system to do the secondary build"
+DEFINE_string arm_user "vsoc-01" "User to invoke on the ARM system"
+
+# Docker options
+
+DEFINE_boolean docker false "Build inside docker"
+DEFINE_string docker_arch "$(uname -m)" "Target architectre"
+DEFINE_string docker_image "docker_vmm" "Name of docker image to build"
+DEFINE_string docker_container "docker_vmm" "Name of docker container to create"
+DEFINE_string docker_source "" "Path to sources checked out using manifest"
+DEFINE_string docker_working "" "Path to working directory"
+DEFINE_string docker_output "${ANDROID_BUILD_TOP}/device/google/cuttlefish_vmm/$(uname -m)-linux-gnu" "Output directory"
+DEFINE_string docker_user "${USER}" "Docker-container user"
+DEFINE_string docker_uid "${UID}" "Docker-container user ID"
+
+# GCE options
+
+DEFINE_boolean gce false "Build on a GCE instance"
+DEFINE_string gce_project "$(gcloud config get-value project)" "Project to use" "p"
+DEFINE_string gce_source_image_family debian-10 "Image familty to use as the base" "s"
+DEFINE_string gce_source_image_project debian-cloud "Project holding the base image" "m"
+DEFINE_string gce_instance "${USER}-build" "Instance name to create for the build" "i"
+DEFINE_string gce_user cuttlefish_crosvm_builder "User name to use on GCE when doing the build"
+DEFINE_string gce_zone "$(gcloud config get-value compute/zone)" "Zone to use" "z"
+
+# Common options
+
+DEFINE_string manifest \
+ "${ANDROID_BUILD_TOP}/device/google/cuttlefish_vmm/$(uname -m)-linux-gnu/manifest.xml" \
+ "manifest to use for the build"
DEFINE_boolean reuse false "Set to true to reuse a previously-set-up instance."
DEFINE_boolean reuse_resync false "Reuse a previously-set-up instance, but clean and re-sync the sources. Overrides --reuse if both are specified."
@@ -43,45 +61,52 @@
set -o errexit
set -x
fail=0
- source_files=("${DIR}"/rebuild_internal.sh)
+ source_files=("${DIR}"/rebuild-internal.sh)
+ # These must match the definitions in the Dockerfile
+ docker_flags=("-e SOURCE_DIR=/source" "-e WORKING_DIR=/working" "-e OUTPUT_DIR=/output" "-e TOOLS_DIR=/static/tools")
gce_flags=()
arm_flags=()
- if [[ -n "${FLAGS_custom_manifest}" ]]; then
- if [[ ! -f "${FLAGS_custom_manifest}" ]]; then
- echo custom manifest not found: ${FLAGS_custom_manifest} 1>&1
+ if [[ -n "${FLAGS_manifest}" ]]; then
+ if [[ ! -f "${FLAGS_manifest}" ]]; then
+ echo custom manifest not found: ${FLAGS_manifest} 1>&1
exit 2
fi
- source_files+=("${FLAGS_custom_manifest}")
- gce_flags+=("CUSTOM_MANIFEST=/home/${FLAGS_x86_user}/$(basename "${FLAGS_custom_manifest}")")
- arm_flags+=("CUSTOM_MANIFEST=/home/${FLAGS_arm_user}/$(basename "${FLAGS_custom_manifest}")")
+ source_files+=("${FLAGS_manifest}")
+ docker_flags+=("-e CUSTOM_MANIFEST=/static/${FLAGS_docker_arch}-linux-gnu/$(basename ${FLAGS_manifest})")
+ gce_flags+=("CUSTOM_MANIFEST=/home/${FLAGS_gce_user}/$(basename "${FLAGS_manifest}")")
+ arm_flags+=("CUSTOM_MANIFEST=/home/${FLAGS_arm_user}/$(basename "${FLAGS_manifest}")")
fi
- local _prepare_source=(install_packages prepare_source);
+ local _prepare_source=(setup_env fetch_source);
local _reuse=0
- if [ ${FLAGS_reuse} -eq ${FLAGS_TRUE} ]; then
+ if [[ ${FLAGS_reuse} -eq ${FLAGS_TRUE} ]]; then
# neither install packages, nor sync sources; skip to building them
- _prepare_source=()
+ _prepare_source=(setup_env)
_reuse=1
fi
- if [ ${FLAGS_reuse_resync} -eq ${FLAGS_TRUE} ]; then
+ if [[ ${FLAGS_reuse_resync} -eq ${FLAGS_TRUE} ]]; then
# do not install packages but clean and sync sources afresh
- _prepare_source=(resync_source);
+ _prepare_source=(setup_env resync_source);
_reuse=1
fi
- if [[ -n "${FLAGS_x86_instance}" ]]; then
- if [[ -z "${FLAGS_project}" ]]; then
+ if [[ ${FLAGS_gce} -eq ${FLAGS_TRUE} ]]; then
+ if [[ -z "${FLAGS_gce_instance}" ]]; then
+ echo Must specify instance 1>&2
+ fail=1
+ fi
+ if [[ -z "${FLAGS_gce_project}" ]]; then
echo Must specify project 1>&2
fail=1
fi
- if [[ -z "${FLAGS_zone}" ]]; then
+ if [[ -z "${FLAGS_gce_zone}" ]]; then
echo Must specify zone 1>&2
fail=1
fi
if [[ "${fail}" -ne 0 ]]; then
exit "${fail}"
fi
- project_zone_flags=(--project="${FLAGS_project}" --zone="${FLAGS_zone}")
+ project_zone_flags=(--project="${FLAGS_gce_project}" --zone="${FLAGS_gce_zone}")
if [ ${_reuse} -eq 0 ]; then
- delete_instances=("${FLAGS_x86_instance}")
+ delete_instances=("${FLAGS_gce_instance}")
gcloud compute instances delete -q \
"${project_zone_flags[@]}" \
"${delete_instances[@]}" || \
@@ -90,50 +115,124 @@
"${project_zone_flags[@]}" \
--boot-disk-size=200GB \
--machine-type=n1-standard-4 \
- --image-family="${FLAGS_source_image_family}" \
- --image-project="${FLAGS_source_image_project}" \
- "${FLAGS_x86_instance}"
- wait_for_instance "${FLAGS_x86_instance}"
+ --image-family="${FLAGS_gce_source_image_family}" \
+ --image-project="${FLAGS_gce_source_image_project}" \
+ "${FLAGS_gce_instance}"
+ wait_for_instance "${FLAGS_gce_instance}"
fi
local _status=$(gcloud compute instances list \
- --project="${FLAGS_project}" \
- --zones="${FLAGS_zone}" \
- --filter="name=('${FLAGS_x86_instance}')" \
+ --project="${FLAGS_gce_project}" \
+ --zones="${FLAGS_gce_zone}" \
+ --filter="name=('${FLAGS_gce_instance}')" \
--format=flattened | awk '/status:/ {print $2}')
if [ "${_status}" != "RUNNING" ] ; then
- echo "Instance ${FLAGS_x86_instance} is not running."
+ echo "Instance ${FLAGS_gce_instance} is not running."
exit 1;
fi
# beta for the --internal-ip flag that may be passed via SSH_FLAGS
gcloud beta compute scp "${SSH_FLAGS[@]}" \
"${project_zone_flags[@]}" \
"${source_files[@]}" \
- "${FLAGS_x86_user}@${FLAGS_x86_instance}:"
+ "${FLAGS_gce_user}@${FLAGS_gce_instance}:"
+ if [ ${_reuse} -eq 0 ]; then
+ gcloud compute ssh "${SSH_FLAGS[@]}" \
+ "${project_zone_flags[@]}" \
+ "${FLAGS_gce_user}@${FLAGS_gce_instance}" -- \
+ ./rebuild-internal.sh install_packages
+ fi
gcloud compute ssh "${SSH_FLAGS[@]}" \
"${project_zone_flags[@]}" \
- "${FLAGS_x86_user}@${FLAGS_x86_instance}" -- \
- ./rebuild_internal.sh "${gce_flags[@]}" ${_prepare_source[@]} x86_64_build
+ "${FLAGS_gce_user}@${FLAGS_gce_instance}" -- \
+ ./rebuild-internal.sh "${gce_flags[@]}" ${_prepare_source[@]} '$(uname -m)_build'
gcloud beta compute scp --recurse "${SSH_FLAGS[@]}" \
"${project_zone_flags[@]}" \
- "${FLAGS_x86_user}@${FLAGS_x86_instance}":x86_64-linux-gnu \
+ "${FLAGS_gce_user}@${FLAGS_gce_instance}":x86_64-linux-gnu \
"${ANDROID_BUILD_TOP}/device/google/cuttlefish_vmm"
gcloud compute disks describe \
- "${project_zone_flags[@]}" "${FLAGS_x86_instance}" | \
+ "${project_zone_flags[@]}" "${FLAGS_gce_instance}" | \
grep ^sourceImage: > "${DIR}"/x86_64-linux-gnu/builder_image.txt
fi
- if [[ -n "${FLAGS_arm_system}" ]]; then
+ if [ ${FLAGS_arm} -eq ${FLAGS_TRUE} ]; then
+ if [[ -z "${FLAGS_arm_instance}" ]]; then
+ echo Must specify IP address of ARM board 1>&2
+ fail=1
+ fi
+ if [[ -z "${FLAGS_arm_instance}" ]]; then
+ echo Must specify a user account on ARM board 1>&2
+ fail=1
+ fi
+ if [[ "${fail}" -ne 0 ]]; then
+ exit "${fail}"
+ fi
scp \
"${source_files[@]}" \
- "${FLAGS_arm_user}@${FLAGS_arm_system}:"
- ssh -t "${FLAGS_arm_user}@${FLAGS_arm_system}" -- \
- ./rebuild-internal.sh "${arm_flags[@]}" ${_prepare_source[@]} arm64_build
- scp -r "${FLAGS_arm_user}@${FLAGS_arm_system}":aarch64-linux-gnu \
+ "${FLAGS_arm_user}@${FLAGS_arm_instance}:"
+ if [ ${_reuse} -eq 0 ]; then
+ ssh -t "${FLAGS_arm_user}@${FLAGS_arm_instance}" -- \
+ ./rebuild-internal.sh install_packages
+ fi
+ ssh -t "${FLAGS_arm_user}@${FLAGS_arm_user}" -- \
+ ./rebuild-internal.sh "${arm_flags[@]}" ${_prepare_source[@]} '$(uname -m)_build'
+ scp -r "${FLAGS_arm_user}@${FLAGS_arm_instance}":aarch64-linux-gnu \
"${ANDROID_BUILD_TOP}/device/google/cuttlefish_vmm"
fi
+ if [[ ${FLAGS_docker} -eq ${FLAGS_TRUE} ]]; then
+ if [[ -z "${FLAGS_docker_image}" ]]; then
+ echo Option --docker_image must not be empty 1>&1
+ fail=1
+ fi
+ if [[ -z "${FLAGS_docker_container}" ]]; then
+ echo Options --docker_container must not be empty 1>&2
+ fail=1
+ fi
+ case "${FLAGS_docker_arch}" in
+ aarch64) ;;
+ x86_64) ;;
+ *) echo Invalid value ${FLAGS_docker_arch} for --docker_arch 1>&2
+ fail=1
+ ;;
+ esac
+ if [[ -z "${FLAGS_docker_user}" ]]; then
+ echo Options --docker_user must not be empty 1>&2
+ fail=1
+ fi
+ if [[ -z "${FLAGS_docker_uid}" ]]; then
+ echo Options --docker_uid must not be empty 1>&2
+ fail=1
+ fi
+ if [[ "${fail}" -ne 0 ]]; then
+ exit "${fail}"
+ fi
+ if [[ ${_reuse} -eq 0 ]]; then
+ docker build \
+ -f ${DIR}/Dockerfile \
+ -t ${FLAGS_docker_image}:latest \
+ ${DIR} \
+ --build-arg USER=${FLAGS_docker_user} \
+ --build-arg UID=${FLAGS_docker_uid}
+ fi
+ _docker_source=()
+ if [ -n "${FLAGS_docker_source}" ]; then
+ _docker_source+=("-v ${FLAGS_docker_source}:/source")
+ fi
+ _docker_working=()
+ if [ -n "${FLAGS_docker_working}" ]; then
+ _docker_working+=("-v ${FLAGS_docker_working}:/working")
+ fi
+ docker run -it --rm \
+ --user ${FLAGS_docker_user} \
+ --name ${FLAGS_docker_container} \
+ ${_docker_source} \
+ ${_docker_working} \
+ -v "${FLAGS_docker_output}":/output \
+ ${docker_flags[@]} \
+ ${FLAGS_docker_image}:latest \
+ ${_prepare_source[@]} ${FLAGS_docker_arch}_build
+ fi
exit 0
gcloud compute instances delete -q \
"${project_zone_flags[@]}" \
- "${FLAGS_x86_instance}"
+ "${FLAGS_gce_instance}"
}
FLAGS "$@" || exit 1