📢 Webサイト閉鎖と移転のお知らせ
このWebサイトは2026年9月に閉鎖いたします。
新しい記事は移転先で追加しております。(旧サイトでは記事を追加しておりません)

 
(同じ利用者による、間の8版が非表示)
155行目: 155行目:
*: <br>
*: <br>
*: 大規模なソフトウェアシステムの性能向上を目指す場合は、特に有用なツールである。
*: 大規模なソフトウェアシステムの性能向上を目指す場合は、特に有用なツールである。
<br><br>
== LLVMツールチェーン と GNUツールチェーンの比較 ==
<center>
{| class="wikitable"
! 項目 !! LLVM !! GNU
|-
! コンパイラ<br>フロントエンド
| Clang (C言語)<br>Clang++ (C++言語)
| gcc (C言語)<br>g++ (C++言語)
|-
! コンパイラ<br>バックエンド
| LLVM<br>(中間表現処理・最適化・コード生成)
| GCCバックエンド<br>(GCC内部に組み込まれている)
|-
! アセンブラ
| llvm-as
| as (GNU Assembler)
|-
! リンカ
| lld (LLVM Linker)
| ld (GNU Linker)
|-
! その他ツール
| llvm-objdump, llvm-ar, llvm-nm など
| objdump, ar, nm など<br>(binutilsに含まれる)
|-
! 設計思想
| モジュール化・ライブラリ指向<br>再利用可能
| 統合的・密結合
|-
! 他言語での利用
| Rust, Swift, Julia など<br>多数の言語で採用
| 主にC/C++/Fortran系
|}
</center>
<br>
<center>
{| class="wikitable" style="width:70%; text-align:center;"
|+ コンパイルからリンクまでの流れ
! style="width:15%; background-color:#e8e8e8;"| ステップ
! style="width:42.5%; background-color:#dae8fc;"| LLVMツールチェーン
! style="width:42.5%; background-color:#f8cecc;"| GNUツールチェーン
|-
! style="background-color:#fff2cc;"| 入力
| colspan="2" style="background-color:#fff2cc; text-align:center;"| ソースコード (.c, .cpp)
|-
! style="background-color:#e3f2fd;"| ① 解析
| style="background-color:#e3f2fd;"| Clang / Clang++<br><small>字句・構文・意味解析</small>
| style="background-color:#ffebee;"| gcc / g++<br><small>字句・構文・意味解析</small>
|-
! style="background-color:#f3e5f5;"| ② 中間表現
| style="background-color:#e3f2fd;"| LLVM IR<br><small>中間表現形式</small>
| style="background-color:#ffebee;"| gcc内部形式<br><small>RTL/GIMPLE</small>
|-
! style="background-color:#fff3e0;"| ③ 最適化
| style="background-color:#e3f2fd;"| LLVM Optimizer<br><small>各種最適化パス</small>
| style="background-color:#ffebee;"| gcc最適化<br><small>内部で最適化処理</small>
|-
! style="background-color:#e0f2f1;"| ④ コード生成
| style="background-color:#e3f2fd;"| LLVM Backend<br><small>機械語生成</small>
| style="background-color:#ffebee;"| gcc Backend<br><small>機械語生成</small>
|-
! style="background-color:#fce4ec;"| ⑤ アセンブル
| style="background-color:#e3f2fd;"| llvm-as<br><small>LLVM Assembler</small>
| style="background-color:#ffebee;"| as<br><small>GNU Assembler</small>
|-
! style="background-color:#f0f0f0;"| 中間生成物
| colspan="2" style="background-color:#f0f0f0; text-align:center;"| オブジェクトファイル (.o)
|-
! style="background-color:#e8f5e9;"| ⑥ リンク
| style="background-color:#e3f2fd;"| lld<br><small>LLVM Linker</small>
| style="background-color:#ffebee;"| ld<br><small>GNU Linker</small>
|-
! style="background-color:#c8e6c9;"| 出力
| colspan="2" style="background-color:#c8e6c9; text-align:center;"| 実行ファイル (例 : a.out, a.exe)
|}
</center>
<br>
* LLVM
*: 各段階が独立したモジュールとして動作し、LLVM IRという共通の中間表現を使用
* GNU
*: フロントエンドからバックエンドまでgccの中で統合的に処理される
<br><br>
<br><br>


269行目: 352行目:
<br>
<br>
==== AArch64 ====
==== AArch64 ====
以下の例では、AArch64をターゲットとしたLLVMをクロスビルドおよびインストールしている。<br>
以下の例では、x64のホストPCおよびAArch64のターゲットPCにおけるLLVMツールチェーンをビルドおよびインストールしている。<br>
<br>
<u>※注意</u><br>
<u>LLVM / Clangをビルドする段階では、AArch64のシステムルートをオプションとして追加する必要はない。</u><br>
# ビルドディレクトリの作成
  mkdir build && cd build
  mkdir build && cd build
   
   
  cmake -G Ninja                                         \
