【クロスプラットフォームライブラリ開発ガイド】WindowsでMacOS向けにビルドしてテストする方法【Rust】

# 前置き
Rustでクロスプラットフォームライブラリを作る実践ガイド①

https://adventar.org/calendars/8825

アドカレ18日目
②はないです

# 前提
Rustの環境がある
WSL(Ubuntu)が入っている
空き容量が60GB程ある（最終的に10~20GB程持っていかれる）

# 手法
1. Linuxで、Mac向けにビルドを行えるようにする
2. MacOS環境を用意する
3. テストする

# 実践（Mac向けにビルド）
## LinuxでMac向けにビルドを行えるようにする

https://github.com/cross-rs/cross-toolchains

一部公式ドキュメントが間違っているので、詳細に説明します

### MacOSのSDKをパッケージング

https://developer.apple.com/download/all/?q=xcode%2013

Macのdevelopperアカウント（無料）にログインして、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/890310/0e83d126-40f4-ca9d-e088-fc56f1a39bc3.png)
をダウンロードします。

次にWSLで、
```bash:bash(WSL)
$ git clone https://github.com/tpoechtrager/osxcross
$ cd osxcross
osxcross$ sudo apt update
osxcross$ sudo apt upgrade
osxcross$ sudo apt install -y clang make cmake libssl-dev liblzma-dev lzma-dev libxml2-dev libbz2-dev
```
ここで、osxcross(現在)のフォルダ内にXcode_13.xipを移動させます(mvコマンドなど)。
その後、xipを解凍してSDKを取り出しパッケージングします
```bash:bash
osxcross$ ./tools/gen_sdk_package_pbzx.sh Xcode_13.xip
```
最終的に`MacOSX11.3.sdk.tar.xz`というフォルダができます
利用規約の都合上、絶対に他の人に上げたり、公開したりしてはいけないので注意しましょう

### Dockerをインストール
```bash:bash(WSL)
$ sudo apt install -y ca-certificates curl gnupg lsb-release
$ sudo mkdir -p /etc/apt/keyrings
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
$ echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
  $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
$ sudo apt update
$ sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin 
$ sudo groupadd docker
$ sudo usermod -aG docker $USER
$ sudo service docker start
$ ls -l /dev/kvm*
```
### dockerイメージの用意
元のフォルダに戻ってから行います
```bash:bash(WSL)
$ git clone https://github.com/cross-rs/cross
$ cd cross
cross$ git submodule update --init --remote
cross$ mv ../osxcross/MacOSX11.3.sdk.tar.xz docker/MacOSX11.3.sdk.tar.xz
cross$ cargo build-docker-image x86_64-apple-darwin-cross \
  --build-arg 'MACOS_SDK_FILE=MacOSX11.3.sdk.tar.xz'
```

### 試しにビルド
環境の用意
```bash:bash(WSL)
$ curl -L --proto '=https' --tlsv1.2 -sSf https://raw.githubusercontent.com/cargo-bins/cargo-binstall/main/install-from-binstall-release.sh | bash
$ cargo binstall cross
$ rustup target add x86_64-apple-darwin
```
実行するコードの用意
```bash:bash(WSL)
$ git clone https://github.com/tczajka/ibig-rs
$ cd ibig-rs
```
下記は通常の方法で行った場合で、失敗します
```bash:bash(WSL)
ibig-rs$ cargo build --release --example factorial --target x86_64-apple-darwin
> error: could not compile `ibig` (example "factorial") due to previous error
```
Crossという特殊なコマンドを利用して行ってみましょう
まず、`Cross.toml`という設定ファイルを用意します
```bash:bash(WSL)
ibig-rs$ cat <<EOF > Cross.toml
[target.x86_64-apple-darwin]
image = "ghcr.io/cross-rs/x86_64-apple-darwin-cross:local"
EOF
```
```bash:bash(WSL)
ibig-rs$ cross build --release --example factorial --target x86_64-apple-darwin
```
成功です！
ビルドしたものは規約上配れなかったと思うので注意しましょう

