LLVMシステム入門¶
概要¶
LLVMプロジェクトへようこそ!
LLVMプロジェクトには複数のコンポーネントがあります。プロジェクトのコア自体は「LLVM」と呼ばれています。これには、中間表現を処理し、それをオブジェクトファイルに変換するために必要なすべてのツール、ライブラリ、ヘッダーファイルが含まれています。ツールには、アセンブラ、逆アセンブラ、ビットコードアナライザー、およびビットコードオプティマイザーが含まれます。また、基本的な回帰テストも含まれています。
Cのような言語は、Clangフロントエンドを使用します。このコンポーネントは、C、C ++、Objective C、およびObjective C ++コードをLLVMビットコードにコンパイルし、そこからLLVMを使用してオブジェクトファイルにコンパイルします。
他のコンポーネントには、libc++ C++標準ライブラリ、LLDリンカーなどがあります。
ソースコードの取得とLLVMのビルド¶
LLVM(Clangなどのサブプロジェクトを含む)をチェックアウトします
git clone https://github.com/llvm/llvm-project.git
または、Windowsの場合
git clone --config core.autocrlf=false https://github.com/llvm/llvm-project.git
ストレージを節約し、チェックアウト時間を短縮するために、shallow cloneを実行することをお勧めします。たとえば、LLVMプロジェクトの最新リビジョンを取得するには、次を使用します。
git clone --depth 1 https://github.com/llvm/llvm-project.git
リポジトリのユーザーブランチ(積み重ねられたプルリクエストと元に戻すために使用)に関心がない可能性があります。この構成を使用すると、git fetch(またはgit pull)からそれらをフィルター処理できます。
git config --add remote.origin.fetch '^refs/heads/users/*'
git config --add remote.origin.fetch '^refs/heads/revert-*'
LLVMとClangを構成およびビルドします
cd llvm-project
cmake -S llvm -B build -G <generator> [options]
一般的なビルドシステムジェネレータは次のとおりです
Ninja
— Ninjaビルドファイルを生成するため。ほとんどのllvm開発者はNinjaを使用しています。Unix Makefiles
— make互換の並列makeファイルを生成するため。Visual Studio
— Visual Studioプロジェクトとソリューションを生成するため。Xcode
— Xcodeプロジェクトを生成するため。より包括的なリストについては、CMakeドキュメントを参照してください。
一般的なオプション
-DLLVM_ENABLE_PROJECTS='...'
— 追加でビルドしたいLLVMサブプロジェクトのセミコロン区切りのリスト。clang、clang-tools-extra、lldb、lld、polly、またはcross-project-testsのいずれかを含めることができます。たとえば、LLVM、Clang、およびLLDをビルドするには、
-DLLVM_ENABLE_PROJECTS="clang;lld"
を使用します。-DCMAKE_INSTALL_PREFIX=directory
— LLVMツールとライブラリをインストールする場所のフルパス名をdirectoryに指定します(デフォルトは/usr/local
)。-DCMAKE_BUILD_TYPE=type
— ビルドの最適化レベルとデバッグ情報を制御します。typeの有効なオプションは、Debug
、Release
、RelWithDebInfo
、およびMinSizeRel
です。詳細については、CMAKE_BUILD_TYPEを参照してください。-DLLVM_ENABLE_ASSERTIONS=ON
— アサーションチェックを有効にしてコンパイルします(デフォルトはデバッグビルドではON、他のすべてのビルドタイプではOFFです)。-DLLVM_USE_LINKER=lld
— システムにインストールされていることを前提として、lldリンカーでリンクします。これにより、デフォルトのリンカーが遅い場合、リンク時間を大幅に短縮できます。-DLLVM_PARALLEL_{COMPILE,LINK,TABLEGEN}_JOBS=N
— 同時に並列で実行するコンパイル/リンク/tablegenジョブの数を制限します。リンクは多くのメモリを使用する可能性があるため、これは特に重要です。LLVMのビルド中にメモリの問題が発生した場合は、これを設定して、同時に実行するコンパイル/リンク/tablegenジョブの最大数を制限してみてください。
cmake --build build [--target <target>]
または、上記のビルドシステムを直接指定します。デフォルトのターゲット(つまり、
cmake --build build
またはmake -C build
)は、すべてのLLVMをビルドします。check-all
ターゲット(つまり、ninja check-all
)は、すべてが正常に動作していることを確認するために回帰テストを実行します。CMakeは、各ツールとライブラリのビルドターゲットを生成し、ほとんどのLLVMサブプロジェクトは独自の
check-<project>
ターゲットを生成します。シリアルビルドの実行は遅くなります。速度を向上させるには、並列ビルドを実行してみてください。これはNinjaではデフォルトで行われます。
make
の場合は、オプション-j NN
を使用します。ここで、NN
は並列ジョブの数、たとえば、利用可能なCPUの数です。
LLVMのみをビルドし、他のサブプロジェクトをビルドしない基本的なCMakeとビルド/テストの呼び出し
cmake -S llvm -B build -G Ninja -DCMAKE_BUILD_TYPE=Debug
ninja -C build check-llvm
これにより、デバッグ情報を使用してLLVMビルドが設定され、LLVMがコンパイルされてLLVMテストが実行されます。
CMakeオプションの詳細については、CMakeを参照してください
ビルドまたはテストの失敗が発生した場合は、下記を参照してください。
LLVMの構成とコンパイルの詳細については、「LLVM入門」セクションを参照してください。ソースコードツリーのレイアウトについては、「ディレクトリレイアウト」を参照してください。
スタンドアロンビルド¶
スタンドアロンビルドを使用すると、システムに既に存在する、事前にビルドされたclangまたはllvmライブラリに対してサブプロジェクトをビルドできます。
(上記のように)llvm-projectの標準チェックアウトからのソースコードを使用してスタンドアロンビルドを実行できますが、sparse checkoutまたはリリースページで入手可能なtarballからビルドすることもできます。
スタンドアロンビルドの場合、他のプロジェクトのスタンドアロンビルドで消費できるように適切に構成されたllvmインストールが必要です。これはディストリビューションが提供するLLVMインストールである可能性があります。または、次のように自分でビルドすることもできます。
cmake -G Ninja -S path/to/llvm-project/llvm -B $builddir \
-DLLVM_INSTALL_UTILS=ON \
-DCMAKE_INSTALL_PREFIX=/path/to/llvm/install/prefix \
< other options >
ninja -C $builddir install
llvmがインストールされたら、スタンドアロンビルド用にプロジェクトを構成するには、次のようにCMakeを呼び出します。
cmake -G Ninja -S path/to/llvm-project/$subproj \
-B $buildir_subproj \
-DLLVM_EXTERNAL_LIT=/path/to/lit \
-DLLVM_ROOT=/path/to/llvm/install/prefix
注意点:
スタンドアロンビルドは、LLVMNがビルドされた元のフォルダではないフォルダで実行する必要があります($builddir!=$builddir_subproj)。
LLVM_ROOT
はllvmインストールのプレフィックスを指す必要があります。たとえば、llvmが/usr/bin
と/usr/lib64
にインストールされている場合は、-DLLVM_ROOT=/usr/
を渡す必要があります。LLVM_ROOT
オプションとLLVM_EXTERNAL_LIT
オプションの両方が、すべてのサブプロジェクトのスタンドアロンビルドを実行するために必要です。各サブプロジェクトに必要な追加オプションは、以下の表に記載されています。
以下の表にリストされているサブプロジェクトでは、check-$subproj
ビルドターゲットとinstall
ビルドターゲットがサポートされています。
サブプロジェクト |
必須のサブディレクトリ |
必須のCMakeオプション |
---|---|---|
llvm |
llvm、cmake、third-party |
LLVM_INSTALL_UTILS=ON |
clang |
clang、cmake |
CLANG_INCLUDE_TESTS=ON(check-clangのみに必要) |
lld |
lld, cmake |
スタンドアロンのclangをビルドする例
#!/bin/sh
build_llvm=`pwd`/build-llvm
build_clang=`pwd`/build-clang
installprefix=`pwd`/install
llvm=`pwd`/llvm-project
mkdir -p $build_llvm
mkdir -p $installprefix
cmake -G Ninja -S $llvm/llvm -B $build_llvm \
-DLLVM_INSTALL_UTILS=ON \
-DCMAKE_INSTALL_PREFIX=$installprefix \
-DCMAKE_BUILD_TYPE=Release
ninja -C $build_llvm install
cmake -G Ninja -S $llvm/clang -B $build_clang \
-DLLVM_EXTERNAL_LIT=$build_llvm/utils/lit \
-DLLVM_ROOT=$installprefix
ninja -C $build_clang
要件¶
LLVMシステムを使い始める前に、以下の要件を確認してください。必要なハードウェアとソフトウェアを事前に知っておくことで、トラブルを回避できる可能性があります。
ハードウェア¶
LLVMは以下のホストプラットフォームで動作することが知られています
OS |
アーキテクチャ |
コンパイラ |
---|---|---|
Linux |
x861 |
GCC、Clang |
Linux |
amd64 |
GCC、Clang |
Linux |
ARM |
GCC、Clang |
Linux |
Mips |
GCC、Clang |
Linux |
PowerPC |
GCC、Clang |
Linux |
SystemZ |
GCC、Clang |
Solaris |
V9 (Ultrasparc) |
GCC |
DragonFlyBSD |
amd64 |
GCC、Clang |
FreeBSD |
x861 |
GCC、Clang |
FreeBSD |
amd64 |
GCC、Clang |
NetBSD |
x861 |
GCC、Clang |
NetBSD |
amd64 |
GCC、Clang |
OpenBSD |
x861 |
GCC、Clang |
OpenBSD |
amd64 |
GCC、Clang |
macOS2 |
PowerPC |
GCC |
macOS |
x86 |
GCC、Clang |
Cygwin/Win32 |
x861, 3 |
GCC |
Windows |
x861 |
Visual Studio |
Windows x64 |
x86-64 |
Visual Studio |
注
Pentiumプロセッサ以上でコード生成がサポートされています
32ビットABIのみでコード生成がサポートされています
Win32ベースのシステムでLLVMモジュールを使用するには、
-DBUILD_SHARED_LIBS=On
を指定してLLVMを構成できます。
デバッグビルドには多くの時間とディスク容量が必要であることに注意してください。LLVMのみのビルドでは、約1〜3 GBの容量が必要です。LLVMとClangのフルビルドでは、約15〜20 GBのディスク容量が必要です。必要な正確な容量はシステムによって異なります。(これは、すべてのデバッグ情報と、ライブラリが複数のツールに静的にリンクされているためです)。
ディスク容量が限られている場合は、選択したツールまたは選択したターゲットのみをビルドできます。リリースビルドでは、必要な容量が大幅に少なくなります。
LLVMスイートは他のプラットフォームでもコンパイルできる可能性がありますが、保証されているわけではありません。コンパイルが成功した場合、LLVMユーティリティは、LLVMビットコードのアセンブル、逆アセンブル、分析、および最適化ができるはずです。コード生成も同様に機能するはずですが、生成されたネイティブコードはプラットフォームでは機能しない場合があります。
ソフトウェア¶
LLVMをコンパイルするには、いくつかのソフトウェアパッケージがインストールされている必要があります。以下の表は、必要なパッケージを示しています。「パッケージ」列は、LLVMが依存するソフトウェアパッケージの一般的な名前です。「バージョン」列には、パッケージの「動作することが確認されている」バージョンが示されています。「注記」列には、LLVMがパッケージを使用する方法やその他の詳細が記載されています。
パッケージ |
バージョン |
注記 |
---|---|---|
>=3.20.0 |
Makefile/ワークスペースジェネレーター |
|
>=3.8 |
自動テストスイート1 |
|
>=1.2.3.4 |
圧縮ライブラリ2 |
|
3.79, 3.79.1 |
Makefile/ビルドプロセッサ3 |
|
>=5.1 |
ヘッダージェネレーター4 |
注
llvm/test
ディレクトリで自動テストスイートを実行する場合、またはPythonライブラリ、ユーティリティ、またはバインディングを利用する場合は、このソフトウェアが必要になります。オプション。選択したLLVMツールに圧縮/解凍機能を追加します。
オプション。CMakeでサポートされている他のビルドツールを使用できます。
New Headergenでlibcをビルドする場合のみ必要です。主にlibcで使用されます。
さらに、コンパイルホストには、通常の多くのUnixユーティリティがあることが予想されます。具体的には、次のものがあります。
ar - アーカイブライブラリビルダー
bzip2 - ディストリビューション生成用のbzip2コマンド
bunzip2 - ディストリビューションチェック用のbunzip2コマンド
chmod - ファイルのアクセス許可を変更する
cat - 出力連結ユーティリティ
cp - ファイルをコピーする
date - 現在の日付/時刻を出力する
echo - 標準出力に出力する
egrep - 拡張正規表現検索ユーティリティ
find - ファイルシステム内のファイル/ディレクトリを検索する
grep - 正規表現検索ユーティリティ
gzip - ディストリビューション生成用のgzipコマンド
gunzip - ディストリビューションチェック用のgunzipコマンド
install - ディレクトリ/ファイルをインストールする
mkdir - ディレクトリを作成する
mv - ファイルを移動(名前変更)する
ranlib - アーカイブライブラリのシンボルテーブルビルダー
rm - ファイルとディレクトリを削除する
sed - 出力を変換するためのストリームエディター
sh - makeビルドスクリプト用のBourneシェル
tar - ディストリビューション生成用のテープアーカイブ
test - ファイルシステム内のものをテストする
unzip - ディストリビューションチェック用のunzipコマンド
zip - ディストリビューション生成用のzipコマンド
ホストC++ツールチェーン(コンパイラと標準ライブラリの両方)¶
LLVMはホストC++コンパイラに対して非常に要求が高く、そのためコンパイラのバグを露呈する傾向があります。また、C++言語とライブラリの改善と開発を適度に追跡しようとしています。そのため、LLVMをビルドするには、最新のホストC++ツールチェーン(コンパイラと標準ライブラリの両方)が必要です。
LLVMは、コーディング標準に文書化されているC++のサブセットを使用して記述されています。この言語バージョンを強制するために、ビルドシステムで最も一般的なホストツールチェーンの特定の最小バージョンをチェックします。
Clang 5.0
Apple Clang 10.0
GCC 7.4
Visual Studio 2019 16.7
これらのツールチェーンよりも古いものは動作する可能性がありますが、特別なオプションでビルドシステムを強制する必要があり、実際にはサポートされているホストプラットフォームではありません。また、これらのコンパイラの古いバージョンでは、LLVMがクラッシュしたり、誤ってコンパイルされたりすることがよくありました。
ICCやxlCなどのあまり広く使用されていないホストツールチェーンの場合、LLVMで使用されているすべてのC++機能をサポートするには、非常に新しいバージョンが必要になる可能性があることに注意してください。
ホストツールチェーンの一部として使用すると失敗することがわかっている特定のソフトウェアバージョンを追跡します。これには、リンカーが含まれることもあります。
GNU ld 2.16.X。ldリンカーの2.16.Xバージョンの一部では、「.gnu.linkonce.t.*
」シンボルが破棄されたセクションで定義されているという非常に長い警告メッセージが生成されます。これらのメッセージは誤りであり、リンケージは正しいので、無視しても安全です。これらのメッセージは、ld 2.17を使用すると表示されなくなります。
GNU binutils 2.17:Binutils 2.17には、LLVMをビルドすると、非常に長いリンク時間(数秒ではなく数分)が発生するバグが含まれています。新しいバージョン(2.17.50.0.4以降)にアップグレードすることをお勧めします。
GNU Binutils 2.19.1 Gold:このバージョンのGoldには、位置独立コードでLLVMをビルドすると断続的な失敗を引き起こすバグが含まれていました。症状は、循環依存関係に関するエラーです。新しいバージョンのGoldにアップグレードすることをお勧めします。
最新のホストC++ツールチェーンの入手¶
このセクションは、主にLinuxと古いBSDに適用されます。macOSでは、十分に新しいXcodeが必要です。そうでない場合は、アップグレードが必要になる可能性が高くなります。Windowsには「システムコンパイラ」がないため、Visual Studio 2019(以降)または最新バージョンのmingw64のいずれかをインストールする必要があります。FreeBSD 10.0以降には、システムコンパイラとして最新のClangがあります。
ただし、一部のLinuxディストリビューションと他の古いBSDには、非常に古いバージョンのGCCがある場合があります。これらの手順は、このようなシステムでもコンパイラをアップグレードするのに役立ちます。ただし、可能な限り、これらの要件を満たす最新のシステムコンパイラを備えた最新バージョンのディストリビューションを使用することをお勧めします。以前のバージョンのClangとlibc++をホストコンパイラとしてインストールするのは魅力的ですが、libc++は比較的最近までLinuxでビルドするように適切にテストまたは設定されていませんでした。その結果、このガイドでは、ブートストラップの最初のホストとしてlibstdc++と最新のGCCを使用し、次にClang(および場合によってはlibc++)を使用することをお勧めします。
最初のステップは、最新のGCCツールチェーンをインストールすることです。ユーザーがバージョンの要件で苦労した最も一般的なディストリビューションは、Ubuntu Precise、12.04 LTSです。このディストリビューションの場合、簡単なオプションの1つは、ツールチェーンテストPPAをインストールし、それを使用して最新のGCCをインストールすることです。ask ubuntu stack exchangeと、更新されたコマンドを含むgithub gistで、これに関する非常に素晴らしい議論があります。ただし、すべてのユーザーがPPAを使用できるわけではなく、他の多くのディストリビューションがあるため、GCCをソースからビルドしてインストールする必要がある場合があります(または、あなたがコンパイラ開発をしている場合は、単に役に立つだけです)。最近では、これも非常に簡単に行えます。
特定のバージョンのGCCをインストールするための簡単な手順
% gcc_version=7.4.0
% wget https://ftp.gnu.org/gnu/gcc/gcc-${gcc_version}/gcc-${gcc_version}.tar.bz2
% wget https://ftp.gnu.org/gnu/gcc/gcc-${gcc_version}/gcc-${gcc_version}.tar.bz2.sig
% wget https://ftp.gnu.org/gnu/gnu-keyring.gpg
% signature_invalid=`gpg --verify --no-default-keyring --keyring ./gnu-keyring.gpg gcc-${gcc_version}.tar.bz2.sig`
% if [ $signature_invalid ]; then echo "Invalid signature" ; exit 1 ; fi
% tar -xvjf gcc-${gcc_version}.tar.bz2
% cd gcc-${gcc_version}
% ./contrib/download_prerequisites
% cd ..
% mkdir gcc-${gcc_version}-build
% cd gcc-${gcc_version}-build
% $PWD/../gcc-${gcc_version}/configure --prefix=$HOME/toolchains --enable-languages=c,c++
% make -j$(nproc)
% make install
詳細については、優れたGCC wikiエントリを参照してください。この情報のほとんどはここから得ました。
GCCツールチェーンを入手したら、LLVMのビルドを構成して、ホストコンパイラとC++標準ライブラリに新しいツールチェーンを使用するようにします。新しいバージョンのlibstdc++はシステムライブラリ検索パスにないため、リンク時(-L
)および実行時(-rpath
)に見つけられるように、追加のリンカーフラグを渡す必要があります。CMakeを使用している場合、この呼び出しによって動作するバイナリが生成されるはずです
% mkdir build
% cd build
% CC=$HOME/toolchains/bin/gcc CXX=$HOME/toolchains/bin/g++ \
cmake .. -DCMAKE_CXX_LINK_FLAGS="-Wl,-rpath,$HOME/toolchains/lib64 -L$HOME/toolchains/lib64"
rpathの設定に失敗すると、ほとんどのLLVMバイナリは起動時に、libstdc++.so.6: version `GLIBCXX_3.4.20' not found
のようなローダーからのメッセージで失敗します。これは、-rpathリンカーフラグを調整する必要があることを意味します。
このメソッドは、すべての実行ファイルのrpathに絶対パスを追加します。これはローカル開発には問題ありません。ビルドしたバイナリを古いシステムでも実行できるように配布する場合は、libstdc++.so.6
を lib/
ディレクトリにコピーしてください。LLVMの出荷バイナリはすべて $ORIGIN/../lib
を指すrpathを持っているため、そこに libstdc++.so.6
があれば見つけられます。配布されないバイナリにはrpathが設定されておらず、libstdc++.so.6
を見つけることができません。上記の libstdc++.so.6
への絶対パスを追加するには、cmakeに -DLLVM_LOCAL_RPATH="$HOME/toolchains/lib64"
を渡してください。これらのバイナリは配布されないため、絶対ローカルパスを持つことは問題ありません。
Clangをビルドする際、ブートストラップの一部として新しいホストとして使用するには、それ に最新のC++標準ライブラリへのアクセス権を与える必要があります。これを行う簡単な方法は2つあります。1つはClangと一緒にlibc++をビルド(およびインストール)し、-stdlib=libc++
コンパイルおよびリンクフラグで使用する方法です。もう1つは、ClangをGCCと同じプレフィックス(上記の$HOME/toolchains
)にインストールする方法です。Clangは自身のプレフィックス内でlibstdc++を探し、見つかればそれを使用します。また、ClangがGCCツールチェーンを探すための明示的なプレフィックスを--gcc-toolchain=/opt/my/gcc/prefix
フラグで追加することもできます。このフラグは、新しくビルドしたClangを使用してブートストラップするときに、コンパイルとリンクの両方のコマンドに渡します。
LLVMを始める¶
このガイドの残りの部分は、LLVMを起動して実行できるようにし、LLVM環境に関する基本的な情報を提供することを目的としています。
このガイドの後半のセクションでは、LLVMソースツリーの一般的なレイアウト、LLVMツールチェーンを使用した簡単な例、LLVMに関する詳細情報を見つけたり、メールでヘルプを得たりするためのリンクについて説明します。
用語と表記¶
このマニュアルでは、ローカルシステムと作業環境に固有のパスを示すために、以下の名前が使用されています。これらは設定する必要のある環境変数ではなく、以下のドキュメントで使用される文字列にすぎません。以下の例では、これらの名前をそれぞれローカルシステム上の適切なパス名に置き換えるだけで済みます。これらのパスはすべて絶対パスです。
SRC_ROOT
これは、LLVMソースツリーの最上位ディレクトリです。
OBJ_ROOT
これは、LLVMオブジェクトツリーの最上位ディレクトリです(つまり、オブジェクトファイルとコンパイルされたプログラムが配置されるツリーです。SRC_ROOTと同じにすることができます)。
パッチの送信¶
Contributingを参照してください。
コミットの二分探索¶
LLVMでgit bisect
を使用する方法については、LLVMコードの二分探索を参照してください。
変更の取り消し¶
gitを使用して変更を取り消す場合、デフォルトのメッセージは「This reverts commit XYZ」になります。コミットメッセージの最後にこれを残し、その前にコミットが取り消される理由の詳細を追加してください。簡単な説明や、問題を示すボットへのリンクがあれば十分です。
ローカルLLVM構成¶
リポジトリをチェックアウトしたら、LLVMスイートのソースコードをビルドする前に構成する必要があります。このプロセスではCMakeを使用します。通常のconfigure
スクリプトとは異なり、CMakeは要求された形式でビルドファイルを生成し、さまざまな*.inc
ファイルとllvm/include/llvm/Config/config.h.cmake
を生成します。
変数は、コマンドラインで-D<変数名>=<値>
の形式を使用してcmake
に渡されます。次の変数は、LLVMの開発者が使用する一般的なオプションの一部です。
CMAKE_C_COMPILER
CMAKE_CXX_COMPILER
CMAKE_BUILD_TYPE
CMAKE_INSTALL_PREFIX
Python3_EXECUTABLE
LLVM_TARGETS_TO_BUILD
LLVM_ENABLE_PROJECTS
LLVM_ENABLE_RUNTIMES
LLVM_ENABLE_DOXYGEN
LLVM_ENABLE_SPHINX
LLVM_BUILD_LLVM_DYLIB
LLVM_LINK_LLVM_DYLIB
LLVM_PARALLEL_LINK_JOBS
LLVM_OPTIMIZED_TABLEGEN
詳細については、よく使用されるCMake変数のリストを参照してください。
LLVMを構成するには、次の手順に従います。
オブジェクトルートディレクトリに移動します。
% cd OBJ_ROOT
cmake
を実行します。% cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=<type> -DCMAKE_INSTALL_PREFIX=/install/path [other options] SRC_ROOT
LLVMスイートのソースコードのコンパイル¶
autotoolsとは異なり、CMakeではビルドタイプは構成時に定義されます。ビルドタイプを変更する場合は、次の呼び出しでcmakeを再実行できます。
% cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=<type> SRC_ROOT
実行間で、CMakeはすべてのオプションに設定された値を保持します。CMakeには、次のビルドタイプが定義されています。
Debug
これらのビルドはデフォルトです。ビルドシステムは、最適化されていないツールとライブラリを、デバッグ情報とアサートを有効にしてコンパイルします。
Release
これらのビルドでは、ビルドシステムはツールとライブラリを最適化を有効にしてコンパイルし、デバッグ情報は生成しません。CMakeのデフォルトの最適化レベルは-O3です。これは、CMakeコマンドラインで
CMAKE_CXX_FLAGS_RELEASE
変数を設定することで構成できます。
RelWithDebInfo
これらのビルドはデバッグ時に役立ちます。最適化されたバイナリをデバッグ情報付きで生成します。CMakeのデフォルトの最適化レベルは-O2です。これは、CMakeコマンドラインで
CMAKE_CXX_FLAGS_RELWITHDEBINFO
変数を設定することで構成できます。
LLVMを構成したら、OBJ_ROOTディレクトリに入り、次のコマンドを発行することでビルドできます。
% make
ビルドが失敗した場合は、こちらを確認して、LLVMをコンパイルできないことがわかっているGCCのバージョンを使用しているかどうかを確認してください。
マシンに複数のプロセッサがある場合は、GNU Makeによって提供される並列ビルドオプションの一部を使用することもできます。たとえば、次のコマンドを使用できます。
% make -j2
LLVMソースコードを操作する際に役立つ、いくつかの特別なターゲットがあります。
make clean
ビルドによって生成されたすべてのファイルを削除します。これには、オブジェクトファイル、生成されたC/C++ファイル、ライブラリ、および実行可能ファイルが含まれます。
make install
LLVMのヘッダーファイル、ライブラリ、ツール、およびドキュメントを、
CMAKE_INSTALL_PREFIX
で指定された$PREFIX
の下の階層にインストールします。デフォルトは/usr/local
です。
make docs-llvm-html
-DLLVM_ENABLE_SPHINX=On
で構成した場合、これはOBJ_ROOT/docs/html
にHTML形式のドキュメントを含むディレクトリを生成します。
LLVMのクロスコンパイル¶
LLVM自体をクロスコンパイルできます。つまり、ビルドが行われるプラットフォームとは異なるプラットフォームでホストされるLLVM実行可能ファイルとライブラリを作成できます(カナディアンクロスビルド)。クロスコンパイル用のビルドファイルを生成するために、CMakeはCMAKE_TOOLCHAIN_FILE
変数を提供します。この変数は、CMakeテスト操作中に使用されるコンパイラフラグと変数を定義できます。
このようなビルドの結果は、ビルドホストでは実行できないが、ターゲットで実行できる実行可能ファイルになります。例として、次のCMake呼び出しは、iOSをターゲットとするビルドファイルを生成できます。これは、最新のXcodeがインストールされたmacOSで機能します。
% cmake -G "Ninja" -DCMAKE_OSX_ARCHITECTURES="armv7;armv7s;arm64"
-DCMAKE_TOOLCHAIN_FILE=<PATH_TO_LLVM>/cmake/platforms/iOS.cmake
-DCMAKE_BUILD_TYPE=Release -DLLVM_BUILD_RUNTIME=Off -DLLVM_INCLUDE_TESTS=Off
-DLLVM_INCLUDE_EXAMPLES=Off -DLLVM_ENABLE_BACKTRACES=Off [options]
<PATH_TO_LLVM>
注:iOS SDKの制限により、iOS用にビルドする場合は、追加のフラグを渡す必要があります。
クロスコンパイルの詳細については、Clang/LLVMを使用したClang/LLVMのクロスコンパイル方法およびクロスコンパイル全般に関するClangドキュメントを確認してください。
LLVMオブジェクトファイルの場所¶
LLVMビルドシステムは、単一のLLVMソースツリーを複数のLLVMビルド間で共有できます。したがって、同じソースツリーを使用して、複数の異なるプラットフォームまたは構成に対してLLVMをビルドできます。
LLVMオブジェクトファイルが存在する必要がある場所にディレクトリを変更します。
% cd OBJ_ROOT
cmake
を実行します。% cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release SRC_ROOT
LLVMビルドは、LLVMソースツリーと一致する構造をOBJ_ROOTの下に作成します。ソースファイルがソースツリーに存在する各レベルには、OBJ_ROOTに対応するCMakeFiles
ディレクトリがあります。そのディレクトリの下には、.dir
で終わる名前の別のディレクトリがあり、その下に各ソースのオブジェクトファイルがあります。
例:
% cd llvm_build_dir % find lib/Support/ -name APFloat* lib/Support/CMakeFiles/LLVMSupport.dir/APFloat.cpp.o
オプションの構成項目¶
binfmt_miscモジュールをサポートするLinuxシステムで実行していて、システムでrootアクセス権を持っている場合は、LLVMビットコードファイルを直接実行するようにシステムを設定できます。これを行うには、次のようなコマンドを使用します(モジュールをすでに使用している場合は、最初のコマンドは必要ない場合があります)。
% mount -t binfmt_misc none /proc/sys/fs/binfmt_misc
% echo ':llvm:M::BC::/path/to/lli:' > /proc/sys/fs/binfmt_misc/register
% chmod u+x hello.bc (if needed)
% ./hello.bc
これにより、LLVMビットコードファイルを直接実行できます。Debianでは、上記の「echo」コマンドの代わりに、このコマンドを使用することもできます。
% sudo update-binfmts --install llvm /path/to/lli --magic 'BC'
ディレクトリレイアウト¶
LLVMソースベースに関する有用な情報の1つは、doxygenドキュメントで、https://llvm.dokyumento.jp/doxygen/で入手できます。以下は、コードレイアウトの簡単な紹介です。
llvm/cmake
¶
システムビルドファイルを生成します。
llvm/cmake/modules
llvmユーザー定義オプションのビルド構成。コンパイラバージョンとリンカーフラグをチェックします。
llvm/cmake/platforms
Android NDK、iOS システム、および MSVC をターゲットとする非 Windows ホスト用のツールチェーン構成。
llvm/examples
¶
LLVM をカスタム言語のコンパイラとして使用する方法を示すいくつかの簡単な例 - 低レベル化、最適化、コード生成など。
Kaleidoscope チュートリアル: Kaleidoscope 言語のチュートリアルでは、手書きのレキサー、パーサー、AST、および LLVM を使用したコード生成サポート(静的(事前)コンパイルとさまざまな Just In Time (JIT) コンパイルのアプローチを含む)を含む、自明でない言語用の優れた小さなコンパイラの実装について説明します。完全な初心者向けの Kaleidoscope チュートリアル。
BuildingAJIT: LLVM の ORC JIT API が LLVM の他の部分とどのように相互作用するかを示す、BuildingAJIT チュートリアルの例。また、ユースケースに適したカスタム JIT を構築するために、それらをどのように再結合するかを教えます。
llvm/include
¶
LLVM ライブラリからエクスポートされたパブリック ヘッダー ファイル。3 つの主要なサブディレクトリ
llvm/include/llvm
すべての LLVM 固有のヘッダー ファイルと、LLVM のさまざまな部分のサブディレクトリ:
Analysis
,CodeGen
,Target
,Transforms
など...
llvm/include/llvm/Support
LLVM に付属しているが、必ずしも LLVM 固有ではない汎用サポート ライブラリ。たとえば、一部の C++ STL ユーティリティとコマンドライン オプション処理ライブラリは、ここにヘッダー ファイルを格納します。
llvm/include/llvm/Config
cmake
によって構成されたヘッダー ファイル。これらは「標準」の UNIX および C ヘッダー ファイルをラップします。ソース コードは、cmake
が生成する条件付き #include を自動的に処理するこれらのヘッダー ファイルを含めることができます。
llvm/lib
¶
ほとんどのソース ファイルはここにあります。コードをライブラリに入れることで、LLVM は ツール間でのコードの共有を容易にします。
llvm/lib/IR/
Instruction や BasicBlock などのコア クラスを実装するコア LLVM ソース ファイル。
llvm/lib/AsmParser/
LLVM アセンブリ言語パーサー ライブラリのソース コード。
llvm/lib/Bitcode/
ビットコードの読み書きのコード。
llvm/lib/Analysis/
コールグラフ、誘導変数、自然ループ識別など、さまざまなプログラム分析。
llvm/lib/Transforms/
積極的なデッド コード削除、スパース条件付き定数伝播、インライン化、ループ不変コード モーション、デッド グローバル削除など、IR から IR へのプログラム変換。
llvm/lib/Target/
コード生成のターゲット アーキテクチャを記述するファイル。たとえば、
llvm/lib/Target/X86
は X86 マシン記述を保持します。
llvm/lib/CodeGen/
コード ジェネレーターの主要部分: 命令セレクター、命令スケジューリング、およびレジスタ割り当て。
llvm/lib/MC/
ライブラリは、マシン コード レベルでコードを表現および処理します。アセンブリとオブジェクト ファイルの出力処理をします。
llvm/lib/ExecutionEngine/
インタープリターおよび JIT コンパイルされたシナリオで、ランタイム時にビットコードを直接実行するためのライブラリ。
llvm/lib/Support/
llvm/include/ADT/
およびllvm/include/Support/
のヘッダー ファイルに対応するソース コード。
llvm/bindings
¶
C または C++ 以外の言語で記述されたプログラムが LLVM インフラストラクチャを利用できるようにするための、LLVM コンパイラ インフラストラクチャのバインディングが含まれています。LLVM プロジェクトは、OCaml および Python 用の言語バインディングを提供します。
llvm/projects
¶
厳密には LLVM の一部ではないが、LLVM と一緒に出荷されるプロジェクト。これは、LLVM ビルド システムを活用する独自の LLVM ベースのプロジェクトを作成するためのディレクトリでもあります。
llvm/test
¶
LLVM インフラストラクチャの機能テスト、回帰テスト、およびその他の健全性チェック。これらは、徹底的でなくても、迅速に実行され、広範囲をカバーすることを目的としています。
test-suite
¶
LLVM のための包括的な正確性、パフォーマンス、およびベンチマーク テスト スイート。これは、さまざまなライセンスの下で大量のサードパーティ コードが含まれているため、別の git リポジトリ <https://github.com/llvm/llvm-test-suite>
に含まれています。詳細については、テスト ガイド ドキュメントを参照してください。
llvm/tools
¶
上記のライブラリから構築された実行可能ファイルで、ユーザー インターフェイスの主要部分を形成します。ツール名 -help
と入力すると、常にツールのヘルプを表示できます。以下は、最も重要なツールの簡単な紹介です。詳細については、コマンド ガイドを参照してください。
bugpoint
bugpoint
は、クラッシュまたは誤コンパイルのいずれであっても、問題を引き起こす最小限のパス数や命令数に与えられたテスト ケースを絞り込むことにより、最適化パスまたはコード生成バックエンドをデバッグするために使用されます。bugpoint
の使用方法の詳細については、HowToSubmitABug.html を参照してください。
llvm-ar
アーカイバーは、指定された LLVM ビットコード ファイルを含むアーカイブを生成します。オプションで、高速ルックアップ用のインデックスを含めることができます。
llvm-as
アセンブラーは、人間が読める LLVM アセンブリを LLVM ビットコードに変換します。
llvm-dis
逆アセンブラーは、LLVM ビットコードを人間が読める LLVM アセンブリに変換します。
llvm-link
当然のことながら、
llvm-link
は複数の LLVM モジュールを単一のプログラムにリンクします。
lli
lli
は、LLVM ビットコードを直接実行できる LLVM インタープリターです (ただし、非常に遅いです...)。それをサポートするアーキテクチャ (現在は x86、Sparc、および PowerPC) では、デフォルトで、lli
は Just-In-Time コンパイラーとして機能し (機能がコンパイルされている場合)、インタープリターよりもはるかに高速にコードを実行します。
llc
llc
は、LLVM ビットコードをネイティブ コード アセンブリ ファイルに変換する LLVM バックエンド コンパイラーです。
opt
opt
は LLVM ビットコードを読み取り、一連の LLVM から LLVM への変換 (コマンドラインで指定) を適用し、結果のビットコードを出力します。'opt -help
' は、LLVM で利用可能なプログラム変換のリストを取得するのに適しています。
opt
は、入力 LLVM ビットコード ファイルに対して特定の分析を実行し、結果を出力することもできます。主に分析をデバッグしたり、分析が何をするかを理解したりするのに役立ちます。
llvm/utils
¶
LLVM ソース コードを扱うためのユーティリティ。インフラストラクチャの一部に対するコード ジェネレーターであるため、一部はビルド プロセスの一部です。
codegen-diff
codegen-diff
は、LLC が生成するコードと LLI が生成するコードの違いを見つけます。これは、一方をデバッグしている場合に、もう一方が正しい出力を生成すると仮定して役立ちます。完全なユーザー マニュアルについては、`perldoc codegen-diff'
を実行してください。
emacs/
LLVM アセンブリ ファイルおよび TableGen 記述ファイル用の Emacs および XEmacs の構文強調表示。それらの使用に関する情報については、
README
を参照してください。
getsrcs.sh
生成されていないすべてのソース ファイルを検索して出力します。ディレクトリをまたがって多くの開発を行いたい場合や、各ファイルを検索したくない場合に役立ちます。たとえば、LLVM ソース ツリーの先頭から
xemacs `utils/getsources.sh`
を実行する方法があります。
llvmgrep
LLVM の各ソース ファイルに対して
egrep -H -n
を実行し、llvmgrep
のコマンドラインで指定された正規表現を渡します。これは、ソース ベースで特定の正規表現を検索するための効率的な方法です。
TableGen/
共通の TableGen 記述ファイルからレジスタ記述、命令セット記述、およびアセンブラーを生成するために使用されるツールが含まれています。
vim/
LLVM アセンブリ ファイルおよび TableGen 記述ファイル用の vim 構文強調表示。それらの使用方法については、
README
を参照してください。
LLVM ツールチェーンを使用した例¶
このセクションでは、ClangフロントエンドでLLVMを使用する例を示します。
clangを使った例¶
まず、簡単なCファイルを作成し、「hello.c」という名前を付けます。
#include <stdio.h> int main() { printf("hello world\n"); return 0; }
次に、Cファイルをネイティブ実行可能ファイルにコンパイルします。
% clang hello.c -o hello
注
ClangはデフォルトでGCCと同じように動作します。標準の-Sおよび-c引数は通常どおり機能します(それぞれネイティブの.sファイルまたは.oファイルを生成します)。
次に、CファイルをLLVMビットコードファイルにコンパイルします。
% clang -O3 -emit-llvm hello.c -c -o hello.bc
-emit-llvmオプションを-Sまたは-cオプションとともに使用すると、コードのLLVM
.ll
または.bc
ファイル(それぞれ)を出力できます。これにより、ビットコードファイルで標準のLLVMツールを使用できます。両方の形式でプログラムを実行します。プログラムを実行するには、次のようにします。
% ./hello
と
% lli hello.bc
2番目の例は、LLVM JIT、lliを起動する方法を示しています。
llvm-dis
ユーティリティを使用して、LLVMアセンブリコードを見てみましょう。% llvm-dis < hello.bc | less
LLCコードジェネレーターを使用して、プログラムをネイティブアセンブリにコンパイルします。
% llc hello.bc -o hello.s
ネイティブアセンブリ言語ファイルをプログラムにアセンブルします。
% /opt/SUNWspro/bin/cc -xarch=v9 hello.s -o hello.native # On Solaris % gcc hello.s -o hello.native # On others
ネイティブコードプログラムを実行します。
% ./hello.native
clangを使用してネイティブコードに直接コンパイルする場合(つまり、
-emit-llvm
オプションが存在しない場合)、ステップ6/7/8が自動的に実行されることに注意してください。
一般的な問題¶
LLVMのビルドまたは使用に問題がある場合、またはLLVMに関するその他の一般的な質問がある場合は、よくある質問ページを参照してください。
メモリとビルド時間が限られている場合は、makeの代わりにninjaを使用してビルドしてみてください。cmakeで次のオプションを設定することを検討してください。
-G Ninja このオプションを設定すると、makeの代わりにninjaを使用してビルドできます。ninjaでビルドすると、特にインクリメンタルビルドでビルド時間が大幅に改善され、メモリ使用量が改善されます。
-DLLVM_USE_LINKER このオプションをlldに設定すると、LinuxなどのELFベースのプラットフォームでのLLVM実行可能ファイルのリンク時間が大幅に短縮されます。初めてLLVMをビルドする場合で、lldがバイナリパッケージとして利用できない場合は、GNU ldのより高速な代替としてgoldリンカーを使用することを検討してください。
-DCMAKE_BUILD_TYPE ビルドの最適化レベルとデバッグ情報を制御します。この設定はRAMとディスクの使用量に影響を与える可能性があります。詳細については、CMAKE_BUILD_TYPEを参照してください。
-DLLVM_ENABLE_ASSERTIONS このオプションは、デバッグビルドではデフォルトでON、リリースビルドではデフォルトでOFFになっています。前のオプションで述べたように、リリースビルドタイプを使用してアサーションを有効にすることは、デバッグビルドタイプを使用する良い代替手段になる可能性があります。
-DLLVM_PARALLEL_LINK_JOBS 同時に実行するジョブの数に等しく設定します。これはmakeで使用される-jオプションに似ていますが、リンクジョブのみを対象としています。このオプションはninjaでのみ使用できます。ビルドプロセス中に使用されるメモリの量を大幅に削減するため、ジョブ数を非常に少なくしたい場合があります。メモリが限られている場合は、これを1に設定することをお勧めします。
-DLLVM_TARGETS_TO_BUILD ビルドするターゲットに等しく設定します。これをX86に設定することもできます。ただし、llvm-project/llvm/lib/Targetディレクトリ内にターゲットの完全なリストがあります。
-DLLVM_OPTIMIZED_TABLEGEN これをONに設定して、ビルド中に完全に最適化されたtablegenを生成します。これにより、ビルド時間が大幅に改善されます。これは、デバッグビルドタイプを使用している場合にのみ役立ちます。
-DLLVM_ENABLE_PROJECTS コンパイルするプロジェクト(clang、lldなど)に等しく設定します。複数のプロジェクトをコンパイルする場合は、項目をセミコロンで区切ります。セミコロンで問題が発生した場合は、単一引用符で囲んでみてください。
-DLLVM_ENABLE_RUNTIMES コンパイルするランタイム(libcxx、libcxxabiなど)に等しく設定します。複数のランタイムをコンパイルする場合は、項目をセミコロンで区切ります。セミコロンで問題が発生した場合は、単一引用符で囲んでみてください。
-DCLANG_ENABLE_STATIC_ANALYZER clang静的アナライザーが不要な場合は、このオプションをOFFに設定します。これにより、ビルド時間がわずかに改善されます。
-DLLVM_USE_SPLIT_DWARF デバッグビルドが必要な場合は、これをONに設定することを検討してください。これにより、リンカーへのメモリ負荷が軽減されます。これにより、バイナリにデバッグ情報が含まれないため、リンクがはるかに高速になります。ただし、DWARFオブジェクトファイル(拡張子.dwo付き)の形式でデバッグ情報が生成されます。これは、LinuxなどのELFを使用するホストプラットフォームにのみ適用されます。
リンク¶
このドキュメントは、LLVMを使用していくつかの簡単なことを行う方法の入門にすぎません... ここに文書化されていない(しかし、何かを書きたい場合は喜んでパッチを受け入れます!)はるかに興味深く複雑なことがたくさんあります。LLVMの詳細については、以下を確認してください。