# CMakeの設定
       -DCMAKE_BUILD_TYPE=Release                             \
  cmake -G Ninja \
       -DCMAKE_INSTALL_PREFIX=<LLVMクロスツールチェーンのインストールディレクトリ> \
       -DCMAKE_BUILD_TYPE=Release                           \
       -DCMAKE_C_COMPILER=/<クロスコンパイラのパス  例: aarch64-unknown-linux-gnu-gcc>  \  # CMakeツールチェーンファイルを使用しない場合
       -DCMAKE_INSTALL_PREFIX=<LLVMツールチェーンのインストールディレクトリ> \
      -DCMAKE_CXX_COMPILER=/<クロスコンパイラのパス  例: aarch64-unknown-linux-gnu-g++> \  # CMakeツールチェーンファイルを使用しない場合
       -DLLVM_ENABLE_PROJECTS="clang;clang-tools-extra;lld" \
      -DCMAKE_CXX_FLAGS='-march=armv8-a -mtune=cortex-a53'                       \  # CMakeツールチェーンファイルを使用しない場合 (左の例は、PinePhoneの場合)
       -DLLVM_TARGETS_TO_BUILD="X86;AArch64"               \
      -DCMAKE_TOOLCHAIN_FILE=<CMakeツールチェーンファイルのパス>                        \  # CMakeツールチェーンファイルを使用する場合
       -DLLVM_DEFAULT_TARGET_TRIPLE=aarch64-linux-gnu       \
      -DLLVM_NATIVE_TOOL_DIR=/<ホスト向けLLVMのインストールディレクトリ>/bin                \
       -DLLVM_ENABLE_LLD=ON                                \
      -DCMAKE_CROSSCOMPILING=1              \
       -DLLVM_ENABLE_LIBCXX=OFF                            \
      -DLLVM_TARGET_ARCH="AArch64"          \
       -DLLVM_ENABLE_ASSERTIONS=OFF                        \
       -DLLVM_TARGETS_TO_BUILD="AArch64"     \
       -DLLVM_OPTIMIZED_TABLEGEN=ON                        \
      -DLLVM_BUILD_RUNTIME=Off              \
       -DLLVM_PARALLEL_LINK_JOBS=2                          \
      -DLLVM_INCLUDE_TESTS=Off              \
      -DLLVM_INCLUDE_EXAMPLES=Off            \
      -DLLVM_ENABLE_BACKTRACES=Off          \
       -DLLVM_DEFAULT_TARGET_TRIPLE=aarch64-unknown-linux-gnu         \
       -DLLVM_TABLEGEN=/<ホスト向けLLVMのインストールディレクトリ>/bin/llvm-tblgen    \
       -DCLANG_TABLEGEN=/<ホスト向けLLVMのインストールディレクトリ>/bin/clang-tblgen  \
       -DCMAKE_LIBRARY_ARCHITECTURE=/<ターゲットのシステムルートのパス>/lib          \
       -DLLVM_ENABLE_PROJECTS="clang;clang-tools-extra;compiler-rt;lld;lldb" \
       -DLLVM_INSTALL_TOOLCHAIN_ONLY=On \
      -DLLDB_ENABLE_PYTHON=0          \
      -DLLDB_ENABLE_LIBEDIT=0          \
      -DLLDB_ENABLE_CURSES=0          \
      -DLLVM_BUILD_LLVM_DYLIB=On      \
      -DLLVM_LINK_LLVM_DYLIB=On        \
      -DDEFAULT_SYSROOT=<ターゲットのシステムルートディレクトリ> \
       ../llvm
       ../llvm
# ビルド
ninja -j$(nproc)
# インストール
ninja install
<br>
<br>
==== iOS ====
* -DCMAKE_BUILD_TYPE=Release
以下の例では、iOSをターゲットとしたLLVMをクロスビルドおよびインストールしている。<br>
*: 開発用途であればRelWithDebInfoでもよい。
*: <br>
* -DLLVM_ENABLE_PROJECTS="clang;clang-tools-extra;lld"
*: 必要なプロジェクトを指定する。
*: lld (LLVMリンカー) はクロスコンパイルで必要となる。
*: <br>
* -DLLVM_TARGETS_TO_BUILD="X86;AArch64"
*: ホスト (x64) と ターゲット (AArch64) の両方を含める。
*: これにより、両方のアーキテクチャ用にコンパイルできる。
*: <br>
* -DLLVM_DEFAULT_TARGET_TRIPLE=aarch64-linux-gnu
*: デフォルトのターゲットをAArch64に設定する。
*: ただし、Qtのビルドシステムでは明示的に指定することが多いため、このオプションは任意である。
*: <br>
* -DLLVM_ENABLE_LLD=ON
*: LLDリンカーを有効化する。
*: これは、クロスリンク時に便利である。
*: <br>
* -DLLVM_OPTIMIZED_TABLEGEN=ON
*: ビルド時間を短縮するための最適化
*: <br>
* -DLLVM_PARALLEL_LINK_JOBS=2
*: リンク処理の並列数を制限する。
*: メモリ不足を防ぐため、システムRAMが16[GB]未満の場合は1または2に設定することを推奨する。
<br>
 
