xref: /llvm-project/llvm/utils/docker/build_docker_image.sh (revision 5136c6d9d207b72135c92567e58e5cdbb86efc09)
1#!/bin/bash
2#===- llvm/utils/docker/build_docker_image.sh ----------------------------===//
3#
4# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5# See https://llvm.org/LICENSE.txt for license information.
6# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7#
8#===----------------------------------------------------------------------===//
9set -e
10
11IMAGE_SOURCE=""
12DOCKER_REPOSITORY=""
13DOCKER_TAG=""
14BUILDSCRIPT_ARGS=""
15CHECKOUT_ARGS=""
16CMAKE_ENABLED_PROJECTS=""
17
18function show_usage() {
19  cat << EOF
20Usage: build_docker_image.sh [options] [-- [cmake_args]...]
21
22Available options:
23  General:
24    -h|--help               show this help message
25  Docker-specific:
26    -s|--source             image source dir (i.e. debian12, nvidia-cuda, etc)
27    -d|--docker-repository  docker repository for the image
28    -t|--docker-tag         docker tag for the image
29  Checkout arguments:
30    -b|--branch         git branch to checkout, i.e. 'main',
31                        'release/10.x'
32                        (default: 'main')
33    -r|--revision       git revision to checkout
34    -c|--cherrypick     revision to cherry-pick. Can be specified multiple times.
35                        Cherry-picks are performed in the sorted order using the
36                        following command:
37                        'git cherry-pick \$rev'.
38    -p|--llvm-project   Add the project to a list LLVM_ENABLE_PROJECTS, passed to
39                        CMake.
40                        Can be specified multiple times.
41    --checksums         name of a file, containing checksums of llvm checkout.
42                        Script will fail if checksums of the checkout do not
43                        match.
44  Build-specific:
45    -i|--install-target name of a cmake install target to build and include in
46                        the resulting archive. Can be specified multiple times.
47
48Required options: --source and --docker-repository, at least one
49  --install-target.
50
51All options after '--' are passed to CMake invocation.
52
53For example, running:
54$ build_docker_image.sh -s debian12 -d mydocker/debian12-clang -t latest \
55  -p clang -i install-clang -i install-clang-resource-headers
56will produce two docker images:
57    mydocker/debian12-clang-build:latest - an intermediate image used to compile
58      clang.
59    mydocker/clang-debian12:latest       - a small image with preinstalled clang.
60Please note that this example produces a not very useful installation, since it
61doesn't override CMake defaults, which produces a Debug and non-boostrapped
62version of clang.
63
64To get a 2-stage clang build, you could use this command:
65$ ./build_docker_image.sh -s debian12 -d mydocker/clang-debian12 -t "latest" \
66    -p clang -i stage2-install-clang -i stage2-install-clang-resource-headers \ 
67    -- \ 
68    -DLLVM_TARGETS_TO_BUILD=Native -DCMAKE_BUILD_TYPE=Release \ 
69    -DBOOTSTRAP_CMAKE_BUILD_TYPE=Release \ 
70    -DCLANG_ENABLE_BOOTSTRAP=ON \ 
71    -DCLANG_BOOTSTRAP_TARGETS="install-clang;install-clang-resource-headers"
72EOF
73}
74
75CHECKSUMS_FILE=""
76SEEN_INSTALL_TARGET=0
77SEEN_CMAKE_ARGS=0
78while [[ $# -gt 0 ]]; do
79  case "$1" in
80    -h|--help)
81      show_usage
82      exit 0
83      ;;
84    -s|--source)
85      shift
86      IMAGE_SOURCE="$1"
87      shift
88      ;;
89    -d|--docker-repository)
90      shift
91      DOCKER_REPOSITORY="$1"
92      shift
93      ;;
94    -t|--docker-tag)
95      shift
96      DOCKER_TAG="$1"
97      shift
98      ;;
99    -r|--revision|-c|--cherrypick|-b|--branch)
100      CHECKOUT_ARGS="$CHECKOUT_ARGS $1 $2"
101      shift 2
102      ;;
103    -i|--install-target)
104      SEEN_INSTALL_TARGET=1
105      BUILDSCRIPT_ARGS="$BUILDSCRIPT_ARGS $1 $2"
106      shift 2
107      ;;
108    -p|--llvm-project)
109      PROJ="$2"
110      CMAKE_ENABLED_PROJECTS="$CMAKE_ENABLED_PROJECTS;$PROJ"
111      shift 2
112      ;;
113    --checksums)
114      shift
115      CHECKSUMS_FILE="$1"
116      shift
117      ;;
118    --)
119      shift
120      BUILDSCRIPT_ARGS="$BUILDSCRIPT_ARGS -- $*"
121      SEEN_CMAKE_ARGS=1
122      shift $#
123      ;;
124    *)
125      echo "Unknown argument $1"
126      exit 1
127      ;;
128  esac
129done
130
131
132if [ "$CMAKE_ENABLED_PROJECTS" != "" ]; then
133  # Remove the leading ';' character.
134  CMAKE_ENABLED_PROJECTS="${CMAKE_ENABLED_PROJECTS:1}"
135
136  if [[ $SEEN_CMAKE_ARGS -eq 0 ]]; then
137    BUILDSCRIPT_ARGS="$BUILDSCRIPT_ARGS --"
138  fi
139  BUILDSCRIPT_ARGS="$BUILDSCRIPT_ARGS -DLLVM_ENABLE_PROJECTS=$CMAKE_ENABLED_PROJECTS"
140fi
141
142command -v docker >/dev/null ||
143  {
144    echo "Docker binary cannot be found. Please install Docker to use this script."
145    exit 1
146  }
147
148if [ "$IMAGE_SOURCE" == "" ]; then
149  echo "Required argument missing: --source"
150  exit 1
151fi
152
153if [ "$DOCKER_REPOSITORY" == "" ]; then
154  echo "Required argument missing: --docker-repository"
155  exit 1
156fi
157
158if [ $SEEN_INSTALL_TARGET -eq 0 ]; then
159  echo "Please provide at least one --install-target"
160  exit 1
161fi
162
163SOURCE_DIR=$(dirname "$0")
164if [ ! -d "$SOURCE_DIR/$IMAGE_SOURCE" ]; then
165  echo "No sources for '$IMAGE_SOURCE' were found in $SOURCE_DIR"
166  exit 1
167fi
168
169BUILD_DIR=$(mktemp -d)
170trap "rm -rf $BUILD_DIR" EXIT
171echo "Using a temporary directory for the build: $BUILD_DIR"
172
173cp -r "$SOURCE_DIR/$IMAGE_SOURCE" "$BUILD_DIR/$IMAGE_SOURCE"
174cp -r "$SOURCE_DIR/scripts" "$BUILD_DIR/scripts"
175
176mkdir "$BUILD_DIR/checksums"
177if [ "$CHECKSUMS_FILE" != "" ]; then
178  cp "$CHECKSUMS_FILE" "$BUILD_DIR/checksums/checksums.txt"
179fi
180
181if [ "$DOCKER_TAG" != "" ]; then
182  DOCKER_TAG=":$DOCKER_TAG"
183fi
184
185echo "Building ${DOCKER_REPOSITORY}${DOCKER_TAG} from $IMAGE_SOURCE"
186docker build -t "${DOCKER_REPOSITORY}${DOCKER_TAG}" \
187  --build-arg "checkout_args=$CHECKOUT_ARGS" \
188  --build-arg "buildscript_args=$BUILDSCRIPT_ARGS" \
189  -f "$BUILD_DIR/$IMAGE_SOURCE/Dockerfile" \
190  "$BUILD_DIR"
191echo "Done"
192