clang-cl + cmake + ninja で Windows バイナリのコマンドラインビルド, クロスコンパイルのメモ

## 背景

* clang(-cl) を Windows コマンドライン, Linux(WSL) で動かし, MSVC 互換でコンパイルしたい
* ビルドには cmake, ninja を使う

Windows バイナリのビルドは, llvm-mingw がおすすめですが, MSVC 互換オプションでビルド確認したい, MSVC ビルドの補助として clang-cl でビルド CI を構築したい, etc など, clang-cl を使いたいときもあります.

## clang-cl とは?

https://releases.llvm.org/download.html

の windows prebuilt や, Visual Studio インストーラー, C++ Build Tools インストーラーとかでもインストールできます.

clang での, MSVC の引数(と, MSVC 用 ABI とか?)の互換性のあるコンパイルモードです.
ただ, コンパイル自体は MSVC 互換というわけではないため, 細かいところでは違いがあります(builtin 命令とか)
icc(Intel C Compiler)みたいな感じで使う感じでしょうか.

動作モードは, `--drver-model` もしくはコマンドの起動名(exe 名)で MSVC モードにするかどうか判断しています.

https://github.com/llvm/llvm-project/blob/master/clang/lib/Driver/ToolChain.cpp#L138

したがって, `clang --driver-mode=cl` でも MSVC モードになりますす.

`--driver-mode` は引数のどの位置にあっても大丈夫そうです.

```
clang /I. --driver-mode=cl muda.cc
```

もいけました.

clang 自体が target 設定で cross-compile できますので, クロスコンパイル時(Linux/WSL でのビルド時)の clang-cl 自体は Linux binary(ELF)を使うことができます.

## Windows SDK 

Header やリンクライブラリ(.lib)として, Windows SDK が必要になります.
(MinGW でも行けるかも?)

オンラインに Licensing term が上がっていないのですが, 一応 Windows SDK を, Windows SDK installer で入れて, `Licneses` フォルダのライセンス条項を見てみました. 

Windows 向けのアプリを開発する, 自社(自身)のネットワーク内でエンドユーザーとしての利用にかぎる, 以外は特に制約もない感じでしたので, 少なくとも header/lib のファイル群を Linux に持って行って clang-cl でクロスコンパイルに使うのはライセンス上問題ないでしょう.

Windows 側で作業する場合, Visual Studio 2019 or C++ Build Tools https://visualstudio.microsoft.com/visual-cpp-build-tools/ でも Windows SDK をインストールできます.

デフォルトでは, `C:¥Program Files (x86)¥Windows Kits¥10` にインストールされます.

## Microsoft STL

なぜか無駄に新しい環境を要求されます(e.g. cmake 3.16)

boost 依存(!)してつらいのですが, 実際に利用しているのは math 関数での特殊関数を(e.g. `bessel`)を実装しているところだけです. したがって bcp あたりで math 部分だけ抜き出した boost パッケージでうまくビルドできるのではないかと思います.

boostの一部のみを使う
https://qiita.com/kk-river/items/999dd21adaddd7d53b81

Boost を Android 向けに bjam ビルドするテクニック(NDK r19c or later)
https://qiita.com/syoyo/items/dbc063a54554be9226a5

残念ながら, 現状 Cmake では clang-cl でのビルドには対応していません.
いろいろ頑張れば clang-cl でもコンパイルできるかもしれません
(MSVC headers/lib も必要)

### MSVC headers/sdk

https://github.com/paleozogt/MSVCDocker

https://github.com/mstorsjo/msvc-wine

あたりを参考にして, aka.ms あたり経由でオフラインバッチで Windows SDK と MSVC headers/sdk 落とせます.

ただ, MSVC headers/sdk 含め, MSVC standalone compiler(C++ Build Tools)も落とせますが, これは Visual Studio のライセンスと一緒に使うときのみライセンス許諾なので注意ください.

Microsoft C++ Build Tools (2019) not allowed for use with Visual Studio Code?
https://law.stackexchange.com/questions/49477/microsoft-c-build-tools-2019-not-allowed-for-use-with-visual-studio-code

にあるように, Microsoft 自身がライセンス違反をしてそうなチュートリアル公開していますがどうなんでしょうかね?

MSVC headers/libs だけ clang-cl で利用する場合はどうなるかな?


## CMake

単に `clang-cl` を `CMAKE_CXX_COMPILER` にしても, 通常の gcc/clang モードと判定されてしまします.

cmake では, MSVC 用の環境変数などが設定さているかどうかで, MSVC モードかどうかを判定しているようです(詳細は cmake のソースコードを解析すればいけるが, 面倒なので見調査)


## 環境設定(MSVC 利用)

今までは `vcbarsall.bat` が使われていたようですが,  VS2017 くらいから `vsdevcmd.bat` が推奨になっているようです.

バッチスクリプトでは, 以下のように call コマンドを使います.

```
call <msvcpath>¥vsdevcmd.bat

```

`<msvcpath>`は VS ごとに変わります. C++ Build Tools(2019) だと, デフォルトでは

`C:¥Program Files (x86)¥Microsoft Visual Studio¥2019¥BuildTools¥Common7¥Tools`

あたりにあります.

## 環境設定(MSVC を利用しない版)

https://qiita.com/syoyo/items/bd4f81e7803afb5a3d19

を参照ください.

## Target triple

`x86_64-windows
T.B.W.

## TODO

* [x] msvc-wine あたりでの設定を参考にして環境変数設定することで, `vsdevcmd.bat` を呼ばずにビルドできるようにする.