• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/bin/bash -r
2
3function container_exists() {
4  [[ $(docker ps -a --filter "name=^/$1$" --format '{{.Names}}') == $1 ]] && echo $1;
5}
6
7declare -A map_uname_to_docker_builder_arch=( [aarch64]=linux/arm64 [x86_64]=linux/amd64 )
8
9# inputs
10# $1 = image name
11# $2 = container name
12# $3 = architecture (x86_64 or aarch64)
13# $4 = user name
14# $5 = user ID
15# $6 = persistent?
16# $7 = path to sources dir
17# $8 = path to working dir
18# $9 = path to output dir
19# $10 = reuse image/container? (0: no reuse; 1: reuse image; 2: reuse container)
20# $11 = build image (when reuse = 0)
21# $12 = path to Dockerfile
22# $13 = path to docker context dir
23# $14 = docker_flags_len
24# $15 = (docker_flags)
25# $16 = _prepare_source_len
26# $17 = (_prepare_source)
27function build_with_docker() {
28  set -o errexit
29  set -x
30
31  local -a _docker_target=( ${1} )
32  local _container_name=${2}
33  local _arch=${3}
34  local _docker_image=${1}_${_arch}
35  local _user=${4}
36  local _uid=${5}
37  local _persistent=${6}
38
39  if [[ ${_persistent} -eq 1 ]]; then
40    _docker_image=${1}_${_arch}_persistent
41  fi
42  local _docker_source=
43  if [ "${7}" != 'x' ]; then
44    _docker_source="-v ${7#x}:/source:rw"
45  fi
46  local _docker_working=
47  if [ "${8}" != 'x' ]; then
48    _docker_working="-v ${8#x}:/working:rw"
49  fi
50  local _docker_output=
51  if [ "${9}" != 'x' ]; then
52    _docker_output="-v ${9#x}:/output:rw"
53  fi
54  local _reuse=${10}
55  local _build_image=${11}
56  local _dockerfile=${12}
57  local _docker_context=${13}
58  shift 13
59  local -a _args=("$@")
60  local -i _docker_flags_len=${_args[0]}
61  local -a _docker_flags=("${_args[@]:1:$_docker_flags_len}")
62  local -i _prepare_source_len=${_args[(_docker_flags_len+1)]}
63  local -a _prepare_source=("${_args[@]:(_docker_flags_len+2):_prepare_source_len}")
64
65  local _build_or_retry=${_arch}_retry
66
67  if [[ ${_reuse} -ne 1 ]]; then
68    _build_or_retry=${_arch}_build
69    if [[ ${_persistent} -eq 1 ]]; then
70      _docker_target+=("${_docker_target[0]}_persistent")
71    fi
72    if [[ ${_build_image} -eq 1 ]]; then
73      if [[ ${_arch} != $(uname -m) ]]; then
74        export DOCKER_CLI_EXPERIMENTAL=enabled
75        # from
76        # https://community.arm.com/developer/tools-software/tools/b/tools-software-ides-blog/posts/getting-started-with-docker-for-arm-on-linux
77        docker run --rm --privileged docker/binfmt:820fdd95a9972a5308930a2bdfb8573dd4447ad3
78        docker buildx create \
79          --name docker_vmm_${_arch}_builder \
80          --platform ${map_uname_to_docker_builder_arch[${_arch}]} \
81          --use
82        docker buildx inspect --bootstrap
83        for _target in ${_docker_target[@]}; do
84          docker buildx build \
85            --platform ${map_uname_to_docker_builder_arch[${_arch}]} \
86            --target ${_target} \
87            -f ${_dockerfile} \
88            -t ${_docker_image}:latest \
89            ${_docker_context} \
90            --build-arg USER=${_user} \
91            --build-arg UID=${_uid} --load
92        done
93        docker buildx rm docker_vmm_${_arch}_builder
94        unset DOCKER_CLI_EXPERIMENTAL
95      else
96        for _target in ${_docker_target[@]}; do
97          docker build \
98            -f ${_dockerfile} \
99            --target ${_target} \
100            -t ${_docker_image}:latest \
101            ${_docker_context} \
102            --build-arg USER=${_user} \
103            --build-arg UID=${_uid}
104        done
105      fi
106    fi
107    if [[ ${_persistent} -eq 1 ]]; then
108      if [[ -n "$(container_exists ${_container_name})" ]]; then
109        docker rm -f ${_container_name}
110      fi
111      docker run -d \
112        --privileged \
113        --name ${_container_name} \
114        -h ${_container_name} \
115        ${_docker_source} \
116        ${_docker_working} \
117        ${_docker_output} \
118        -v /sys/fs/cgroup:/sys/fs/cgroup:ro \
119        ${_docker_image}:latest
120    fi
121#  else
122#    # If we are reusing the docker image, then we cannot change the target
123#    # architecture (though we can change the persistence) of the container.
124#    echo TODO
125  fi
126
127  if [[ ${_persistent} -eq 1 ]]; then
128    if [[ "$(docker inspect --format='{{.State.Status}}' ${_container_name})" == "paused" ]]; then
129      docker unpause ${_container_name}
130    fi
131    docker exec -it \
132      --user ${_user} \
133      ${_docker_flags[@]} \
134      ${_container_name} \
135      /static/rebuild-internal.sh ${_prepare_source[@]} ${_build_or_retry}
136    docker pause ${_container_name}
137  else
138    docker run -it --rm \
139      --user ${_user} \
140      ${_docker_flags[@]} \
141      ${_docker_source} \
142      ${_docker_working} \
143      ${_docker_output} \
144      ${_docker_image}:latest \
145      /static/rebuild-internal.sh ${_prepare_source[@]} ${_build_or_retry}
146  fi
147}
148
149build_with_docker $@
150