Convert arm-board build to docker
Test: build crosvm on an ARM board
Bug: 148642775 Clean up the crosvm build
Change-Id: I7d704ef306714cbb7919db4e9ae01a6cb6213421
Signed-off-by: Iliyan Malchev <malchev@google.com>
diff --git a/rebuild-docker.sh b/rebuild-docker.sh
index ab9dc13..cb25ff4 100755
--- a/rebuild-docker.sh
+++ b/rebuild-docker.sh
@@ -4,6 +4,8 @@
[[ $(docker ps -a --filter "name=^/$1$" --format '{{.Names}}') == $1 ]] && echo $1;
}
+declare -A map_uname_to_docker_builder_arch=( [aarch64]=linux/arm64 [x86_64]=linux/amd64 )
+
# inputs
# $1 = image name
# $2 = container name
@@ -68,9 +70,12 @@
_docker_target+=("${_docker_target[0]}_persistent")
fi
if [[ ${_build_image} -eq 1 ]]; then
- if [[ ${_arch} == aarch64 ]]; then
+ if [[ ${_arch} != $(uname -m) ]]; then
export DOCKER_CLI_EXPERIMENTAL=enabled
- docker buildx create --name docker_vmm_${_arch}_builder --platform linux/arm64 --use
+ docker buildx create \
+ --name docker_vmm_${_arch}_builder \
+ --platform ${map_uname_to_docker_builder_arch[${_arch}]} \
+ --use
for _target in ${_docker_target[@]}; do
docker buildx build \
--platform ${map_uname_to_docker_builder_arch[${_arch}]} \
diff --git a/rebuild.sh b/rebuild.sh
index 2e66863..aa0edf3 100755
--- a/rebuild.sh
+++ b/rebuild.sh
@@ -43,8 +43,10 @@
# Common options
+# The /./ pattern in the path defition below is interpreted by rsync; do not
+# remove it!
DEFINE_string manifest \
- "${ANDROID_BUILD_TOP}/device/google/cuttlefish_vmm/$(uname -m)-linux-gnu/manifest.xml" \
+ "${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."
@@ -59,25 +61,7 @@
done
}
-function container_exists() {
- [[ $(docker ps -a --filter "name=^/$1$" --format '{{.Names}}') == $1 ]] && echo $1;
-}
-
-# inputs
-# $1 = FLAGS_docker_image
-# $2 = FLAGS_docker_container
-# $3 = FLAGS_docker_arch
-# $4 = FLAGS_docker_user
-# $5 = FLAGS_docker_uid
-# $6 = FLAGS_docker_persistent
-# $7 = FLAGS_docker_source
-# $8 = FLAGS_docker_working
-# $9 = FLAGS_docker_output
-# $10 = _reuse
-# $11 = docker_flags
-# $12 = _prepare_source
-# $13 = USE
-build_locally_using_docker() {
+check_common_docker_options() {
if [[ -z "${FLAGS_docker_image}" ]]; then
echo Option --docker_image must not be empty 1>&1
fail=1
@@ -86,21 +70,6 @@
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
# Volume mapping are specified only when a container is created. With
# --reuse, an already-created persistent container is reused, which implies
# that we cannot change the volume maps. For non-persistent containers, we
@@ -120,94 +89,56 @@
if [[ "${fail}" -ne 0 ]]; then
exit "${fail}"
fi
- local _docker_source=
- if [ -n "${FLAGS_docker_source}" ]; then
- _docker_source="-v ${FLAGS_docker_source}:/source:rw"
+}
+
+build_locally_using_docker() {
+ check_common_docker_options
+ 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
- local _docker_working=
- if [ -n "${FLAGS_docker_working}" ]; then
- _docker_working="-v ${FLAGS_docker_working}:/working:rw"
+ if [[ -z "${FLAGS_docker_uid}" ]]; then
+ echo Options --docker_uid must not be empty 1>&2
+ fail=1
fi
- local _docker_output=${FLAGS_docker_output}
+ if [[ "${fail}" -ne 0 ]]; then
+ exit "${fail}"
+ fi
+ local -i _persistent=0
+ if [[ ${FLAGS_persistent} -eq ${FLAGS_TRUE} ]]; then
+ _persistent=1
+ fi
+ local -i _build_image=0
+ if [[ ${FLAGS_docker_build_image} -eq ${FLAGS_TRUE} ]]; then
+ _build_image=1
+ fi
+ local _docker_output="${FLAGS_docker_output}"
if [[ "${_docker_output}" == "${ANDROID_BUILD_TOP}/device/google/cuttlefish_vmm/$(uname -m)-linux-gnu" && \
"$(uname -m)" != ${FLAGS_docker_arch} ]]; then
_docker_output="${ANDROID_BUILD_TOP}/device/google/cuttlefish_vmm/${FLAGS_docker_arch}-linux-gnu"
fi
- local _docker_image=${FLAGS_docker_image}_${FLAGS_docker_arch};
- if [[ ${FLAGS_docker_persistent} -eq ${FLAGS_TRUE} ]]; then
- _docker_image=${FLAGS_docker_image}_${FLAGS_docker_arch}_persistent;
- fi
- local _build_or_retry=${FLAGS_docker_arch}_retry
- if [[ ${_reuse} -eq 0 ]]; then
- _build_or_retry=${FLAGS_docker_arch}_build
- local _docker_target=()
- _docker_target+=("${FLAGS_docker_image}");
- if [[ ${FLAGS_docker_persistent} -eq ${FLAGS_TRUE} ]]; then
- _docker_target+=("${FLAGS_docker_image}_persistent");
- fi
- if [[ ${FLAGS_docker_build_image} -eq ${FLAGS_TRUE} ]]; then
- if [[ ${FLAGS_docker_arch} == aarch64 ]]; then
- export DOCKER_CLI_EXPERIMENTAL=enabled
- docker buildx create --name docker_vmm_${FLAGS_docker_arch}_builder --platform linux/arm64 --use
- for _target in ${_docker_target[@]}; do
- docker buildx build \
- --platform linux/arm64 \
- --target ${_target} \
- -f ${DIR}/Dockerfile \
- -t ${_docker_image}:latest \
- ${DIR} \
- --build-arg USER=${FLAGS_docker_user} \
- --build-arg UID=${FLAGS_docker_uid} --load
- done
- docker buildx rm docker_vmm_${FLAGS_docker_arch}_builder
- unset DOCKER_CLI_EXPERIMENTAL
- else
- for _target in ${_docker_target[@]}; do
- docker build \
- -f ${DIR}/Dockerfile \
- --target ${_target} \
- -t ${_docker_image}:latest \
- ${DIR} \
- --build-arg USER=${FLAGS_docker_user} \
- --build-arg UID=${FLAGS_docker_uid}
- done
- fi
- fi
- if [[ ${FLAGS_docker_persistent} -eq ${FLAGS_TRUE} ]]; then
- if [[ -n "$(container_exists ${FLAGS_docker_container})" ]]; then
- docker rm -f ${FLAGS_docker_container}
- fi
- docker run -d \
- --privileged \
- --name ${FLAGS_docker_container} \
- -h ${FLAGS_docker_container} \
- ${_docker_source} \
- ${_docker_working} \
- -v "${_docker_output}":/output:rw \
- -v /sys/fs/cgroup:/sys/fs/cgroup:ro \
- ${_docker_image}:latest
- fi
- fi
- if [[ ${FLAGS_docker_persistent} -eq ${FLAGS_TRUE} ]]; then
- if [[ "$(docker inspect --format='{{.State.Status}}' ${FLAGS_docker_container})" == "paused" ]]; then
- docker unpause ${FLAGS_docker_container}
- fi
- docker exec -it \
- --user ${FLAGS_docker_user} \
- ${docker_flags[@]} \
- ${FLAGS_docker_container} \
- /static/rebuild-internal.sh ${_prepare_source[@]} ${_build_or_retry}
- docker pause ${FLAGS_docker_container}
- else
- docker run -it --rm \
- --user ${FLAGS_docker_user} \
- ${docker_flags[@]} \
- ${_docker_source} \
- ${_docker_working} \
- -v "${_docker_output}":/output:rw \
- ${_docker_image}:latest \
- /static/rebuild-internal.sh ${_prepare_source[@]} ${_build_or_retry}
- fi
+ ${DIR}/rebuild-docker.sh "${FLAGS_docker_image}" \
+ "${FLAGS_docker_container}" \
+ "${FLAGS_docker_arch}" \
+ "${FLAGS_docker_user}" \
+ "${FLAGS_docker_uid}" \
+ "${_persistent}" \
+ "x${FLAGS_docker_source}" \
+ "x${FLAGS_docker_working}" \
+ "x${_docker_output}" \
+ "${_reuse}" \
+ "${_build_image}" \
+ "${DIR}/Dockerfile" \
+ "${DIR}" \
+ "${#docker_flags[@]}" "${docker_flags[@]}" \
+ "${#_prepare_source[@]}" "${_prepare_source[@]}"
}
function build_on_gce() {
@@ -283,6 +214,11 @@
}
function build_on_arm_board() {
+ check_common_docker_options
+ if [[ "${FLAGS_docker_arch}" != "aarch64" ]]; then
+ echo ARM board supports building only aarch64 1>&2
+ fail=1
+ fi
if [[ -z "${FLAGS_arm_instance}" ]]; then
echo Must specify IP address of ARM board 1>&2
fail=1
@@ -294,29 +230,59 @@
if [[ "${fail}" -ne 0 ]]; then
exit "${fail}"
fi
- scp \
- "${source_files[@]}" \
- "${FLAGS_arm_user}@${FLAGS_arm_instance}:"
- if [ ${_reuse} -eq 0 ]; then
+ if [[ "${_reuse}" -eq 0 ]]; then
ssh -t "${FLAGS_arm_user}@${FLAGS_arm_instance}" -- \
- ./rebuild-internal.sh install_packages
- ssh -t "${FLAGS_arm_user}@${FLAGS_arm_instance}" -- \
- ./rebuild-internal.sh "${arm_flags[@]}" ${_prepare_source[@]} '$(uname -m)_build'
- else
- ssh -t "${FLAGS_arm_user}@${FLAGS_arm_instance}" -- \
- ./rebuild-internal.sh "${arm_flags[@]}" ${_prepare_source[@]} '$(uname -m)_retry'
+ rm -rf '$PWD/docker'
fi
- scp -r "${FLAGS_arm_user}@${FLAGS_arm_instance}":aarch64-linux-gnu \
- "${ANDROID_BUILD_TOP}/device/google/cuttlefish_vmm"
+ rsync -avR -e ssh \
+ "${source_files[@]}" \
+ "${FLAGS_arm_user}@${FLAGS_arm_instance}:~/docker/"
+
+ local -i _persistent=0
+ if [[ ${FLAGS_persistent} -eq ${FLAGS_TRUE} ]]; then
+ _persistent=1
+ fi
+ local -i _build_image=0
+ if [[ ${FLAGS_docker_build_image} -eq ${FLAGS_TRUE} ]]; then
+ _build_image=1
+ fi
+ ssh -t "${FLAGS_arm_user}@${FLAGS_arm_instance}" -- \
+ mkdir -p '$PWD/docker/source' '$PWD/docker/working' '$PWD/docker/output'
+ ssh -t "${FLAGS_arm_user}@${FLAGS_arm_instance}" -- \
+ ./docker/rebuild-docker.sh "${FLAGS_docker_image}" \
+ "${FLAGS_docker_container}" \
+ "${FLAGS_docker_arch}" \
+ '${USER}' \
+ '${UID}' \
+ "${_persistent}" \
+ 'x$PWD/docker/source' \
+ 'x$PWD/docker/working' \
+ 'x$PWD/docker/output' \
+ "${_reuse}" \
+ "${_build_image}" \
+ '~/docker/Dockerfile' \
+ '~/docker/' \
+ "${#docker_flags[@]}" "${docker_flags[@]}" \
+ "${#_prepare_source[@]}" "${_prepare_source[@]}"
+
+ rsync -avR -e ssh "${FLAGS_arm_user}@${FLAGS_arm_instance}":docker/output/./ \
+ "${ANDROID_BUILD_TOP}/device/google/cuttlefish_vmm/${FLAGS_docker_arch}-linux-gnu"
}
main() {
set -o errexit
set -x
fail=0
- source_files=("${DIR}"/rebuild-internal.sh)
+ # The /./ patterns in the path defitions below are interpreted by rsync; do not
+ # remove them!
+ source_files=("${DIR}"/./rebuild-docker.sh \
+ "${DIR}"/./rebuild-internal.sh \
+ "${DIR}"/./Dockerfile \
+ "${DIR}"/./x86_64-linux-gnu/manifest.xml \
+ "${DIR}"/./aarch64-linux-gnu/manifest.xml \
+ "${DIR}"/./.dockerignore)
# 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")
+ docker_flags=("-eSOURCE_DIR=/source" "-eWORKING_DIR=/working" "-eOUTPUT_DIR=/output" "-eTOOLS_DIR=/static/tools")
gce_flags=()
arm_flags=()
@@ -331,12 +297,12 @@
exit 2
fi
source_files+=("${FLAGS_manifest}")
- docker_flags+=("-e CUSTOM_MANIFEST=/static/${FLAGS_docker_arch}-linux-gnu/$(basename ${FLAGS_manifest})")
+ docker_flags+=("-eCUSTOM_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=(setup_env fetch_source);
- local _reuse=0
+ local -a _prepare_source=(setup_env fetch_source);
+ local -i _reuse=0
if [[ ${FLAGS_reuse} -eq ${FLAGS_TRUE} ]]; then
# neither install packages, nor sync sources; skip to building them
_prepare_source=(setup_env)
@@ -354,7 +320,7 @@
"${project_zone_flags[@]}" \
"${FLAGS_gce_instance}"
fi
- if [ ${FLAGS_arm} -eq ${FLAGS_TRUE} ]; then
+ if [[ ${FLAGS_arm} -eq ${FLAGS_TRUE} ]]; then
build_on_arm_board
exit 0
fi