Extract docker-build logic into its own file.
To prepare for invoking it on ARM boards and GCE.
Test: build
Bug: 148642775 Clean up the crosvm build
Change-Id: Icaedd3340ca74a2f647e48a622a4edea73bc5ebf
Signed-off-by: Iliyan Malchev <malchev@google.com>
diff --git a/rebuild-docker.sh b/rebuild-docker.sh
new file mode 100755
index 0000000..ab9dc13
--- /dev/null
+++ b/rebuild-docker.sh
@@ -0,0 +1,140 @@
+#!/bin/bash -r
+
+function container_exists() {
+ [[ $(docker ps -a --filter "name=^/$1$" --format '{{.Names}}') == $1 ]] && echo $1;
+}
+
+# inputs
+# $1 = image name
+# $2 = container name
+# $3 = architecture (x86_64 or aarch64)
+# $4 = user name
+# $5 = user ID
+# $6 = persistent?
+# $7 = path to sources dir
+# $8 = path to working dir
+# $9 = path to output dir
+# $10 = reuse image/container? (0: no reuse; 1: reuse image; 2: reuse container)
+# $11 = build image (when reuse = 0)
+# $11 = path to Dockerfile
+# $12 = path to docker context dir
+# $13 = docker_flags_len
+# $14 = (docker_flags)
+# $15 = _prepare_source_len
+# $16 = (_prepare_source)
+function build_with_docker() {
+ set -o errexit
+ set -x
+
+ local -a _docker_target=( ${1} )
+ local _container_name=${2}
+ local _arch=${3}
+ local _docker_image=${1}_${_arch}
+ local _user=${4}
+ local _uid=${5}
+ local _persistent=${6}
+
+ if [[ ${_persistent} -eq 1 ]]; then
+ _docker_image=${1}_${_arch}_persistent
+ fi
+ local _docker_source=
+ if [ "${7}" != 'x' ]; then
+ _docker_source="-v ${7#x}:/source:rw"
+ fi
+ local _docker_working=
+ if [ "${8}" != 'x' ]; then
+ _docker_working="-v ${8#x}:/working:rw"
+ fi
+ local _docker_output=
+ if [ "${9}" != 'x' ]; then
+ _docker_output="-v ${9#x}:/output:rw"
+ fi
+ local _reuse=${10}
+ local _build_image=${11}
+ local _dockerfile=${12}
+ local _docker_context=${13}
+ shift 13
+ local -a _args=("$@")
+ local -i _docker_flags_len=${_args[0]}
+ local -a _docker_flags=("${_args[@]:1:$_docker_flags_len}")
+ local -i _prepare_source_len=${_args[(_docker_flags_len+1)]}
+ local -a _prepare_source=("${_args[@]:(_docker_flags_len+2):_prepare_source_len}")
+
+ local _build_or_retry=${_arch}_retry
+
+ if [[ ${_reuse} -ne 1 ]]; then
+ _build_or_retry=${_arch}_build
+ if [[ ${_persistent} -eq 1 ]]; then
+ _docker_target+=("${_docker_target[0]}_persistent")
+ fi
+ if [[ ${_build_image} -eq 1 ]]; then
+ if [[ ${_arch} == aarch64 ]]; then
+ export DOCKER_CLI_EXPERIMENTAL=enabled
+ docker buildx create --name docker_vmm_${_arch}_builder --platform linux/arm64 --use
+ for _target in ${_docker_target[@]}; do
+ docker buildx build \
+ --platform ${map_uname_to_docker_builder_arch[${_arch}]} \
+ --target ${_target} \
+ -f ${_dockerfile} \
+ -t ${_docker_image}:latest \
+ ${_docker_context} \
+ --build-arg USER=${_user} \
+ --build-arg UID=${_uid} --load
+ done
+ docker buildx rm docker_vmm_${_arch}_builder
+ unset DOCKER_CLI_EXPERIMENTAL
+ else
+ for _target in ${_docker_target[@]}; do
+ docker build \
+ -f ${_dockerfile} \
+ --target ${_target} \
+ -t ${_docker_image}:latest \
+ ${_docker_context} \
+ --build-arg USER=${_user} \
+ --build-arg UID=${_uid}
+ done
+ fi
+ fi
+ if [[ ${_persistent} -eq 1 ]]; then
+ if [[ -n "$(container_exists ${_container_name})" ]]; then
+ docker rm -f ${_container_name}
+ fi
+ docker run -d \
+ --privileged \
+ --name ${_container_name} \
+ -h ${_container_name} \
+ ${_docker_source} \
+ ${_docker_working} \
+ ${_docker_output} \
+ -v /sys/fs/cgroup:/sys/fs/cgroup:ro \
+ ${_docker_image}:latest
+ fi
+# else
+# # If we are reusing the docker image, then we cannot change the target
+# # architecture (though we can change the persistence) of the container.
+# echo TODO
+ fi
+
+ if [[ ${_persistent} -eq 1 ]]; then
+ if [[ "$(docker inspect --format='{{.State.Status}}' ${_container_name})" == "paused" ]]; then
+ docker unpause ${_container_name}
+ fi
+ docker exec -it \
+ --user ${_user} \
+ ${_docker_flags[@]} \
+ ${_container_name} \
+ /static/rebuild-internal.sh ${_prepare_source[@]} ${_build_or_retry}
+ docker pause ${_container_name}
+ else
+ docker run -it --rm \
+ --user ${_user} \
+ ${_docker_flags[@]} \
+ ${_docker_source} \
+ ${_docker_working} \
+ ${_docker_output} \
+ ${_docker_image}:latest \
+ /static/rebuild-internal.sh ${_prepare_source[@]} ${_build_or_retry}
+ fi
+}
+
+build_with_docker $@
diff --git a/rebuild.sh b/rebuild.sh
index 5378f3f..2e66863 100755
--- a/rebuild.sh
+++ b/rebuild.sh
@@ -63,6 +63,153 @@
[[ $(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() {
+ 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
+ # 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
+ # use docker run, which creates and runs the continer in one step; in that
+ # case, we must pass the same values for --docker_source and --docker_output
+ # that we passed when we ran the non-persistent continer the first time.
+ if [[ ${_reuse} -eq 1 && ${FLAGS_docker_persistent} -eq ${FLAGS_TRUE} ]]; then
+ if [ -n "${FLAGS_docker_source}" ]; then
+ echo Option --docker_source may not be specified with --reuse 1>&2
+ fail=1
+ fi
+ if [ -n "${FLAGS_docker_working}" ]; then
+ echo Option --docker_working may not be specified with --reuse 1>&2
+ fail=1
+ fi
+ fi
+ 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"
+ fi
+ local _docker_working=
+ if [ -n "${FLAGS_docker_working}" ]; then
+ _docker_working="-v ${FLAGS_docker_working}:/working:rw"
+ 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
+}
+
function build_on_gce() {
if [[ -z "${FLAGS_gce_instance}" ]]; then
echo Must specify instance 1>&2
@@ -163,139 +310,6 @@
"${ANDROID_BUILD_TOP}/device/google/cuttlefish_vmm"
}
-build_locally_using_docker() {
- 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
- # 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
- # use docker run, which creates and runs the continer in one step; in that
- # case, we must pass the same values for --docker_source and --docker_output
- # that we passed when we ran the non-persistent continer the first time.
- if [[ ${_reuse} -eq 1 && ${FLAGS_docker_persistent} -eq ${FLAGS_TRUE} ]]; then
- if [ -n "${FLAGS_docker_source}" ]; then
- echo Option --docker_source may not be specified with --reuse 1>&2
- fail=1
- fi
- if [ -n "${FLAGS_docker_working}" ]; then
- echo Option --docker_working may not be specified with --reuse 1>&2
- fail=1
- fi
- fi
- if [[ "${fail}" -ne 0 ]]; then
- exit "${fail}"
- fi
- _docker_source=
- if [ -n "${FLAGS_docker_source}" ]; then
- _docker_source="-v ${FLAGS_docker_source}:/source:rw"
- fi
- _docker_working=
- if [ -n "${FLAGS_docker_working}" ]; then
- _docker_working="-v ${FLAGS_docker_working}:/working:rw"
- 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
-}
-
main() {
set -o errexit
set -x