xref: /aosp_15_r20/external/cpu_features/scripts/run_integration.sh (revision eca53ba6d2e951e174b64682eaf56a36b8204c89)
1#!/usr/bin/env bash
2set -eo pipefail
3
4function extract() {
5  echo "Extracting ${1}..."
6  case $1 in
7    *.tar.bz2)   tar xjf "$1"    ;;
8    *.tar.xz)    tar xJf "$1"    ;;
9    *.tar.gz)    tar xzf "$1"    ;;
10    *)
11      >&2 echo "don't know how to extract '$1'..."
12      exit 1
13  esac
14}
15
16function unpack() {
17  mkdir -p "${ARCHIVE_DIR}"
18  cd "${ARCHIVE_DIR}" || exit 2
19  local -r URL=$1
20  local -r RELATIVE_DIR=$2
21  local -r DESTINATION="${ARCHIVE_DIR}/${RELATIVE_DIR}"
22  if [[  ! -d "${DESTINATION}" ]] ; then
23    echo "Downloading ${URL}..."
24    local -r ARCHIVE_NAME=$(basename "${URL}")
25    [[ -f "${ARCHIVE_NAME}" ]] || wget --no-verbose "${URL}"
26    extract "${ARCHIVE_NAME}"
27    rm -f "${ARCHIVE_NAME}"
28  fi
29}
30
31function install_qemu() {
32  if [[ "${QEMU_ARCH}" == "DISABLED" ]]; then
33    >&2 echo 'QEMU is disabled !'
34    return 0
35  fi
36  local -r QEMU_VERSION=${QEMU_VERSION:=7.1.0}
37  local -r QEMU_TARGET=${QEMU_ARCH}-linux-user
38
39  if echo "${QEMU_VERSION} ${QEMU_TARGET}" | cmp --silent "${QEMU_INSTALL}/.build" -; then
40    echo "qemu ${QEMU_VERSION} up to date!"
41    return 0
42  fi
43
44  echo "QEMU_VERSION: ${QEMU_VERSION}"
45  echo "QEMU_TARGET: ${QEMU_TARGET}"
46
47  rm -rf "${QEMU_INSTALL}"
48
49  # Checking for a tarball before downloading makes testing easier :-)
50  local -r QEMU_URL="http://wiki.qemu-project.org/download/qemu-${QEMU_VERSION}.tar.xz"
51  local -r QEMU_DIR="qemu-${QEMU_VERSION}"
52  unpack ${QEMU_URL} ${QEMU_DIR}
53  cd ${QEMU_DIR} || exit 2
54
55  # Qemu (meson based build) depends on: pkgconf, libglib2.0, python3, ninja
56  ./configure \
57    --prefix="${QEMU_INSTALL}" \
58    --target-list="${QEMU_TARGET}" \
59    --audio-drv-list= \
60    --disable-brlapi \
61    --disable-curl \
62    --disable-curses \
63    --disable-docs \
64    --disable-gcrypt \
65    --disable-gnutls \
66    --disable-gtk \
67    --disable-libnfs \
68    --disable-libssh \
69    --disable-nettle \
70    --disable-opengl \
71    --disable-sdl \
72    --disable-virglrenderer \
73    --disable-vte
74
75  # wrapper on ninja
76  make -j8
77  make install
78
79  echo "$QEMU_VERSION $QEMU_TARGET" > "${QEMU_INSTALL}/.build"
80}
81
82function assert_defined(){
83  if [[ -z "${!1}" ]]; then
84    >&2 echo "Variable '${1}' must be defined"
85    exit 1
86  fi
87}
88
89function clean_build() {
90  # Cleanup previous build
91  rm -rf "${BUILD_DIR}"
92  mkdir -p "${BUILD_DIR}"
93}
94
95function expand_linaro_config() {
96  #ref: https://releases.linaro.org/components/toolchain/binaries/
97  local -r LINARO_VERSION=7.5-2019.12
98  local -r LINARO_ROOT_URL=https://releases.linaro.org/components/toolchain/binaries/${LINARO_VERSION}
99
100  local -r GCC_VERSION=7.5.0-2019.12
101  local -r GCC_URL=${LINARO_ROOT_URL}/${TARGET}/gcc-linaro-${GCC_VERSION}-x86_64_${TARGET}.tar.xz
102  local -r GCC_RELATIVE_DIR="gcc-linaro-${GCC_VERSION}-x86_64_${TARGET}"
103  unpack "${GCC_URL}" "${GCC_RELATIVE_DIR}"
104
105  local -r SYSROOT_VERSION=2.25-2019.12
106  local -r SYSROOT_URL=${LINARO_ROOT_URL}/${TARGET}/sysroot-glibc-linaro-${SYSROOT_VERSION}-${TARGET}.tar.xz
107  local -r SYSROOT_RELATIVE_DIR=sysroot-glibc-linaro-${SYSROOT_VERSION}-${TARGET}
108  unpack "${SYSROOT_URL}" "${SYSROOT_RELATIVE_DIR}"
109
110  local -r SYSROOT_DIR=${ARCHIVE_DIR}/${SYSROOT_RELATIVE_DIR}
111  local -r STAGING_DIR=${ARCHIVE_DIR}/${SYSROOT_RELATIVE_DIR}-stage
112  local -r GCC_DIR=${ARCHIVE_DIR}/${GCC_RELATIVE_DIR}
113
114  # Write a Toolchain file
115  # note: This is manadatory to use a file in order to have the CMake variable
116  # 'CMAKE_CROSSCOMPILING' set to TRUE.
117  # ref: https://cmake.org/cmake/help/latest/manual/cmake-toolchains.7.html#cross-compiling-for-linux
118  cat >"$TOOLCHAIN_FILE" <<EOL
119set(CMAKE_SYSTEM_NAME Linux)
120set(CMAKE_SYSTEM_PROCESSOR ${TARGET})
121
122set(CMAKE_SYSROOT ${SYSROOT_DIR})
123set(CMAKE_STAGING_PREFIX ${STAGING_DIR})
124
125set(tools ${GCC_DIR})
126set(CMAKE_C_COMPILER \${tools}/bin/${TARGET}-gcc)
127set(CMAKE_CXX_COMPILER \${tools}/bin/${TARGET}-g++)
128
129set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
130set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
131set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
132set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
133EOL
134CMAKE_ADDITIONAL_ARGS+=( -DCMAKE_TOOLCHAIN_FILE="${TOOLCHAIN_FILE}" )
135QEMU_ARGS+=( -L "${SYSROOT_DIR}" )
136QEMU_ARGS+=( -E LD_LIBRARY_PATH=/lib )
137}
138
139function expand_bootlin_config() {
140  # ref: https://toolchains.bootlin.com/
141  local -r GCC_DIR=${ARCHIVE_DIR}/${GCC_RELATIVE_DIR}
142
143  case "${TARGET}" in
144    "aarch64")
145      local -r TOOLCHAIN_URL="https://toolchains.bootlin.com/downloads/releases/toolchains/aarch64/tarballs/aarch64--glibc--stable-2021.11-1.tar.bz2"
146      local -r GCC_PREFIX="aarch64"
147      ;;
148    "aarch64be")
149      local -r TOOLCHAIN_URL="https://toolchains.bootlin.com/downloads/releases/toolchains/aarch64be/tarballs/aarch64be--glibc--stable-2021.11-1.tar.bz2"
150      local -r GCC_PREFIX="aarch64_be"
151      ;;
152    "ppc64le")
153      local -r TOOLCHAIN_URL="https://toolchains.bootlin.com/downloads/releases/toolchains/powerpc64le-power8/tarballs/powerpc64le-power8--glibc--stable-2021.11-1.tar.bz2"
154      local -r GCC_PREFIX="powerpc64le"
155      ;;
156    "ppc64")
157      local -r TOOLCHAIN_URL="https://toolchains.bootlin.com/downloads/releases/toolchains/powerpc64-power8/tarballs/powerpc64-power8--glibc--stable-2021.11-1.tar.bz2"
158      local -r GCC_PREFIX="powerpc64"
159      ;;
160    "ppc")
161      #local -r TOOLCHAIN_URL="https://toolchains.bootlin.com/downloads/releases/toolchains/powerpc-e500mc/tarballs/powerpc-e500mc--glibc--stable-2021.11-1.tar.bz2"
162      local -r TOOLCHAIN_URL="https://toolchains.bootlin.com/downloads/releases/toolchains/powerpc-440fp/tarballs/powerpc-440fp--glibc--stable-2021.11-1.tar.bz2"
163      local -r GCC_PREFIX="powerpc"
164      ;;
165    "riscv32")
166      local -r TOOLCHAIN_URL="https://toolchains.bootlin.com/downloads/releases/toolchains/riscv32-ilp32d/tarballs/riscv32-ilp32d--glibc--bleeding-edge-2022.08-1.tar.bz2"
167      local -r GCC_PREFIX="riscv32"
168      ;;
169    "riscv64")
170      local -r TOOLCHAIN_URL="https://toolchains.bootlin.com/downloads/releases/toolchains/riscv64-lp64d/tarballs/riscv64-lp64d--glibc--stable-2022.08-1.tar.bz2"
171      local -r GCC_PREFIX="riscv64"
172      ;;
173    "s390x")
174      local -r TOOLCHAIN_URL="https://toolchains.bootlin.com/downloads/releases/toolchains/s390x-z13/tarballs/s390x-z13--glibc--stable-2022.08-1.tar.bz2"
175      local -r GCC_PREFIX="s390x"
176      ;;
177    *)
178      >&2 echo 'unknown power platform'
179      exit 1 ;;
180  esac
181
182  local -r TOOLCHAIN_RELATIVE_DIR="${TARGET}"
183  unpack "${TOOLCHAIN_URL}" "${TOOLCHAIN_RELATIVE_DIR}"
184  local -r EXTRACT_DIR="${ARCHIVE_DIR}/$(basename ${TOOLCHAIN_URL%.tar.bz2})"
185
186  local -r TOOLCHAIN_DIR=${ARCHIVE_DIR}/${TOOLCHAIN_RELATIVE_DIR}
187  if [[ -d "${EXTRACT_DIR}" ]]; then
188    mv "${EXTRACT_DIR}" "${TOOLCHAIN_DIR}"
189  fi
190
191  local -r SYSROOT_DIR="${TOOLCHAIN_DIR}/${GCC_PREFIX}-buildroot-linux-gnu/sysroot"
192  #local -r STAGING_DIR=${SYSROOT_DIR}-stage
193
194  # Write a Toolchain file
195  # note: This is manadatory to use a file in order to have the CMake variable
196  # 'CMAKE_CROSSCOMPILING' set to TRUE.
197  # ref: https://cmake.org/cmake/help/latest/manual/cmake-toolchains.7.html#cross-compiling-for-linux
198  cat >"${TOOLCHAIN_FILE}" <<EOL
199set(CMAKE_SYSTEM_NAME Linux)
200set(CMAKE_SYSTEM_PROCESSOR ${GCC_PREFIX})
201
202set(CMAKE_SYSROOT ${SYSROOT_DIR})
203#set(CMAKE_STAGING_PREFIX ${STAGING_DIR})
204
205set(tools ${TOOLCHAIN_DIR})
206
207set(CMAKE_C_COMPILER \${tools}/bin/${GCC_PREFIX}-linux-gcc)
208set(CMAKE_C_FLAGS "${POWER_FLAGS}")
209set(CMAKE_CXX_COMPILER \${tools}/bin/${GCC_PREFIX}-linux-g++)
210set(CMAKE_CXX_FLAGS "${POWER_FLAGS} -L${SYSROOT_DIR}/lib")
211
212set(CMAKE_FIND_ROOT_PATH ${TOOLCHAIN_DIR})
213set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
214set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
215set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
216set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
217EOL
218
219CMAKE_ADDITIONAL_ARGS+=( -DCMAKE_TOOLCHAIN_FILE="${TOOLCHAIN_FILE}" )
220QEMU_ARGS+=( -L "${SYSROOT_DIR}" )
221QEMU_ARGS+=( -E LD_PRELOAD="${SYSROOT_DIR}/usr/lib/libstdc++.so.6:${SYSROOT_DIR}/lib/libgcc_s.so.1" )
222}
223
224function expand_codescape_config() {
225  # https://www.mips.com/develop/tools/codescape-mips-sdk/mips-toolchain-configurations/
226  # mips-mti: MIPS32R6 and MIPS64R6
227  # mips-img: MIPS32R2 and MIPS64R2
228
229  # ref: https://codescape.mips.com/components/toolchain/2020.06-01/downloads.html
230  local -r DATE=2020.06-01
231  local -r CODESCAPE_URL=https://codescape.mips.com/components/toolchain/${DATE}/Codescape.GNU.Tools.Package.${DATE}.for.MIPS.MTI.Linux.CentOS-6.x86_64.tar.gz
232  local -r GCC_RELATIVE_DIR="mips-mti-linux-gnu/${DATE}"
233
234  # ref: https://codescape.mips.com/components/toolchain/2019.02-04/downloads.html
235  #local -r DATE=2019.02-04
236  #local -r CODESCAPE_URL=https://codescape.mips.com/components/toolchain/${DATE}/Codescape.GNU.Tools.Package.${DATE}.for.MIPS.IMG.Linux.CentOS-6.x86_64.tar.gz
237  #local -r GCC_RELATIVE_DIR="mips-img-linux-gnu/${DATE}"
238
239  local -r GCC_URL=${CODESCAPE_URL}
240  unpack "${GCC_URL}" "${GCC_RELATIVE_DIR}"
241
242  local -r GCC_DIR=${ARCHIVE_DIR}/${GCC_RELATIVE_DIR}
243  local MIPS_FLAGS=""
244  local LIBC_DIR_SUFFIX=""
245  local FLAVOUR=""
246  case "${TARGET}" in
247    "mips32")
248      MIPS_FLAGS="-EB -mips32r6 -mabi=32"
249      FLAVOUR="mips-r6-hard"
250      #MIPS_FLAGS="-EB -mips32r2 -mabi=32"
251      #FLAVOUR="mips-r2-hard"
252      LIBC_DIR_SUFFIX="lib"
253      ;;
254    "mips32el")
255      MIPS_FLAGS="-EL -mips32r6 -mabi=32"
256      FLAVOUR="mipsel-r6-hard"
257      #MIPS_FLAGS="-EL -mips32r2 -mabi=32"
258      #FLAVOUR="mipsel-r2-hard"
259      LIBC_DIR_SUFFIX="lib"
260      ;;
261    "mips64")
262      MIPS_FLAGS="-EB -mips64r6 -mabi=64"
263      FLAVOUR="mips-r6-hard"
264      #MIPS_FLAGS="-EB -mips64r2 -mabi=64"
265      #FLAVOUR="mips-r2-hard"
266      LIBC_DIR_SUFFIX="lib64"
267      ;;
268    "mips64el")
269      MIPS_FLAGS="-EL -mips64r6 -mabi=64"
270      FLAVOUR="mipsel-r6-hard"
271      #MIPS_FLAGS="-EL -mips64r2 -mabi=64"
272      #FLAVOUR="mipsel-r2-hard"
273      LIBC_DIR_SUFFIX="lib64"
274      ;;
275    *)
276      >&2 echo 'unknown mips platform'
277      exit 1 ;;
278  esac
279  local -r SYSROOT_DIR=${GCC_DIR}/sysroot
280  local -r STAGING_DIR=${SYSROOT_DIR}-stage
281
282  # Write a Toolchain file
283  # note: This is manadatory to use a file in order to have the CMake variable
284  # 'CMAKE_CROSSCOMPILING' set to TRUE.
285  # ref: https://cmake.org/cmake/help/latest/manual/cmake-toolchains.7.html#cross-compiling-for-linux
286  cat >"${TOOLCHAIN_FILE}" <<EOL
287set(CMAKE_SYSTEM_NAME Linux)
288set(CMAKE_SYSTEM_PROCESSOR ${TARGET})
289
290set(CMAKE_SYSROOT ${SYSROOT_DIR})
291set(CMAKE_STAGING_PREFIX ${STAGING_DIR})
292
293set(tools ${GCC_DIR})
294
295# R6
296set(CMAKE_C_COMPILER \${tools}/bin/mips-mti-linux-gnu-gcc)
297set(CMAKE_C_FLAGS "${MIPS_FLAGS}")
298set(CMAKE_CXX_COMPILER \${tools}/bin/mips-mti-linux-gnu-g++)
299set(CMAKE_CXX_FLAGS "${MIPS_FLAGS} -L${SYSROOT_DIR}/usr/lib64")
300
301# R2
302#set(CMAKE_C_COMPILER \${tools}/bin/mips-img-linux-gnu-gcc)
303#set(CMAKE_C_FLAGS "${MIPS_FLAGS}")
304#set(CMAKE_CXX_COMPILER \${tools}/bin/mips-img-linux-gnu-g++)
305#set(CMAKE_CXX_FLAGS "${MIPS_FLAGS}")
306
307set(CMAKE_FIND_ROOT_PATH ${GCC_DIR})
308set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
309set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
310set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
311set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
312EOL
313
314CMAKE_ADDITIONAL_ARGS+=( -DCMAKE_TOOLCHAIN_FILE="${TOOLCHAIN_FILE}" )
315QEMU_ARGS+=( -L "${SYSROOT_DIR}/${FLAVOUR}" )
316local -r LIBC_DIR=${GCC_DIR}/mips-mti-linux-gnu/lib/${FLAVOUR}/${LIBC_DIR_SUFFIX}
317#local -r LIBC_DIR=${GCC_DIR}/mips-img-linux-gnu/lib/${FLAVOUR}/${LIBC_DIR_SUFFIX}
318QEMU_ARGS+=( -E LD_PRELOAD="${LIBC_DIR}/libstdc++.so.6:${LIBC_DIR}/libgcc_s.so.1" )
319}
320
321function build() {
322  cd "${PROJECT_DIR}" || exit 2
323  set -x
324  clean_build
325  cmake -S. -B"${BUILD_DIR}" "${CMAKE_DEFAULT_ARGS[@]}" "${CMAKE_ADDITIONAL_ARGS[@]}"
326  cmake --build "${BUILD_DIR}" --target all -j8 -v
327  set +x
328}
329
330function run_test() {
331  assert_defined QEMU_ARCH
332  if [[ "${QEMU_ARCH}" == "DISABLED" ]]; then
333    >&2 echo "QEMU is disabled for ${TARGET}"
334    return
335  fi
336  install_qemu
337  RUN_CMD="${QEMU_INSTALL}/bin/qemu-${QEMU_ARCH} ${QEMU_ARGS[*]}"
338
339  cd "${BUILD_DIR}" || exit 2
340  declare -a TEST_BINARIES=()
341  TEST_BINARIES+=($(find "${BUILD_DIR}"/test -executable -type f))
342  TEST_BINARIES+=($(find "${BUILD_DIR}" -maxdepth 1 -executable -type f))
343  set -x
344  set -e
345  for test_binary in ${TEST_BINARIES[*]} ; do
346      ${RUN_CMD} "${test_binary}"
347  done
348  set +e
349  set +x
350}
351
352function usage() {
353  local -r NAME=$(basename "$0")
354  echo -e "$NAME - Build using a cross toolchain.
355
356SYNOPSIS
357\t$NAME [-h|--help] [toolchain|build|qemu|test|all]
358
359DESCRIPTION
360\tCross compile using a cross toolchain.
361
362\tYou MUST define the following variables before running this script:
363\t* TARGET:
364\t\tx86_64
365\t\taarch64 aarch64be (bootlin)
366\t\taarch64-linux-gnu aarch64_be-linux-gnu (linaro)
367\t\tarm-linux-gnueabihf armv8l-linux-gnueabihf arm-linux-gnueabi (linaro)
368\t\tarmeb-linux-gnueabihf armeb-linux-gnueabi (linaro)
369\t\tmips32 mips32el (codespace)
370\t\tmips64 mips64el (codespace)
371\t\tppc (bootlin)
372\t\tppc64 ppc64le (bootlin)
373\t\triscv32 riscv64 (bootlin)
374\t\ts390x (bootlin)
375
376OPTIONS
377\t-h --help: show this help text
378\ttoolchain: download, unpack toolchain and generate CMake toolchain file
379\tbuild: toolchain + build the project using the toolchain file (note: remove previous build dir)
380\tqemu: download, unpack and build qemu
381\ttest: qemu + run all executable using qemu (note: don't build !)
382\tall: build + test (default)
383
384EXAMPLES
385* Using export:
386export TARGET=aarch64-linux-gnu
387$0
388
389* One-liner:
390TARGET=aarch64-linux-gnu $0"
391}
392
393# Main
394function main() {
395  case ${1} in
396    -h | --help)
397      usage; exit ;;
398  esac
399
400  assert_defined TARGET
401
402  declare -r PROJECT_DIR="$(cd -P -- "$(dirname -- "$0")/.." && pwd -P)"
403  declare -r ARCHIVE_DIR="${PROJECT_DIR}/build_cross/archives"
404  declare -r BUILD_DIR="${PROJECT_DIR}/build_cross/${TARGET}"
405  declare -r TOOLCHAIN_FILE=${ARCHIVE_DIR}/toolchain_${TARGET}.cmake
406
407  echo "Target: '${TARGET}'"
408
409  echo "Project dir: '${PROJECT_DIR}'"
410  echo "Archive dir: '${ARCHIVE_DIR}'"
411  echo "Build dir: '${BUILD_DIR}'"
412  echo "toolchain file: '${TOOLCHAIN_FILE}'"
413
414  declare -a CMAKE_DEFAULT_ARGS=( -G ${CMAKE_GENERATOR:-"Ninja"} )
415  declare -a CMAKE_ADDITIONAL_ARGS=()
416
417  declare -a QEMU_ARGS=()
418  case ${TARGET} in
419    x86_64)
420      declare -r QEMU_ARCH=x86_64 ;;
421    arm-linux-gnueabihf | armv8l-linux-gnueabihf | arm-linux-gnueabi)
422      expand_linaro_config
423      declare -r QEMU_ARCH=arm ;;
424    armeb-linux-gnueabihf | armeb-linux-gnueabi)
425      expand_linaro_config
426      declare -r QEMU_ARCH=DISABLED ;;
427    aarch64-linux-gnu)
428      expand_linaro_config
429      declare -r QEMU_ARCH=aarch64 ;;
430    aarch64_be-linux-gnu)
431      expand_linaro_config
432      declare -r QEMU_ARCH=aarch64_be ;;
433    aarch64)
434      expand_bootlin_config
435      declare -r QEMU_ARCH=aarch64 ;;
436    aarch64be)
437      expand_bootlin_config
438      declare -r QEMU_ARCH=aarch64_be ;;
439    mips32)
440      expand_codescape_config
441      declare -r QEMU_ARCH=mips ;;
442    mips32el)
443      expand_codescape_config
444      declare -r QEMU_ARCH=mipsel ;;
445    mips64)
446      expand_codescape_config
447      declare -r QEMU_ARCH=mips64 ;;
448    mips64el)
449      expand_codescape_config
450      declare -r QEMU_ARCH=mips64el ;;
451    ppc64le)
452      expand_bootlin_config
453      declare -r QEMU_ARCH=ppc64le ;;
454    ppc64)
455      expand_bootlin_config
456      declare -r QEMU_ARCH=ppc64 ;;
457    ppc)
458      expand_bootlin_config
459      declare -r QEMU_ARCH=ppc ;;
460    riscv32)
461      expand_bootlin_config
462      declare -r QEMU_ARCH=riscv32 ;;
463    riscv64)
464      expand_bootlin_config
465      declare -r QEMU_ARCH=riscv64 ;;
466    s390x)
467      expand_bootlin_config
468      declare -r QEMU_ARCH=s390x ;;
469    *)
470      >&2 echo "Unknown TARGET '${TARGET}'..."
471      exit 1 ;;
472  esac
473  declare -r QEMU_INSTALL=${ARCHIVE_DIR}/qemu-${QEMU_ARCH}
474
475  case ${1} in
476    toolchain)
477      exit ;;
478    build)
479      build ;;
480    qemu)
481      install_qemu ;;
482    test)
483      run_test ;;
484    *)
485      build
486      run_test ;;
487  esac
488}
489
490main "${1:-all}"
491