reference, declarationdefinition
definition → references, declarations, derived classes, virtual overrides
reference to multiple definitions → definitions
unreferenced
    1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127
  128
  129
  130
  131
  132
  133
  134
  135
  136
  137
  138
  139
  140
  141
  142
  143
  144
  145
  146
  147
  148
  149
  150
  151
  152
  153
  154
  155
  156
  157
  158
  159
  160
  161
  162
  163
  164
  165
  166
  167
  168
  169
  170
  171
  172
  173
  174
  175
  176
  177
  178
  179
  180
  181
  182
  183
  184
  185
  186
  187
  188
  189
  190
  191
  192
  193
  194
  195
  196
  197
  198
  199
=========================================
A guide to Dockerfiles for building LLVM
=========================================

Introduction
============
You can find a number of sources to build docker images with LLVM components in
``llvm/utils/docker``. They can be used by anyone who wants to build the docker
images for their own use, or as a starting point for someone who wants to write
their own Dockerfiles.

We currently provide Dockerfiles with ``debian8`` and ``nvidia-cuda`` base images.
We also provide an ``example`` image, which contains placeholders that one would need
to fill out in order to produce Dockerfiles for a new docker image.

Why?
----
Docker images provide a way to produce binary distributions of
software inside a controlled environment. Having Dockerfiles to builds docker images
inside LLVM repo makes them much more discoverable than putting them into any other
place.

Docker basics
-------------
If you've never heard about Docker before, you might find this section helpful
to get a very basic explanation of it.
`Docker <https://www.docker.com/>`_ is a popular solution for running programs in
an isolated and reproducible environment, especially to maintain releases for
software deployed to large distributed fleets.
It uses linux kernel namespaces and cgroups to provide a lightweight isolation
inside currently running linux kernel.
A single active instance of dockerized environment is called a *docker
container*.
A snapshot of a docker container filesystem is called a *docker image*.
One can start a container from a prebuilt docker image.

Docker images are built from a so-called *Dockerfile*, a source file written in
a specialized language that defines instructions to be used when build
the docker image (see `official
documentation <https://docs.docker.com/engine/reference/builder/>`_ for more
details). A minimal Dockerfile typically contains a base image and a number
of RUN commands that have to be executed to build the image. When building a new
image, docker will first download your base image, mount its filesystem as
read-only and then add a writable overlay on top of it to keep track of all
filesystem modifications, performed while building your image. When the build
process is finished, a diff between your image's final filesystem state and the
base image's filesystem is stored in the resulting image.

Overview
========
The ``llvm/utils/docker`` folder contains Dockerfiles and simple bash scripts to
serve as a basis for anyone who wants to create their own Docker image with
LLVM components, compiled from sources. The sources are checked out from the
upstream svn repository when building the image.

Inside each subfolder we host Dockerfiles for two images:

- ``build/`` image is used to compile LLVM, it installs a system compiler and all
  build dependencies of LLVM. After the build process is finished, the build
  image will have an archive with compiled components at ``/tmp/clang.tar.gz``.
- ``release/`` image usually only contains LLVM components, compiled by the
  ``build/`` image, and also libstdc++ and binutils to make image minimally
  useful for C++ development. The assumption is that you usually want clang to
  be one of the provided components.

To build both of those images, use ``build_docker_image.sh`` script.
It will checkout LLVM sources and build clang in the ``build`` container, copy results
of the build to the local filesystem and then build the ``release`` container using
those. The ``build_docker_image.sh`` accepts a list of LLVM repositories to
checkout, and arguments for CMake invocation.

If you want to write your own docker image, start with an ``example/`` subfolder.
It provides incomplete Dockerfiles with (very few) FIXMEs explaining the steps
you need to take in order to make your Dockerfiles functional.

Usage
=====
The ``llvm/utils/build_docker_image.sh`` script provides a rather high degree of
control on how to run the build. It allows you to specify the projects to
checkout from svn and provide a list of CMake arguments to use during when
building LLVM inside docker container.

Here's a very simple example of getting a docker image with clang binary,
compiled by the system compiler in the debian8 image:

