Skip to content

Commit af351da

Browse files
committed
Added Dockerfiles to build clang from sources.
Reviewers: klimek, chandlerc, mehdi_amini Reviewed By: klimek, mehdi_amini Subscribers: mehdi_amini, jlebar, llvm-commits Differential Revision: https://reviews.llvm.org/D34197 llvm-svn: 306810
1 parent 99a16aa commit af351da

File tree

11 files changed

+654
-0
lines changed

11 files changed

+654
-0
lines changed

llvm/docs/Docker.rst

Lines changed: 205 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,205 @@
1+
=========================================
2+
A guide to Dockerfiles for building LLVM
3+
=========================================
4+
5+
Introduction
6+
============
7+
You can find a number of sources to build docker images with LLVM components in
8+
``llvm/utils/docker``. They can be used by anyone who wants to build the docker
9+
images for their own use, or as a starting point for someone who wants to write
10+
their own Dockerfiles.
11+
12+
We currently provide Dockerfiles with ``debian8`` and ``nvidia-cuda`` base images.
13+
We also provide an ``example`` image, which contains placeholders that one would need
14+
to fill out in order to produce Dockerfiles for a new docker image.
15+
16+
Why?
17+
----
18+
Docker images provide a way to produce binary distributions of
19+
software inside a controlled environment. Having Dockerfiles to builds docker images
20+
inside LLVM repo makes them much more discoverable than putting them into any other
21+
place.
22+
23+
Docker basics
24+
-------------
25+
If you've never heard about Docker before, you might find this section helpful
26+
to get a very basic explanation of it.
27+
`Docker <https://www.docker.com/>`_ is a popular solution for running programs in
28+
an isolated and reproducible environment, especially to maintain releases for
29+
software deployed to large distributed fleets.
30+
It uses linux kernel namespaces and cgroups to provide a lightweight isolation
31+
inside currently running linux kernel.
32+
A single active instance of dockerized environment is called a *docker
33+
container*.
34+
A snapshot of a docker container filesystem is called a *docker image*.
35+
One can start a container from a prebuilt docker image.
36+
37+
Docker images are built from a so-called *Dockerfile*, a source file written in
38+
a specialized language that defines instructions to be used when build
39+
the docker image (see `official
40+
documentation <https://docs.docker.com/engine/reference/builder/>`_ for more
41+
details). A minimal Dockerfile typically contains a base image and a number
42+
of RUN commands that have to be executed to build the image. When building a new
43+
image, docker will first download your base image, mount its filesystem as
44+
read-only and then add a writable overlay on top of it to keep track of all
45+
filesystem modifications, performed while building your image. When the build
46+
process is finished, a diff between your image's final filesystem state and the
47+
base image's filesystem is stored in the resulting image.
48+
49+
Overview
50+
========
51+
The ``llvm/utils/docker`` folder contains Dockerfiles and simple bash scripts to
52+
serve as a basis for anyone who wants to create their own Docker image with
53+
LLVM components, compiled from sources. The sources are checked out from the
54+
upstream svn repository when building the image.
55+
56+
Inside each subfolder we host Dockerfiles for two images:
57+
58+
- ``build/`` image is used to compile LLVM, it installs a system compiler and all
59+
build dependencies of LLVM. After the build process is finished, the build
60+
image will have an archive with compiled components at ``/tmp/clang.tar.gz``.
61+
- ``release/`` image usually only contains LLVM components, compiled by the
62+
``build/`` image, and also libstdc++ and binutils to make image minimally
63+
useful for C++ development. The assumption is that you usually want clang to
64+
be one of the provided components.
65+
66+
To build both of those images, use ``build_docker_image.sh`` script.
67+
It will checkout LLVM sources and build clang in the ``build`` container, copy results
68+
of the build to the local filesystem and then build the ``release`` container using
69+
those. The ``build_docker_image.sh`` accepts a list of LLVM repositories to
70+
checkout, and arguments for CMake invocation.
71+
72+
If you want to write your own docker image, start with an ``example/`` subfolder.
73+
It provides incomplete Dockerfiles with (very few) FIXMEs explaining the steps
74+
you need to take in order to make your Dockerfiles functional.
75+
76+
Usage
77+
=====
78+
The ``llvm/utils/build_docker_image.sh`` script provides a rather high degree of
79+
control on how to run the build. It allows you to specify the projects to
80+
checkout from svn and provide a list of CMake arguments to use during when
81+
building LLVM inside docker container.
82+
83+
Here's a very simple example of getting a docker image with clang binary,
84+
compiled by the system compiler in the debian8 image:
85+
86+
.. code-block:: bash
87+
88+
./llvm/utils/docker/build_docker_image.sh \
89+
--source debian8 \
90+
--docker-repository clang-debian8 --docker-tag "staging" \
91+
-- \
92+
-p clang -i install-clang -i install-clang-headers \
93+
-- \
94+
-DCMAKE_BUILD_TYPE=Release
95+
96+
Note there are two levels of ``--`` indirection. First one separates
97+
``build_docker_image.sh`` arguments from ``llvm/utils/build_install_llvm.sh``
98+
arguments. Second one separates CMake arguments from ``build_install_llvm.sh``
99+
arguments. Note that build like that doesn't use a 2-stage build process that
100+
you probably want for clang. Running a 2-stage build is a little more intricate,
101+
this command will do that:
102+
103+
.. code-block:: bash
104+
105+
# Run a 2-stage build.
106+
# LLVM_TARGETS_TO_BUILD=Native is to reduce stage1 compile time.
107+
# Options, starting with BOOTSTRAP_* are passed to stage2 cmake invocation.
108+
./build_docker_image.sh \
109+
--source debian8 \
110+
--docker-repository clang-debian8 --docker-tag "staging" \
111+
-- \
112+
-p clang -i stage2-install-clang -i stage2-install-clang-headers \
113+
-- \
114+
-DLLVM_TARGETS_TO_BUILD=Native -DCMAKE_BUILD_TYPE=Release \
115+
-DBOOTSTRAP_CMAKE_BUILD_TYPE=Release \
116+
-DCLANG_ENABLE_BOOTSTRAP=ON -DCLANG_BOOTSTRAP_TARGETS="install-clang;install-clang-headers"
117+
118+
This will produce two images, a release image ``clang-debian8:staging`` and a
119+
build image ``clang-debian8-build:staging`` from the latest upstream revision.
120+
After the image is built you can run bash inside a container based on your
121+
image like this:
122+
123+
.. code-block:: bash
124+
125+
docker run -ti clang-debian8:staging bash
126+
127+
Now you can run bash commands as you normally would:
128+
129+
.. code-block:: bash
130+
131+
root@80f351b51825:/# clang -v
132+
clang version 5.0.0 (trunk 305064)
133+
Target: x86_64-unknown-linux-gnu
134+
Thread model: posix
135+
InstalledDir: /bin
136+
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/4.8
137+
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/4.8.4
138+
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/4.9
139+
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/4.9.2
140+
Selected GCC installation: /usr/lib/gcc/x86_64-linux-gnu/4.9
141+
Candidate multilib: .;@m64
142+
Selected multilib: .;@m64
143+
144+
145+
Which image should I choose?
146+
============================
147+
We currently provide two images: debian8-based and nvidia-cuda-based. They
148+
differ in the base image that they use, i.e. they have a different set of
149+
preinstalled binaries. Debian8 is very minimal, nvidia-cuda is larger, but has
150+
preinstalled CUDA libraries and allows to access a GPU, installed on your
151+
machine.
152+
153+
If you need a minimal linux distribution with only clang and libstdc++ included,
154+
you should try debian8-based image.
155+
156+
If you want to use CUDA libraries and have access to a GPU on your machine,
157+
you should choose nvidia-cuda-based image and use `nvidia-docker
158+
<https://github.com/NVIDIA/nvidia-docker>`_ to run your docker containers. Note
159+
that you don't need nvidia-docker to build the images, but you need it in order
160+
to have an access to GPU from a docker container that is running the built
161+
image.
162+
163+
If you have a different use-case, you could create your own image based on
164+
``example/`` folder.
165+
166+
Any docker image can be built and run using only the docker binary, i.e. you can
167+
run debian8 build on Fedora or any other Linux distribution. You don't need to
168+
install CMake, compilers or any other clang dependencies. It is all handled
169+
during the build process inside Docker's isolated environment.
170+
171+
Stable build
172+
============
173+
If you want a somewhat recent and somewhat stable build, use the
174+
``branches/google/stable`` branch, i.e. the following command will produce a
175+
debian8-based image using the latest ``google/stable`` sources for you:
176+
177+
.. code-block:: bash
178+
179+
./llvm/utils/docker/build_docker_image.sh \
180+
-s debian8 --d clang-debian8 -t "staging" \
181+
-- \
182+
--branch branches/google/stable \
183+
-p clang -i install-clang -i install-clang-headers \
184+
-- \
185+
-DCMAKE_BUILD_TYPE=Release
186+
187+
188+
Minimizing docker image size
189+
============================
190+
Due to Docker restrictions we use two images (i.e., build and release folders)
191+
for the release image to be as small as possible. It's much easier to achieve
192+
that using two images, because Docker would store a filesystem layer for each
193+
command in the Dockerfile, i.e. if you install some packages in one command,
194+
then remove those in a separate command, the size of the resulting image will
195+
still be proportinal to the size of an image with installed packages.
196+
Therefore, we strive to provide a very simple release image which only copies
197+
compiled clang and does not do anything else.
198+
199+
Docker 1.13 added a ``--squash`` flag that allows to flatten the layers of the
200+
image, i.e. remove the parts that were actually deleted. That is an easier way
201+
to produce the smallest images possible by using just a single image. We do not
202+
use it because as of today the flag is in experimental stage and not everyone
203+
may have the latest docker version available. When the flag is out of
204+
experimental stage, we should investigate replacing two images approach with
205+
just a single image, built using ``--squash`` flag.

