WSL2 Ubuntu 20.04でWindows用のバイナリをクロスコンパイルしたい
コンパイラはclang. これは https://releases.llvm.org/download.html からPre-Built Binaryがダウンロードできるため(11.0.0).
clangのクロスコンパイルについては https://releases.llvm.org/11.0.0/tools/clang/docs/CrossCompilation.html に記述があるため読んでみる。
まず-target
。何を渡せばいいのか? -print-targets, --print-targets はarchの一覧が出るだけ。
--target-help は一見役立ちそうだが使い方が不明。
gccのマニュアルによると
Print (on the standard output) a description of target-specific command-line options for each tool. For some targets extra target-specific information may also be printed.
なので関係ない。
適当にllvmのgitリポジトリを"windows"で検索してみたところ、sys
はwindows
がありそう。というかwin32
と書いてもwindows
になる。
$ clang -print-target-triple -target x86_64-unknown-win32-unknown
x86_64-unknown-windows-msvc
試してみる。
$ clang -target x86_64-unknown-windows-unknown -fuse-ld=lld --rtlib=compiler-rt
lld-link: error: could not open '/usr/local/lib/clang/11.0.0/lib/windows/clang_rt.builtins-x86_64.lib': No such file or directory
lld-link: error: could not open 'libcmt.lib': No such file or directory
/usr/local/lib/clang/11.0.0/lib/windows
がない。当たり前か。
libcmt.lib
とは、 https://docs.microsoft.com/ja-jp/cpp/c-runtime-library/crt-library-features?view=msvc-170 を見ると、なんとなく crt?.o
っぽいので、VC++を入れなきゃ手に入らない気がする。
msvc
以外のabi
はないのか。
llvmのリポジトリを眺めていると、windows
に関してMinGW, Cygwinが有効であることがわかった。
$ clang -print-effective-triple -target x86_64-unknown-mingw-unknown
x86_64-unknown-windows-gnu
$ clang -print-effective-triple -target x86_64-unknown-cygwin-unknown
x86_64-unknown-windows-cygnus
MinGWが最も期待が高い。
$ clang -target x86_64-unknown-mingw-unknown -fuse-ld=lld --rtlib=compiler-rt
lld: error: unable to find library -lmingw32
lld: error: unable to find library -lmoldname
lld: error: unable to find library -lmingwex
lld: error: unable to find library -lmsvcrt
lld: error: unable to find library -ladvapi32
lld: error: unable to find library -lshell32
lld: error: unable to find library -luser32
lld: error: unable to find library -lkernel32
lld: error: unable to find library -lmingw32
lld: error: unable to find library -lmoldname
lld: error: unable to find library -lmingwex
lld: error: unable to find library -lmsvcrt
lld: error: unable to find library -lkernel32
mingw-w64-x86-64-dev
# apt install mingw-w64-x86-64-dev
$ clang -target x86_64-unknown-mingw-unknown -fuse-ld=lld --rtlib=compiler-rt -L/usr/x86_64-w64-mingw32/lib
lld-link: error: could not open '/usr/local/lib/clang/11.0.0/lib/windows/libclang_rt.builtins-x86_64.a': No such file or directory
$ clang -target x86_64-unknown-mingw-unknown -fuse-ld=lld -L/usr/x86_64-w64-mingw32/lib
lld: error: unable to find library -lgcc
lld: error: unable to find library -lgcc_eh
# apt install gcc-mingw-w64-x86-64
$ clang -target x86_64-unknown-mingw-unknown -fuse-ld=lld -L/usr/x86_64-w64-mingw32/lib -L/usr/lib/gcc/x86_64-w64-mingw32/9.3-win32
動いた。
そう言えばここまでのソースは以下のように最低限。
int
main(void)
{
return 0;
}
次はこれ
#include <stdio.h>
int
main(void)
{
(void)printf("Hello,World!\n");
return 0;
}
$ clang -target x86_64-unknown-mingw-unknown -fuse-ld=lld -L/usr/x86_64-w64-mingw32/lib -L/usr/lib/gcc/x86_64-w64-mingw32/9.3-win32
fatal error: 'stdio.h' file not found
これはmingw-w64-x86-64-devに入っているので
$ clang -target x86_64-unknown-mingw-unknown -isystem /usr/x86_64-w64-mingw32/include -fuse-ld=lld -L/usr/x86_64-w64-mingw32/lib -L/usr/lib/gcc/x86_64-w64-mingw32/9.3-win32
>helloworld.exe
Hello,World!
とりあえず成功。
コンパイラランタイムもclangにしたいな……
こうすべきだったっぽい
$ clang -target x86_64-unknown-mingw-unknown --sysroot=/usr/x86_64-w64-mingw32 -fuse-ld=lld -L/usr/lib/gcc/x86_64-w64-mingw32/9.3-win32
-mcpu
だの-mfpu
だのについては、まずx86_64
が使えるオプションについて https://gcc.gnu.org/onlinedocs/gcc-11.2.0/gcc/x86-Options.html#x86-Options (と、 https://gcc.gnu.org/onlinedocs/gcc-11.2.0/gcc/x86-Windows-Options.html#x86-Windows-Options ) を参照。
-mtune=native
だけでいいと思われる。というかこれはクロスコンパイルに限らずつけたほうがよい。
なお
-mcpu=cpu-type
A deprecated synonym for -mtune.
MinGWはPOSIXのあれも結構動く。
しかし例えば、setenv()
はない。
$ rg -Lqw setenv /usr/x86_64-w64-mingw32/include/; echo $?
1
$ llvm-nm --defined-only /usr/x86_64-w64-mingw32/lib/lib*.a | rg -Lqw seten
v; echo $?
1
https://osdn.net/projects/mingw/scm/git/mingw-org-wsl/blobs/5.5-trunk/mingwrt/mingwex/setenv.c にはあるので、バージョンの問題なのだろう。
あとやりたいこと: compiler-rtをWindows(MinGW)向けにクロスコンパイル
めんどいので後回しかな……
clang最新版は https://github.com/llvm/llvm-project/releases から探すのが良い。Ubuntu 20.04はLLVM 13.0.0にある。
何故か18.04が優遇されていて、14.0.0もある。
llvm-mingw というのがある。これがあればmingw-w64-x86-64-dev
もgcc-mingw-w64-x86-64
も要らない。
clangのバージョンを合わせたllvm-mingw-<release>-ucrt-x86_64.zip
を持ってきて展開。更に中の lib/clang/13.0.0/lib/windows
をclangの同じ階層に持ってくる。
これにより
clang -target x86_64-unknown-mingw-unknown --sysroot=/path/to/llvm-mingw --rtlib=compiler-rt -fuse-ld=lld
で動く。