==== ARM EABIHF ====
===== ABI / HF =====
ABIとは、コンパイルされたバイナリコード同士がどのように通信し合うかを定めるプロトコルである。<br>
ABIは関数を呼び出す際にどのレジスタを使うか、引数をどの順序でスタックに積むか、戻り値をどこに格納するか、構造体のメモリ配置はどうするか、といった細かい取り決めを規定している。<br>
<br>
異なるABIでコンパイルされたライブラリとプログラムは、例え同じCPUアーキテクチャであっても正しく連携できない。<br>
<br>
Hard Float ABIでは、浮動小数点演算の結果を浮動小数点専用のレジスタ (VFPレジスタ) を使用して関数間で受け渡す。<br>
<br>
EABIHFは32ビットARM用のABIである。<br>
* Raspberry Pi OS 32ビットでは、ARMv8でもEABIHF (hard-float) が使用可能。
* Raspberry Pi OS 64ビットでは、AAPCS64 (ARM Architecture Procedure Call Standard 64-bit) という別のABIを使用。
<br>
===== VFPレジスタ =====
Raspberry Pi 4以降でもVFPレジスタは存在するが、実装が進化している。<br>
* ARMv7以前 (Raspberry Pi 2 / 3等)
** VFP (Vector Floating Point) が独立したコプロセッサ
** VFPv3 / VFPv4として実装
** NEONと一部統合
*: <br>
* ARMv8-A (Raspberry Pi 4以降)
** 浮動小数点とSIMDが完全に統合
** 32個の128ビットレジスタ (V0-V31) として実装
** これらは以下のようにアクセス可能である。
*** 64ビット浮動小数点 : D0-D31
*** 32ビット浮動小数点 : S0-S31
*** 128ビットSIMD:V0-V31 (NEON)
<br>
32 / 64ビットで、利用できる機能やABIが異なるが、いずれにおいても浮動小数点演算用のレジスタは存在し、ハードウェアアクセラレーションが利用できる。<br>
<br>
===== ビルド / インストール =====
  mkdir build && cd build
  mkdir build && cd build
   
   
  cmake -G Ninja "Unix Makefiles"                                                          \
  cmake -G Ninja \
                -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=<LLVMのインストールディレクトリ> \
      -DCMAKE_BUILD_TYPE=Release                           \
                -DCMAKE_OSX_ARCHITECTURES="armv7;armv7s;arm64"                             \
      -DCMAKE_INSTALL_PREFIX=<LLVMツールチェーンのインストールディレクトリ> \
                -DCMAKE_TOOLCHAIN_FILE=<PATH_TO_LLVM>/cmake/platforms/iOS.cmake            \
      -DLLVM_ENABLE_PROJECTS="clang;clang-tools-extra;lld"  \
                -DLLVM_BUILD_RUNTIME=Off -DLLVM_INCLUDE_TESTS=Off                         \
      -DLLVM_TARGETS_TO_BUILD="X86;ARM;AArch64"             \
                -DLLVM_INCLUDE_EXAMPLES=Off -DLLVM_ENABLE_BACKTRACES=Off                  \
      -DLLVM_DEFAULT_TARGET_TRIPLE=arm-linux-gnueabihf      \
                ../llvm
      -DLLVM_ENABLE_LLD=ON                                  \
      -DLLVM_ENABLE_LIBCXX=OFF                              \
      -DLLVM_ENABLE_ASSERTIONS=OFF                         \
      -DLLVM_OPTIMIZED_TABLEGEN=ON                          \
      -DLLVM_PARALLEL_LINK_JOBS=2                          \
      ../llvm
   
   
  ninja -j $(nproc)
  ninja -j $(nproc)
  ninja install
  ninja install
