#!/bin/bash #===- llvm/utils/docker/build_docker_image.sh ----------------------------===// # # Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. # See https://llvm.org/LICENSE.txt for license information. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception # #===----------------------------------------------------------------------===// set -e IMAGE_SOURCE="" DOCKER_REPOSITORY="" DOCKER_TAG="" BUILDSCRIPT_ARGS="" CHECKOUT_ARGS="" CMAKE_ENABLED_PROJECTS="" function show_usage() { cat << EOF Usage: build_docker_image.sh [options] [-- [cmake_args]...] Available options: General: -h|--help show this help message Docker-specific: -s|--source image source dir (i.e. debian8, nvidia-cuda, etc) -d|--docker-repository docker repository for the image -t|--docker-tag docker tag for the image Checkout arguments: -b|--branch svn branch to checkout, i.e. 'trunk', 'branches/release_40' (default: 'trunk') -r|--revision svn revision to checkout -c|--cherrypick revision to cherry-pick. Can be specified multiple times. Cherry-picks are performed in the sorted order using the following command: 'svn patch <(svn diff -c \$rev)'. -p|--llvm-project name of an svn project to checkout. Will also add the project to a list LLVM_ENABLE_PROJECTS, passed to CMake. For clang, please use 'clang', not 'cfe'. Project 'llvm' is always included and ignored, if specified. Can be specified multiple times. -c|--checksums name of a file, containing checksums of llvm checkout. Script will fail if checksums of the checkout do not match. Build-specific: -i|--install-target name of a cmake install target to build and include in the resulting archive. Can be specified multiple times. Required options: --source and --docker-repository, at least one --install-target. All options after '--' are passed to CMake invocation. For example, running: $ build_docker_image.sh -s debian8 -d mydocker/debian8-clang -t latest \ -p clang -i install-clang -i install-clang-resource-headers will produce two docker images: mydocker/debian8-clang-build:latest - an intermediate image used to compile clang. mydocker/clang-debian8:latest - a small image with preinstalled clang. Please note that this example produces a not very useful installation, since it doesn't override CMake defaults, which produces a Debug and non-boostrapped version of clang. To get a 2-stage clang build, you could use this command: $ ./build_docker_image.sh -s debian8 -d mydocker/clang-debian8 -t "latest" \ -p clang -i stage2-install-clang -i stage2-install-clang-resource-headers \ -- \ -DLLVM_TARGETS_TO_BUILD=Native -DCMAKE_BUILD_TYPE=Release \ -DBOOTSTRAP_CMAKE_BUILD_TYPE=Release \ -DCLANG_ENABLE_BOOTSTRAP=ON \ -DCLANG_BOOTSTRAP_TARGETS="install-clang;install-clang-resource-headers" EOF } CHECKSUMS_FILE="" SEEN_INSTALL_TARGET=0 SEEN_CMAKE_ARGS=0 while [[ $# -gt 0 ]]; do case "$1" in -h|--help) show_usage exit 0 ;; -s|--source) shift IMAGE_SOURCE="$1" shift ;; -d|--docker-repository) shift DOCKER_REPOSITORY="$1" shift ;; -t|--docker-tag) shift DOCKER_TAG="$1" shift ;; -r|--revision|-c|-cherrypick|-b|--branch) CHECKOUT_ARGS="$CHECKOUT_ARGS $1 $2" shift 2 ;; -i|--install-target) SEEN_INSTALL_TARGET=1 BUILDSCRIPT_ARGS="$BUILDSCRIPT_ARGS $1 $2" shift 2 ;; -p|--llvm-project) PROJ="$2" if [ "$PROJ" == "cfe" ]; then PROJ="clang" fi CHECKOUT_ARGS="$CHECKOUT_ARGS $1 $PROJ" if [ "$PROJ" != "clang-tools-extra" ]; then CMAKE_ENABLED_PROJECTS="$CMAKE_ENABLED_PROJECTS;$PROJ" fi shift 2 ;; -c|--checksums) shift CHECKSUMS_FILE="$1" shift ;; --) shift BUILDSCRIPT_ARGS="$BUILDSCRIPT_ARGS -- $*" SEEN_CMAKE_ARGS=1 shift $# ;; *) echo "Unknown argument $1" exit 1 ;; esac done if [ "$CMAKE_ENABLED_PROJECTS" != "" ]; then # Remove the leading ';' character. CMAKE_ENABLED_PROJECTS="${CMAKE_ENABLED_PROJECTS:1}" if [[ $SEEN_CMAKE_ARGS -eq 0 ]]; then BUILDSCRIPT_ARGS="$BUILDSCRIPT_ARGS --" fi BUILDSCRIPT_ARGS="$BUILDSCRIPT_ARGS -DLLVM_ENABLE_PROJECTS=$CMAKE_ENABLED_PROJECTS" fi command -v docker >/dev/null || { echo "Docker binary cannot be found. Please install Docker to use this script." exit 1 } if [ "$IMAGE_SOURCE" == "" ]; then echo "Required argument missing: --source" exit 1 fi if [ "$DOCKER_REPOSITORY" == "" ]; then echo "Required argument missing: --docker-repository" exit 1 fi if [ $SEEN_INSTALL_TARGET -eq 0 ]; then echo "Please provide at least one --install-target" exit 1 fi SOURCE_DIR=$(dirname $0) if [ ! -d "$SOURCE_DIR/$IMAGE_SOURCE" ]; then echo "No sources for '$IMAGE_SOURCE' were found in $SOURCE_DIR" exit 1 fi BUILD_DIR=$(mktemp -d) trap "rm -rf $BUILD_DIR" EXIT echo "Using a temporary directory for the build: $BUILD_DIR" cp -r "$SOURCE_DIR/$IMAGE_SOURCE" "$BUILD_DIR/$IMAGE_SOURCE" cp -r "$SOURCE_DIR/scripts" "$BUILD_DIR/scripts" mkdir "$BUILD_DIR/checksums" if [ "$CHECKSUMS_FILE" != "" ]; then cp "$CHECKSUMS_FILE" "$BUILD_DIR/checksums/checksums.txt" fi if [ "$DOCKER_TAG" != "" ]; then DOCKER_TAG=":$DOCKER_TAG" fi echo "Building ${DOCKER_REPOSITORY}${DOCKER_TAG} from $IMAGE_SOURCE" docker build -t "${DOCKER_REPOSITORY}${DOCKER_TAG}" \ --build-arg "checkout_args=$CHECKOUT_ARGS" \ --build-arg "buildscript_args=$BUILDSCRIPT_ARGS" \ -f "$BUILD_DIR/$IMAGE_SOURCE/Dockerfile" \ "$BUILD_DIR" echo "Done"