2021年02月19日
Ubuntu上でWindows用clangをカナディアンクロスビルドする
Binutils や GCC は、Ubuntu 上で Windows で動作する、組み込み向け(RISC-V など)のコンパイラツールチェーンを簡単にビルドできます(カナディアンクロスビルド)。configure の際に --target=riscv64-unknown-elf --host=x86_64-w64-mingw32 --build=x86_64-pc-linux-gnu を指定するだけで、後は基本的にネイティブと同じです。この時、Ubuntu 上(x86_64-pc-linux-gnu)で動作するクロスの x86_64-w64-mingw32-gcc(g++)でビルドが行われるという仕組みです。
Clang の場合、CMake でどのように設定すれば良いのかとか、Windows バイナリを生成可能な clang が Ubuntu 上に見当たらなかった(clang をビルドするには、MinGW gcc ではなく、clang が必要)などの理由により、これまでは VisualStudio を使って Windows 上でビルドしていました。
今回、以下の記事で llvm-mingw の存在を知り、無事カナディアンクロスビルドに成功しました。
Clang の場合、CMake でどのように設定すれば良いのかとか、Windows バイナリを生成可能な clang が Ubuntu 上に見当たらなかった(clang をビルドするには、MinGW gcc ではなく、clang が必要)などの理由により、これまでは VisualStudio を使って Windows 上でビルドしていました。
今回、以下の記事で llvm-mingw の存在を知り、無事カナディアンクロスビルドに成功しました。
参考記事
「libclang/libLLVM を Windows(MinGW) 向けに llvm-mingw でクロスコンパイルするメモ(10.0.0 or later)」
clang をクロスビルドする際には、llvm-tblgen と clang-tblgen が必要なので、一度 Linux 向けに clang をビルドします。環境構築の方法は、この過去記事を参照してください。
「Ubuntu 18.04 LTSで最新のClang12をビルドする方法」
ビルド環境は Ubuntu 18.04 LTS です。
今回は build_linux で Linux 用をビルドして install_linux にインストール。build_mingw で Windows 用をビルドして install_mingw にインストールします。
「libclang/libLLVM を Windows(MinGW) 向けに llvm-mingw でクロスコンパイルするメモ(10.0.0 or later)」
clang をクロスビルドする際には、llvm-tblgen と clang-tblgen が必要なので、一度 Linux 向けに clang をビルドします。環境構築の方法は、この過去記事を参照してください。
「Ubuntu 18.04 LTSで最新のClang12をビルドする方法」
ビルド環境は Ubuntu 18.04 LTS です。
今回は build_linux で Linux 用をビルドして install_linux にインストール。build_mingw で Windows 用をビルドして install_mingw にインストールします。
~/work/test/clang_canadian_cross_build$ git clone https://github.com/llvm/llvm-project.git $ cd llvm-project/ $ git log -1 commit df2940aa85f0265c5f718cb23546404246667b99 (HEAD -> main, origin/main, origin/HEAD) Author: Vitaly Buka1 回目の clang のビルドです。今回は libc や libcompiler_rt はビルドしないので、テストはあまり意味が無いのですが、一応動かしました。clang-tblgen などはインストールされないので、手動で cp しています。Date: Thu Feb 18 17:22:32 2021 -0800 [android] Fix testing adb call Looks like some debug leftover which force another retry. $ cd .. $ mkdir build_linux build_mingw install_linux install_mingw
$ mkdir build_linux build_mingw install_linux install_mingw $ cd build_linux/ $ cmake -DLLVM_ENABLE_PROJECTS="clang;lld" -G "Unix Makefiles" ../llvm-project/llvm -DLLVM_ENABLE_ASSERTIONS=ON -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../install_linux -DLLVM_TARGETS_TO_BUILD="RISCV" -DLLVM_DEFAULT_TARGET_TRIPLE=riscv64-unknown-elf -DLLVM_BUILD_EXAMPLES=OFF -DLLVM_INCLUDE_EXAMPLES=OFF -DBUILD_SHARED_LIBS=OFF -DLLVM_OPTIMIZED_TABLEGEN=ON -DLLVM_ENABLE_LIBXML2=OFF $ make -j64 $ make check-all -j64 Failed Tests (5): Clang :: CodeGen/sanitize-coverage-old-pm.c Clang :: Driver/as-options.s Clang :: Driver/clang-s-opts.s Clang :: Driver/lto.c LLVM :: DebugInfo/Generic/missing-abstract-variable.ll Testing Time: 92.52s Unsupported : 28953 Passed : 43158 Expectedly Failed: 63 Failed : 5 $ make install $ cp bin/* ../install_linux/bin適当な所に llvm-mingw をダウンロードして、build_linux と一緒に PATH を通しておきます。msvcrt はもう古いらしく、ucrt の方が良いのかもしれませんが、今回は msvcrt で試しました。
$ cd /home/kmc/Downloads $ wget https://github.com/mstorsjo/llvm-mingw/releases/download/20201020/llvm-mingw-20201020-msvcrt-ubuntu-18.04.tar.xz $ tar xvf llvm-mingw-20201020-msvcrt-ubuntu-18.04.tar.xz $ export LLVM_MINGW_PATH=/home/kmc/Downloads/llvm-mingw-20201020-msvcrt-ubuntu-18.04 $ export INSTALL_LINUX=/home/kmc/work/test/clang_canadian_cross_build/install_linux $ export PATH=$INSTALL_LINUX/bin:$LLVM_MINGW_PATH/bin:$PATHちゃんと PATH が通っているか確認しておきます。
$ x86_64-w64-mingw32-clang -v clang version 11.0.0 (https://github.com/llvm/llvm-project.git 176249bd6732a8044d457092ed932768724a6f06) Target: x86_64-w64-windows-gnu Thread model: posix InstalledDir: /home/kmc/Downloads/llvm-mingw-20201020-msvcrt-ubuntu-18.04/bin $ x86_64-w64-mingw32-clang++ -v clang version 11.0.0 (https://github.com/llvm/llvm-project.git 176249bd6732a8044d457092ed932768724a6f06) Target: x86_64-w64-windows-gnu Thread model: posix InstalledDir: /home/kmc/Downloads/llvm-mingw-20201020-msvcrt-ubuntu-18.04/bin $ llvm-tblgen --version LLVM (http://llvm.org/): LLVM version 13.0.0git Optimized build with assertions. Default target: riscv64-unknown-elf Host CPU: znver2 $ clang-tblgen --version LLVM (http://llvm.org/): LLVM version 13.0.0git Optimized build with assertions. Default target: riscv64-unknown-elf Host CPU: znver2バイナリサイズが肥大化してしまう問題がありますが、今回は dll のコピーなどの面倒を避けるために全部 static link します。
$ cd build_mingw $ cmake -DLLVM_ENABLE_PROJECTS="clang;lld" -G "Unix Makefiles" ../llvm-project/llvm -DCMAKE_CROSSCOMPILING=True -DCMAKE_SYSTEM_NAME=Windows -DLLVM_TABLEGEN=$INSTALL_LINUX/bin/llvm-tblgen -DCLANG_TABLEGEN=$INSTALL_LINUX/bin/clang-tblgen -DLLVM_CONFIG_PATH=$INSTALL_LINUX/bin/llvm-config -DCMAKE_C_COMPILER=x86_64-w64-mingw32-clang -DCMAKE_CXX_COMPILER=x86_64-w64-mingw32-clang++ -DCMAKE_RC_COMPILER=x86_64-w64-mingw32-windres -DLLVM_ENABLE_ASSERTIONS=ON -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../install_mingw -DLLVM_TARGETS_TO_BUILD="RISCV" -DLLVM_DEFAULT_TARGET_TRIPLE=riscv64-unknown-elf -DLLVM_BUILD_EXAMPLES=OFF -DLLVM_INCLUDE_EXAMPLES=OFF -DBUILD_SHARED_LIBS=OFF -DLLVM_OPTIMIZED_TABLEGEN=ON -DLLVM_ENABLE_LIBXML2=OFF -DCMAKE_C_FLAGS="-static" -DCMAKE_CXX_FLAGS="-static" $ make -j64 && make installバイナリサイズが 110MB もありますが、とりあえずビルドはできました。
$ du -h ../install_mingw/bin/clang.exe 110M ../install_mingw/bin/clang.exe依存 dll も無く、無事に Windows 上で動きました。
dumpbin /dependents y:\work\test\clang_canadian_cross_build\install_mingw\bin\clang.exe Microsoft (R) COFF/PE Dumper Version 10.00.40219.01 Copyright (C) Microsoft Corporation. All rights reserved. Dump of file y:\work\test\clang_canadian_cross_build\install_mingw\bin\clang.exe File Type: EXECUTABLE IMAGE Image has the following dependencies: KERNEL32.dll msvcrt.dll SHELL32.dll ole32.dll ADVAPI32.dll VERSION.dll C:\Users\kmc\test>y:\work\test\clang_canadian_cross_build\install_mingw\bin\clang.exe -v clang version 13.0.0 (https://github.com/llvm/llvm-project.git df2940aa85f0265c5f718cb23546404246667b99) Target: riscv64-unknown-unknown-elf Thread model: posix InstalledDir: y:\work\test\clang_canadian_cross_build\install_mingw\bin