<br>
Hard Float ABI用のCMakeツールチェーンファイルの例を以下に示す。<br>
<syntaxhighlight lang="cmake">
# ターゲットシステムの設定
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR arm)
# システムルートのパス (Hard Float ABI用のシステムルート)
set(CMAKE_SYSROOT <Hard Float ABI用のシステムルートのフルパス>)
# LLVMツールチェーンのパス
set(LLVM_PATH <LLVMツールチェーンのインストールディレクトリ>)
# コンパイラの指定
set(CMAKE_C_COMPILER ${LLVM_PATH}/bin/clang)
set(CMAKE_CXX_COMPILER ${LLVM_PATH}/bin/clang++)
# ターゲットトリプルの設定
# Hard Float ABIを使用するため、末尾に"hf"を追加
set(CMAKE_C_COMPILER_TARGET arm-linux-gnueabihf)
set(CMAKE_CXX_COMPILER_TARGET arm-linux-gnueabihf)
# 検索パスの設定
set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT})
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
# コンパイラフラグの設定
# Hard Float ABIを明示的に指定し、適切なFPUも指定する
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=armv8-a -mfpu=neon-vfpv4 -mfloat-abi=hard")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=armv8-a -mfpu=neon-vfpv4 -mfloat-abi=hard")
# リンカーフラグ
# ライブラリパスをHard Float ABI用のディレクトリに変更
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-rpath-link,${CMAKE_SYSROOT}/lib/arm-linux-gnueabihf")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-rpath-link,${CMAKE_SYSROOT}/usr/lib/arm-linux-gnueabihf")
</syntaxhighlight>
<br>
==== ARM EABI ====
Soft Float ABIでは、浮動小数点の値も汎用レジスタを使って受け渡す。<br>
<br>
Soft Float ABIが必要になる場面は、古いARMプロセッサやFPU (浮動小数点演算ユニット) を持たない組み込みシステムである。<br>
ARMv5 や ARMv6の一部のバリアント、コスト重視の産業用制御システムなどがこのカテゴリに入る。<br>
これらのシステムでは、浮動小数点演算は全てソフトウェアでエミュレートされるため、VFPレジスタを使った受け渡しができない。<br>
<br>
ただし、FPUを持つプロセッサであっても、Soft Float ABIでコンパイルすることは可能である。<br>
この場合、FPUは利用されず全ての浮動小数点演算がソフトウェアで処理される。<br>
これは、既存のSoft Float ABI用のライブラリとの互換性を保ちたい場合等に用いられる。<br>
<br>
mkdir build && cd build
cmake -G Ninja \
      -DCMAKE_BUILD_TYPE=Release                          \
      -DCMAKE_INSTALL_PREFIX=<LLVMツールチェーンのインストールディレクトリ> \
      -DLLVM_ENABLE_PROJECTS="clang;clang-tools-extra;lld" \
      -DLLVM_TARGETS_TO_BUILD="X86;ARM;AArch64"            \
      -DLLVM_DEFAULT_TARGET_TRIPLE=arm-linux-gnueabi      \
      -DLLVM_ENABLE_LLD=ON                                \
      -DLLVM_ENABLE_LIBCXX=OFF                            \
      -DLLVM_ENABLE_ASSERTIONS=OFF                        \
      -DLLVM_OPTIMIZED_TABLEGEN=ON                        \
      -DLLVM_PARALLEL_LINK_JOBS=2                          \
      ../llvm
ninja -j $(nproc)
ninja install
<br>
Soft Float ABI用のCMakeツールチェーンファイルの例を以下に示す。<br>
<syntaxhighlight lang="cmake">
# ターゲットシステムの設定
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR arm)
# システムルートのパス (Soft Float ABI用のシステムルート)
set(CMAKE_SYSROOT <Soft Float ABI用のシステムルートのフルパス>)
# LLVMツールチェーンのパス
set(LLVM_PATH <LLVMツールチェーンのインストールディレクトリ>)
# コンパイラの指定
set(CMAKE_C_COMPILER ${LLVM_PATH}/bin/clang)
set(CMAKE_CXX_COMPILER ${LLVM_PATH}/bin/clang++)
# ターゲットトリプルの設定
set(CMAKE_C_COMPILER_TARGET arm-linux-gnueabi)
set(CMAKE_CXX_COMPILER_TARGET arm-linux-gnueabi)
# 検索パスの設定
set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT})
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
# コンパイラフラグの設定
# Soft Float ABIを明示的に指定する
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=armv7-a -mfloat-abi=softfp")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=armv7-a -mfloat-abi=softfp")
# リンカーフラグ
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-rpath-link,${CMAKE_SYSROOT}/lib/arm-linux-gnueabi")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-rpath-link,${CMAKE_SYSROOT}/usr/lib/arm-linux-gnueabi")
</syntaxhighlight>
<br><br>
<br><br>


__FORCETOC__
__FORCETOC__
[[カテゴリ:RHEL]][[カテゴリ:SUSE]]
[[カテゴリ:RHEL]][[カテゴリ:SUSE]]