Rust + Visual Studio 2017 Expressで環境構築

WindowsでRustを業務利用する場合、Microsoft C++ Build Toolsでは使用できる範囲が限定されることがあるため、よりライセンスの緩いVisual Studio 2017 Express（以降WDExpress）で環境を構築する方法を記載します。

記事の最後に一連の設定を行うスクリプトがあります。

現在Visual Studio 2017 Expressは以下のURLからダウンロード出来ます。

http://aka.ms/vs/15/release/vs_WDExpress.exe

2024/07/18追記
本記事の内容を新規の環境にインストールするには以下の順序で行う必要があります。

1. Visual Studio 2017 Expressのインストール
1. SetupWDExpress.ps1(後述)を管理者で実行
1. rustup-init.exeの実行(Rustのインストール)

# WDExpressはRustでサポートされていない？

WDExpressとRustをセットアップした状態でCargo runを実行すると以下のエラーになります。

```powershell
error: linker `link.exe` not found
```

https://github.com/rust-lang/rust/issues/53474

このIssueに詳しい状況が記載されています。

Rustはリンカーの検出にホストOSのビット数を参考にフォルダを探そうとしているようで、64bitOSならHostx64、32bitOSならHostx86を探します。
WDExpressは他のエディション(Community、Professtional、Enterprise)と異なり、MSVC以下のフォルダにHostx86しかありません。Hostx64フォルダがあれば正常にリンカーを検出できるはずです。

# シンボリックリンクでHostx64フォルダの作成

VisualStudioをインストールすると
C:\Program Files (x86)\Microsoft Visual Studio\2017
にエディション毎のフォルダが作成されます。

WDExpressには以下のフォルダが存在します。（MSVC以下のバージョンは実際にインストールされているものを確認してください）

```powershell:インストール済みのフォルダ
\WDExpress\VC\Tools\MSVC\14.16.27023\bin\Hostx86
```

64bitOSでは以下のフォルダが存在すればRustがリンカーを検出してくれます。

```powershell:Rustが検索しようとするフォルダ
\WDExpress\VC\Tools\MSVC\14.16.27023\bin\Hostx64
```

RustがHostx64フォルダを見つけられれば良いので、シンボリックリンクでHostx86をHostx64の参照先にします。（これで中身の丸ごとコピーは回避出来ます。）
 PowerShellでシンボリックリンクは以下のコマンドで作成できます。

```powershell:シンボリックリンクの作成
# New-Item -ItemType SymbolicLink -Path "$destDir" -Target "$srcDir"
New-Item -ItemType SymbolicLink -Path C:\Program Files (x86)\Microsoft Visual Studio\2017\WDExpress\VC\Tools\MSVC\14.16.27023\bin\Hostx64 -Target C:\Program Files (x86)\Microsoft Visual Studio\2017\WDExpress\VC\Tools\MSVC\14.16.27023\bin\Hostx86
```

# DLLのパスを追加

シンボリックリンクを作成し、Cargoを実行した場合以下のエラーになります。

```powershell:cargo run 実行時のエラー
LINK : fatal error LNK1171: mspdb140.dll
```

このDLLは以下のディレクトリにあります。

```powershell:mspdb140.dllが存在するディレクトリ
C:\Program Files (x86)\Microsoft Visual Studio\2017\WDExpress\Common7\IDE
```

上記のディレクトリをPathに追加すれば、Rustのコンパイルが通るようになります。(x86_64、i686どちらもコンパイル出来ます)

# 環境構築用のスクリプト

これまでの一連の設定を適用するスクリプトです。管理者権限で実行してください。
また、スクリプト実行後に一度PowerShellを再起動してください。(Pathの反映のため)

## PowerShellのスクリプト実行を有効化

スクリプト実行が許可されていない場合に実行してください。

```batch:EnablePowerShell
PowerShell Set-ExecutionPolicy RemoteSigned
```

## Pathの追加とシンボリックリンクの作成

WDExpressのインストールディレクトリからバージョンを取得し、シンボリックリンクを作成するフォルダを特定しています。
バージョンは以下のファイルに記載されています。（改行コードがあるのでpathを結合する場合は注意が必要です）
C:\Program Files (x86)\Microsoft Visual Studio\2017\WDExpress\VC\Auxiliary\Build\Microsoft.VCToolsVersion.default.txt

```powershell:SetupWDExpress.ps1
echo "WDExpressのチェック"
if ((Test-Path "C:\Program Files (x86)\Microsoft Visual Studio\2017\WDExpress\Common7\IDE"))
{
    echo "ユーザ環境変数にDLLのフォルダを追加"
    $tmpUserPath = [System.Environment]::GetEnvironmentVariable("Path", "User")
    if (!($tmpUserPath.IndexOf(";C:\Program Files (x86)\Microsoft Visual Studio\2017\WDExpress\Common7\IDE", 0) -ge 0))
    {
        echo "PathにDLLのフォルダを追加"
        $tmpUserPath += ";C:\Program Files (x86)\Microsoft Visual Studio\2017\WDExpress\Common7\IDE"
        [System.Environment]::SetEnvironmentVariable("Path", $tmpUserPath, "User")
        echo "Hostx64用のシンボリックリンクを作成"
        $version = Get-Content "C:\Program Files (x86)\Microsoft Visual Studio\2017\WDExpress\VC\Auxiliary\Build\Microsoft.VCToolsVersion.default.txt" -Raw
        $version = [regex]::Replace($version, "\r\n", { "" }) #
        $targetDir = "C:\Program Files (x86)\Microsoft Visual Studio\2017\WDExpress\VC\Tools\MSVC\" + $version + "\bin\"
        $srcDir = $targetDir + "Hostx86"
        $destDir = $targetDir + "Hostx64"
        echo "New-Item -ItemType SymbolicLink -Path $destDir -Target $srcDir"
        New-Item -ItemType SymbolicLink -Path "$destDir" -Target "$srcDir"
    }
}
```

cargoを実行し、正常にビルドが出来るか確認します。

```powershell:64bit、32bitの実行
cargo run --release
cargo run --release --target=i686-pc-windows-msvc
```