llvm/docs/index.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ representation.
9191
CompileCudaWithLLVM
9292
ReportingGuide
9393
Benchmarking
94+
Docker
9495

9596
:doc:`GettingStarted`
9697
Discusses how to get up and running quickly with the LLVM infrastructure.
@@ -161,6 +162,9 @@ representation.
161162
A collection of tips for frontend authors on how to generate IR
162163
which LLVM is able to effectively optimize.
163164

165+
:doc:`Docker`
166+
A reference for using Dockerfiles provided with LLVM.
167+
164168

165169
Programming Documentation
166170
=========================

llvm/utils/docker/README

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
See llvm/docs/Docker.rst for details
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
#!/bin/bash
2+
#===- llvm/utils/docker/build_docker_image.sh ----------------------------===//
3+
#
4+
# The LLVM Compiler Infrastructure
5+
#
6+
# This file is distributed under the University of Illinois Open Source
7+
# License. See LICENSE.TXT for details.
8+
#
9+
#===----------------------------------------------------------------------===//
10+
set -e
11+
12+
IMAGE_SOURCE=""
13+
DOCKER_REPOSITORY=""
14+
DOCKER_TAG=""
15+
BUILDSCRIPT_ARGS=""
16+
17+
function show_usage() {
18+
usage=$(cat << EOF
19+
Usage: build_docker_image.sh [options] [-- [buildscript_args]...]
20+
21+
Available options:
22+
-s|--source image source dir (i.e. debian8, nvidia-cuda, etc)
23+
-d|--docker-repository docker repository for the image
24+
-t|--docker-tag docker tag for the image
25+
Required options: --source and --docker-repository.
26+
27+
All options after '--' are passed to buildscript (see
28+
scripts/build_install_llvm.sh).
29+
30+
For example, running:
31+
$ build_docker_image.sh -s debian8 -d mydocker/debian8-clang -t latest \
32+
-- -p clang -i install-clang -i install-clang-headers
33+
will produce two docker images:
34+
mydocker/debian8-clang-build:latest - an intermediate image used to compile
35+
clang.
36+
mydocker/clang-debian8:latest - a small image with preinstalled clang.
37+
Please note that this example produces a not very useful installation, since it
38+
doesn't override CMake defaults, which produces a Debug and non-boostrapped
39+
version of clang.
40+
For an example of a somewhat more useful build, see build_clang_image.sh.
41+
EOF
42+
)
43+
echo "$usage"
44+
}
45+
46+
while [[ $# -gt 0 ]]; do
47+
case "$1" in
48+
-h|--help)
49+
show_usage
50+
exit 0
51+
;;
52+
-s|--source)
53+
shift
54+
IMAGE_SOURCE="$1"
55+
shift
56+
;;
57+
-d|--docker-repository)
58+
shift
59+
DOCKER_REPOSITORY="$1"
60+
shift
61+
;;
62+
-t|--docker-tag)
63+
shift
64+
DOCKER_TAG="$1"
65+
shift
66+
;;
67+
--)
68+
shift
69+
BUILDSCRIPT_ARGS="$*"
70+
shift $#
71+
;;
72+
*)
73+
echo "Unknown argument $1"
74+
exit 1
75+
;;
76+
esac
77+
done
78+
79+
command -v docker >/dev/null ||
80+
{
81+
echo "Docker binary cannot be found. Please install Docker to use this script."
82+
exit 1
83+
}
84+
85+
if [ "$IMAGE_SOURCE" == "" ]; then
86+
echo "Required argument missing: --source"
87+
exit 1
88+
fi
89+
90+
if [ "$DOCKER_REPOSITORY" == "" ]; then
91+
echo "Required argument missing: --docker-repository"
92+
exit 1
93+
fi
94+
95+
cd $(dirname $0)
96+
if [ ! -d $IMAGE_SOURCE ]; then
97+
echo "No sources for '$IMAGE_SOURCE' were found in $PWD"
98+
exit 1
99+
fi
100+
101+
echo "Building from $IMAGE_SOURCE"
102+
103+
if [ "$DOCKER_TAG" != "" ]; then
104+
DOCKER_TAG=":$DOCKER_TAG"
105+
fi
106+
107+
echo "Building $DOCKER_REPOSITORY-build$DOCKER_TAG"
108+
docker build -t "$DOCKER_REPOSITORY-build$DOCKER_TAG" \
109+
--build-arg "buildscript_args=$BUILDSCRIPT_ARGS" \
110+
-f "$IMAGE_SOURCE/build/Dockerfile" .
111+
112+
echo "Copying clang installation to release image sources"
113+
docker run -v "$PWD/$IMAGE_SOURCE:/workspace" "$DOCKER_REPOSITORY-build$DOCKER_TAG" \
114+
cp /tmp/clang.tar.gz /workspace/release
115+
trap "rm -f $PWD/$IMAGE_SOURCE/release/clang.tar.gz" EXIT
116+
117+
echo "Building release image"
118+
docker build -t "${DOCKER_REPOSITORY}${DOCKER_TAG}" \
119+
"$IMAGE_SOURCE/release"
120+
121+
echo "Done"
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
#===- llvm/utils/docker/debian8/build/Dockerfile -------------------------===//
2+
#
3+
# The LLVM Compiler Infrastructure
4+
#
5+
# This file is distributed under the University of Illinois Open Source
6+
# License. See LICENSE.TXT for details.
7+
#
8+
#===----------------------------------------------------------------------===//
9+
# Produces an image that compiles and archives clang, based on debian8.
10+
FROM launcher.gcr.io/google/debian8:latest
11+
12+
LABEL maintainer "LLVM Developers"
13+
14+
# Install build dependencies of llvm.
15+
# First, Update the apt's source list and include the sources of the packages.
16+
RUN grep deb /etc/apt/sources.list | \
17+
sed 's/^deb/deb-src /g' >> /etc/apt/sources.list
18+
19+
# Install compiler, python and subversion.
20+
RUN apt-get update && \
21+
apt-get install -y --no-install-recommends build-essential python2.7 wget \
22+
subversion ninja-build && \
23+
rm -rf /var/lib/apt/lists/*
24+
25+
# Install cmake version that can compile clang into /usr/local.
26+
# (Version in debian8 repos is is too old)
27+
RUN wget -O - "https://cmake.org/files/v3.7/cmake-3.7.2-Linux-x86_64.tar.gz" | \
28+
tar xzf - -C /usr/local --strip-components=1
29+
30+
# Arguments passed to build_install_clang.sh.
31+
ARG buildscript_args
32+
33+
# Run the build. Results of the build will be available as /tmp/clang.tar.gz.
34+
ADD scripts/build_install_llvm.sh /tmp
35+
RUN /tmp/build_install_llvm.sh ${buildscript_args}

0 commit comments

Comments
 (0)