## 実行環境を用意する
MacOSの実行環境は幾つかあり、
- [OSX-KVM](https://github.com/kholia/OSX-KVM)
MacOSを動かせる仮想環境を用意し、OSを突っ込む
- [ravynOS](https://github.com/ravynsoft/ravynos)
MacOS互換のOS
- [Darling](https://github.com/darlinghq/darling)
仮想ランタイム環境

今回はWSLのような、コマンドを使える環境だけ欲しいため、Darling Shellを用います
### Darlingを用意する
```bash:bash(WSL)
$ sudo apt install cmake automake clang-15 bison flex libfuse-dev libudev-dev pkg-config libc6-dev-i386 \
gcc-multilib libcairo2-dev libgl1-mesa-dev curl libglu1-mesa-dev libtiff5-dev \
libfreetype6-dev git git-lfs libelf-dev libxml2-dev libegl1-mesa-dev libfontconfig1-dev \
libbsd-dev libxrandr-dev libxcursor-dev libgif-dev libavutil-dev libpulse-dev \
libavformat-dev libavcodec-dev libswresample-dev libdbus-1-dev libxkbfile-dev \
libssl-dev libstdc++-12-dev \
llvm ninja-build
$ git clone https://github.com/darlinghq/darling.git
$ cd darling
darling$ git checkout b75c25e2c192d005dec3f0613acc33b500d08172
darling$ git submodule update --init --recursive
darling$ mkdir build && cd $_
darling/build$ cmake -DADDITIONAL_PACKAGES=ON -DJSC_UNIFIED_BUILD=ON -GNinja ..
darling/build$ ninja
darling/build$ sudo ninja install
```
`ninja install`の際に、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/890310/cf149466-a0bc-ca38-22d7-947aa9153787.png)
となったら、
`rm ./src/csu/libcsu.a`してから`sudo ninja install`。
```bash:bash(WSL)
$ darling shell
Darling []$ ls
cross    darling  ibig-rs  osxcross
Darling []$ cd ibig-rs/target/x86_64-apple-darwin/release/examples
Darling [ibig-rs/target/x86_64-apple-darwin/release/examples]$ ./factorial
/****大量の数字****/
```
ということで上手くいきました！！！

## Darlingについて
実は、`Darling`は`brew`を入れることが可能です。MacOSと同じコマンドでInstallします。
また、いつものコマンドでRustをInstallすることが可能です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/890310/1cb2a506-4ace-1e5a-462b-a49dc62e31e4.png)
`brew install neofetch`を行うと、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/890310/4a148d31-412b-f6e3-6497-ea0df1f668eb.png)
となります。

### cargo
因みに、`cargo run --example factorial --release`を行うと、`(signal: 11, SIGSEGV: invalid memory reference)`が発生してビルドできなかったので、crossを入れた意味はあります。

### brew warning
そして、`brew`は`Xcode`のバージョンが古いと何もしてくれないので、`Command_Line_Tools_for_Xcode_12.3.dmg`をダウンロードしてきて、`WSL`のホームに置くと、`Darling`の`~/Downloads`にマウントされているので、インストールします。
※Xcode_12.4は、`Error: Your Command Line Tools (CLT) does not support macOS 10.15.
It is either outdated or was modified.`となりました。
試しに、`nodebrew`をインストールします。
```bash:Darling
Darling[]$ hdiutil attach Command_Line_Tools_for_Xcode_12.3.dmg
Darling[]$ sudo installer -pkg "/Volumes/Command_Line_Tools_for_Xcode_12.3/Command Line Tools.pkg" -target /
Darling[]$ brew install nodebrew
```
pkgのインストールに失敗した場合は、7zなどで.pkgを取り出すとよいです。
なお、最初に試したGo言語はよくわからないけど永遠に失敗しました。Darlingの問題に思えます。

#最後に
Go言語のインストールに失敗したりや、Rustのビルドに失敗したりなど、安定しているとは言えません。
また、Objective-C Runtimeも少なめです。Mac特有のAPIを使っていればいるほど失敗しやすいと思われます。
このように、Darling Shellは安定しているというわけではないですが、軽く試すことなどはできます。
Macなんて持ってないという方は、この方法で軽く遊んだり試して、本格的な確認は`Github Actions`などを用いて、クロスプラットフォームライブラリを作りましょう！！

# メモ書き
Ubuntu 22.04.3 LTSを1から入れ直して書いた記事なので、合っているはずです。

## 容量
WSLを入れたときの残り空き領域は100GB + ダウンロード済みXcode_13.xip 10GB
SDKのパッケージングが終わった時 58GB
Dockerを入れたとき 57GB
一時ファイルを全て削除した上で、下記を実行した後 108 GB ※絶対に何かミスりましたね

### WSLに持っていかれた容量はそのままでは返ってきません。下記コマンドでWindowsに戻すことができます。
https://blog.suraj-mittal.dev/reduce-wsl2-disk-filesize/

```powershell:wsl.exe
sudo fstrim /
ws
wsl --shutdown
diskpart
# open window Diskpart
select vdisk file="C:\path\to\…\ext4.vhdx"
attach vdisk readonly
compact vdisk
detach vdisk
exit
```

### 注意
Dockerのイメージは、50MBの`MacOSX11.3.sdk.tar.xz`さえあれば簡単に作れるから、これだけは別で取っておくこと
Darling Shellはビルドが長いので、むやみに削除しないこと