.. code-block:: bash

    ./llvm/utils/docker/build_docker_image.sh \
	--source debian8 \
	--docker-repository clang-debian8 --docker-tag "staging" \
	-p clang -i install-clang -i install-clang-headers \
	-- \
	-DCMAKE_BUILD_TYPE=Release

Note that a build like that doesn't use a 2-stage build process that
you probably want for clang. Running a 2-stage build is a little more intricate,
this command will do that:

.. code-block:: bash

    # Run a 2-stage build.
    #   LLVM_TARGETS_TO_BUILD=Native is to reduce stage1 compile time.
    #   Options, starting with BOOTSTRAP_* are passed to stage2 cmake invocation.
    ./build_docker_image.sh \
	--source debian8 \
	--docker-repository clang-debian8 --docker-tag "staging" \
	-p clang -i stage2-install-clang -i stage2-install-clang-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-headers"
	
This will produce two images, a release image ``clang-debian8:staging`` and a
build image ``clang-debian8-build:staging`` from the latest upstream revision.
After the image is built you can run bash inside a container based on your
image like this:

.. code-block:: bash

    docker run -ti clang-debian8:staging bash

Now you can run bash commands as you normally would:

.. code-block:: bash

    root@80f351b51825:/# clang -v
    clang version 5.0.0 (trunk 305064)
    Target: x86_64-unknown-linux-gnu
    Thread model: posix
    InstalledDir: /bin
    Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/4.8
    Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/4.8.4
    Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/4.9
    Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/4.9.2
    Selected GCC installation: /usr/lib/gcc/x86_64-linux-gnu/4.9
    Candidate multilib: .;@m64
    Selected multilib: .;@m64


Which image should I choose?
============================
We currently provide two images: debian8-based and nvidia-cuda-based. They
differ in the base image that they use, i.e. they have a different set of
preinstalled binaries. Debian8 is very minimal, nvidia-cuda is larger, but has
preinstalled CUDA libraries and allows to access a GPU, installed on your
machine.

If you need a minimal linux distribution with only clang and libstdc++ included,
you should try debian8-based image.

If you want to use CUDA libraries and have access to a GPU on your machine,
you should choose nvidia-cuda-based image and use `nvidia-docker
<https://github.com/NVIDIA/nvidia-docker>`_ to run your docker containers. Note
that you don't need nvidia-docker to build the images, but you need it in order
to have an access to GPU from a docker container that is running the built
image.

If you have a different use-case, you could create your own image based on
``example/`` folder.

Any docker image can be built and run using only the docker binary, i.e. you can
run debian8 build on Fedora or any other Linux distribution. You don't need to
install CMake, compilers or any other clang dependencies. It is all handled
during the build process inside Docker's isolated environment.

Stable build
============
If you want a somewhat recent and somewhat stable build, use the
``branches/google/stable`` branch, i.e. the following command will produce a
debian8-based image using the latest ``google/stable`` sources for you:

.. code-block:: bash

    ./llvm/utils/docker/build_docker_image.sh \
	-s debian8 --d clang-debian8 -t "staging" \
	--branch branches/google/stable \
	-p clang -i install-clang -i install-clang-headers \
	-- \
	-DCMAKE_BUILD_TYPE=Release


Minimizing docker image size
============================
Due to Docker restrictions we use two images (i.e., build and release folders)
for the release image to be as small as possible. It's much easier to achieve
that using two images, because Docker would store a filesystem layer for each
command in the  Dockerfile, i.e. if you install some packages in one command,
then remove  those in a separate command, the size of the resulting image will
still be proportinal to the size of an image with installed packages.
Therefore, we strive to provide a very simple release image which only copies
compiled clang and does not do anything else.

Docker 1.13 added a ``--squash`` flag that allows to flatten the layers of the
image, i.e. remove the parts that were actually deleted. That is an easier way
to produce the smallest images possible by using just a single image. We do not
use it because as of today the flag is in experimental stage and not everyone
may have the latest docker version available. When the flag is out of
experimental stage, we should investigate replacing two images approach with
just a single image, built using ``--squash`` flag.