LLVMをビルドするためのDockerfileガイド

はじめに

`llvm/utils/docker` には、LLVMコンポーネントを含むDockerイメージをビルドするための多数のソースがあります。これらは、Dockerイメージを独自に使用するためにビルドしたい人、または独自のDockerfileを作成するための出発点として使用できます。

現在、`debian10` と `nvidia-cuda` ベースイメージのDockerfileを提供しています。また、新しいDockerイメージ用のDockerfileを作成するために必要なプレースホルダーを含む `example` イメージも提供しています。

なぜ?

Dockerイメージは、制御された環境内でソフトウェアのバイナリ配布を作成する方法を提供します。LLVMリポジトリ内にDockerイメージをビルドするためのDockerfileを用意することで、他の場所に配置するよりもはるかに発見しやすくなります。

Dockerの基本

Dockerについて聞いたことがない場合は、このセクションで基本的な説明を読むと役立つかもしれません。Docker は、隔離された再現可能な環境でプログラムを実行するための一般的なソリューションであり、特に大規模な分散フリートにデプロイされたソフトウェアのリリースを維持するために使用されます。Linuxカーネルのnamespaceとcgroupを使用して、現在実行中のLinuxカーネル内に軽量な隔離を提供します。Docker化された環境のアクティブなインスタンスは、*Dockerコンテナ*と呼ばれます。Dockerコンテナファイルシステムのスナップショットは、*Dockerイメージ*と呼ばれます。事前にビルドされたDockerイメージからコンテナを起動できます。

Dockerイメージは、*Dockerfile*と呼ばれる、Dockerイメージのビルド時に使用される命令を定義する特殊な言語で記述されたソースファイルからビルドされます(詳細は公式ドキュメントを参照してください)。最小限のDockerfileには、通常、ベースイメージと、イメージをビルドするために実行する必要がある多数のRUNコマンドが含まれています。新しいイメージをビルドすると、Dockerは最初にベースイメージをダウンロードし、そのファイルシステムを読み取り専用としてマウントし、その上に書き込み可能なオーバーレイを追加して、イメージのビルド中に実行されたすべてのファイルシステムの変更を追跡します。ビルドプロセスが完了すると、イメージの最終的なファイルシステムの状態とベースイメージのファイルシステムの差分が結果のイメージに保存されます。

概要

`llvm/utils/docker` フォルダには、ソースからコンパイルされたLLVMコンポーネントを含む独自のDockerイメージを作成したい人のための基礎となるDockerfileとシンプルなbashスクリプトが含まれています。ソースは、イメージのビルド時にアップストリームgitリポジトリからチェックアウトされます。

結果のイメージには、要求されたLLVMコンポーネントと、C++開発に最小限役立ついくつかの追加パッケージ(例:libstdc++とbinutils)のみが含まれています。

ビルドを実行するためのインターフェースは、`build_docker_image.sh` スクリプトです。チェックアウトするLLVMリポジトリのリストと、CMake呼び出しの引数を受け入れます。

独自のDockerイメージを作成する場合は、`example/` サブフォルダから始めてください。Dockerfileを機能させるために行う必要がある手順を説明する(ごく少数の)FIXMEを含む、不完全なDockerfileが提供されています。

使用方法

`llvm/utils/build_docker_image.sh` スクリプトは、ビルドの実行方法をかなり細かく制御できます。gitからチェックアウトするプロジェクトを指定し、Dockerコンテナ内でLLVMをビルドするときに使用するCMake引数のリストを提供できます。

debian10イメージのシステムコンパイラによってコンパイルされたclangバイナリを含むDockerイメージを取得する非常に簡単な例を次に示します。

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

このようなビルドでは、clangに必要な2段階ビルドプロセスを使用していないことに注意してください。2段階ビルドの実行はもう少し複雑です。次のコマンドで実行できます。

# 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 debian10 \
    --docker-repository clang-debian10 --docker-tag "staging" \
    -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"

これにより、最新のアップストリームリビジョンから新しいイメージ `clang-debian10:staging` が生成されます。イメージがビルドされた後、イメージに基づくコンテナ内でbashを実行できます。

docker run -ti clang-debian10:staging bash

これで、通常どおり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

どのイメージを選択すべきですか?

現在、Debian10ベースとnvidia-cudaベースの2つのイメージを提供しています。これらは、使用するベースイメージが異なり、つまり、プリインストールされているバイナリセットが異なります。Debian10は非常に小さく、nvidia-cudaは大きくなりますが、CUDAライブラリがプリインストールされており、マシンにインストールされているGPUにアクセスできます。

clangとlibstdc++のみを含む最小限のLinuxディストリビューションが必要な場合は、Debian10ベースのイメージを試してください。

CUDAライブラリを使用し、マシン上のGPUにアクセスする場合は、nvidia-cudaベースのイメージを選択し、nvidia-docker を使用してDockerコンテナを実行する必要があります。イメージをビルドするためにnvidia-dockerは必要ありませんが、ビルドされたイメージを実行しているDockerコンテナからGPUにアクセスするにはnvidia-dockerが必要です。

別のユースケースがある場合は、`example/` フォルダに基づいて独自の 이미지を作成できます。

どのDockerイメージも、Dockerバイナリのみを使用してビルドおよび実行できます。つまり、Fedoraまたは他のLinuxディストリビューションでdebian10ビルドを実行できます。CMake、コンパイラ、またはその他のclang依存関係をインストールする必要はありません。Dockerの隔離された環境内でのビルドプロセス中にすべて処理されます。

安定版ビルド

ある程度最近で安定したビルドが必要な場合は、`branches/google/stable` ブランチを使用してください。つまり、次のコマンドは、最新の `google/stable` ソースを使用してDebian10ベースのイメージを作成します。

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

Dockerイメージサイズの最小化

Dockerのファイルシステムの仕組み上、後続のコマンドで削除された場合でも、すべての中間書き込みは結果のイメージに保持されます。結果のイメージサイズを最小限に抑えるために、マルチステージDockerビルドを使用します。内部的には、Dockerは2つのイメージをビルドします。最初のイメージはすべての作業を行います。ビルドの依存関係をインストールし、LLVMソースコードをチェックアウトし、LLVMをコンパイルします。最初のイメージはビルド中にのみ使用され、わかりやすい名前がありません。つまり、ビルド完了後にハッシュ値を介してのみアクセスできます。2番目のイメージは、結果のイメージです。ビルドされたバイナリのみが含まれ、ビルドの依存関係は含まれていません。また、わかりやすい名前(-dおよび-tフラグで指定)でアクセスできます。