Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MSBuildの探索手順を変更する #1785

Merged
6 commits merged into from Feb 2, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
185 changes: 99 additions & 86 deletions tools/find-tools.bat
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,38 @@ setlocal

if "%1" equ "clear" (
endlocal
set CMD_GIT=
set CMD_7Z=
set CMD_HHC=
set CMD_ISCC=
set CMD_CPPCHECK=
set CMD_DOXYGEN=
set CMD_VSWHERE=
set CMD_MSBUILD=
set CMD_CMAKE=
set CMD_NINJA=
set CMD_LEPROC=
set CMD_PYTHON=
set NUM_VSVERSION=
set CMAKE_G_PARAM=
set FIND_TOOLS_CALLED=
call :clear_variables
echo find-tools.bat has been cleared
exit /b
) else if "%~1" neq "" (
)

if not defined CMD_VSWHERE call :vswhere 2> nul
if not exist "%CMD_VSWHERE%" (
echo vswhere was not found
exit /b
)

set ARG_VSVERSION=
if "%1" neq "" (
set "ARG_VSVERSION=%~1"
)
call :convert_arg_vsversion
if not defined ARG_VSVERSION (
call :convert_arg_vsversion
)

if defined NUM_VSVERSION (
if "%ARG_VSVERSION%" neq "%NUM_VSVERSION%" (
endlocal
call :clear_variables
setlocal
set "ARG_VSVERSION=%~1"
call :vswhere
call :convert_arg_vsversion
)
)
set NUM_VSVERSION=%ARG_VSVERSION%

if defined FIND_TOOLS_CALLED (
echo find-tools.bat already called
exit /b
Expand All @@ -35,7 +47,6 @@ if not defined CMD_HHC call :hhc 2> nul
if not defined CMD_ISCC call :iscc 2> nul
if not defined CMD_CPPCHECK call :cppcheck 2> nul
if not defined CMD_DOXYGEN call :doxygen 2> nul
if not defined CMD_VSWHERE call :vswhere 2> nul
if not defined CMD_MSBUILD call :msbuild 2> nul
if not defined CMD_CMAKE call :cmake 2> nul
if not defined CMD_NINJA call :cmake 2> nul
Expand Down Expand Up @@ -75,6 +86,62 @@ endlocal ^
set FIND_TOOLS_CALLED=1
exit /b

:clear_variables
set CMD_GIT=
set CMD_7Z=
set CMD_HHC=
set CMD_ISCC=
set CMD_CPPCHECK=
set CMD_DOXYGEN=
set CMD_VSWHERE=
set CMD_MSBUILD=
set CMD_CMAKE=
set CMD_NINJA=
set CMD_LEPROC=
set CMD_PYTHON=
set NUM_VSVERSION=
set CMAKE_G_PARAM=
set FIND_TOOLS_CALLED=
exit /b

:convert_arg_vsversion
if not defined ARG_VSVERSION (
set "ARG_VSVERSION=%NUM_VSVERSION%"
)
if not defined ARG_VSVERSION (
set "ARG_VSVERSION=latest"
)

:: convert productLineVersion to Internal Major Version
if "%ARG_VSVERSION%" == "2017" (
set ARG_VSVERSION=15
) else if "%ARG_VSVERSION%" == "2019" (
set ARG_VSVERSION=16
) else if "%ARG_VSVERSION%" == "2022" (
set ARG_VSVERSION=17
) else if "%ARG_VSVERSION%" == "latest" (
call :get_latest_installed_vsversion
)
::指定されたバージョンのC++がインストールされているかチェック
set /a ARG_VSVERSION_NEXT=ARG_VSVERSION + 1
for /f "usebackq delims=" %%d in (`"%CMD_VSWHERE%" -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath -version [%ARG_VSVERSION%^,%ARG_VSVERSION_NEXT%^)`) do (
if exist "%%d" exit /b
)
::指定されたバージョンが存在しなければ「指定なし」にしてやり直す
set ARG_VSVERSION=
exit /b

:get_latest_installed_vsversion
for /f "usebackq delims=" %%v in (`"%CMD_VSWHERE%" -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationVersion -latest`) do (
set VSVERSION=%%v
)
if defined VSVERSION (
set ARG_VSVERSION=%VSVERSION:~0,2%
) else (
set ARG_VSVERSION=15
)
exit /b

:Git
set APPDIR=Git\Cmd
set PATH2=%PATH%;%ProgramFiles%\%APPDIR%\;%ProgramFiles(x86)%\%APPDIR%\;%ProgramW6432%\%APPDIR%\;
Expand Down Expand Up @@ -152,95 +219,41 @@ exit /b

:: ---------------------------------------------------------------------------------------------------------------------
:: sub routine for finding msbuild
::
:: ARG_VSVERSION
:: latest => the latest version of installed Visual Studio
:: 2017 => Visual Studio 2017
:: 2019 => Visual Studio 2019
:: 15 => Visual Studio 2017
:: 16 => Visual Studio 2019
:: ---------------------------------------------------------------------------------------------------------------------
:msbuild
:: convert productLineVersion to Internal Major Version
if "%ARG_VSVERSION%" == "" (
set NUM_VSVERSION=15
) else if "%ARG_VSVERSION%" == "2017" (
set NUM_VSVERSION=15
) else if "%ARG_VSVERSION%" == "2019" (
set NUM_VSVERSION=16
) else if "%ARG_VSVERSION%" == "2022" (
set NUM_VSVERSION=17
) else if "%ARG_VSVERSION%" == "latest" (
call :check_latest_installed_vsversion
) else (
set NUM_VSVERSION=%ARG_VSVERSION%
)

call :check_installed_vsversion

call :find_msbuild
if not exist "%CMD_MSBUILD%" (
call :find_msbuild_legacy
set NUM_VSVERSION=15
)

:: vs2017単独インストールで導入されるvswhereには機能制限がある
if "%NUM_VSVERSION%" == "15" (
call :find_msbuild_legacy
set CMAKE_G_PARAM=Visual Studio 15 2017
) else if "%NUM_VSVERSION%" == "16" (
set CMAKE_G_PARAM=Visual Studio 16 2019
) else if "%NUM_VSVERSION%" == "17" (
set CMAKE_G_PARAM=Visual Studio 17 2022
) else (
call :find_msbuild
call :set_cmake_gparam_automatically
)
exit /b

:set_cmake_gparam_automatically
call :get_product_line_version
set CMAKE_G_PARAM=Visual Studio %NUM_VSVERSION% %VS_PRODUCT_LINE_VERSION%
exit /b

:get_product_line_version
set /a NUM_VSVERSION_NEXT=NUM_VSVERSION + 1
for /f "usebackq delims=" %%v in (`"%CMD_VSWHERE%" -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property catalog_productLineVersion -version [%NUM_VSVERSION%^,%NUM_VSVERSION_NEXT%^)`) do (
set VS_PRODUCT_LINE_VERSION=%%v
)
exit /b

:check_latest_installed_vsversion
for /f "usebackq delims=" %%v in (`"%CMD_VSWHERE%" -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationVersion -latest`) do (
set VSVERSION=%%v
)
set NUM_VSVERSION=%VSVERSION:~0,2%
exit /b

:check_installed_vsversion
set /a NUM_VSVERSION_NEXT=NUM_VSVERSION + 1
for /f "usebackq delims=" %%d in (`"%CMD_VSWHERE%" -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath -version [%NUM_VSVERSION%^,%NUM_VSVERSION_NEXT%^)`) do (
if exist "%%d" exit /b
)
call :check_latest_installed_vsversion
exit /b

:find_msbuild
set /a NUM_VSVERSION_NEXT=NUM_VSVERSION + 1
for /f "usebackq delims=" %%a in (`"%CMD_VSWHERE%" -requires Microsoft.Component.MSBuild -find MSBuild\**\Bin\MSBuild.exe -version [%NUM_VSVERSION%^,%NUM_VSVERSION_NEXT%^)`) do (
set "CMD_MSBUILD=%%a"
)
if exist "%CMD_MSBUILD%" (
exit /b
)
set CMD_MSBUILD=
exit /b

:find_msbuild_legacy
for /f "usebackq delims=" %%d in (`"%CMD_VSWHERE%" -requires Microsoft.Component.MSBuild -property installationPath -version [15^,16^)`) do (
set "CMD_MSBUILD=%%d\MSBuild\15.0\Bin\MSBuild.exe"
)
if exist "%CMD_MSBUILD%" (
exit /b
exit /b

:set_cmake_gparam_automatically
call :get_product_line_version
set CMAKE_G_PARAM=Visual Studio %NUM_VSVERSION% %VS_PRODUCT_LINE_VERSION%
exit /b

:get_product_line_version
set /a NUM_VSVERSION_NEXT=NUM_VSVERSION + 1
for /f "usebackq delims=" %%v in (`"%CMD_VSWHERE%" -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property catalog_productLineVersion -version [%NUM_VSVERSION%^,%NUM_VSVERSION_NEXT%^)`) do (
set VS_PRODUCT_LINE_VERSION=%%v
)
set CMD_MSBUILD=
exit /b

:cmake
Expand Down Expand Up @@ -284,7 +297,7 @@ exit /b
call :find_py
call :check_python_version
if defined CMD_PYTHON (
exit /b 0
exit /b 0
)

call :find_python
Expand Down
52 changes: 22 additions & 30 deletions tools/find-tools.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
| Inno Setup 5 | CMD_ISCC | Inno Setup 5 | ISCC.exe |
| Cppcheck | CMD_CPPCHECK | cppcheck | cppcheck.exe |
| Doxygen | CMD_DOXYGEN | doxygen\bin | doxygen.exe |
| vswhere | CMD_VSWHERE | Microsoft Visual Studio\Installer | vswhere.exe |
| Visual Studio Locator | CMD_VSWHERE | Microsoft Visual Studio\Installer | vswhere.exe |
This conversation was marked as resolved.
Show resolved Hide resolved
| MSBuild | CMD_MSBUILD | 特殊 | MSBuild.exe |
| Locale Emulator | CMD_LEPROC | なし | LEProc.exe |
| Python | CMD_PYTHON | なし | py.exe (python.exe) |
Expand All @@ -41,39 +41,31 @@ MSBuild以外の探索手順は同一であり、7-Zipを例に説明する。

### ユーザーがビルドに使用する Visual Studio のバージョンを切り替える方法

環境変数 ```ARG_VSVERSION``` の値でビルドに使用するバージョンを切り替えられる。
環境変数 `NUM_VSVERSION` の値でビルドに使用するバージョンを切り替えられる。

| ARG_VSVERSION | 使用される Visual Studio のバージョン |
| -------------- | ------------------------------------- |
| 空 | インストールされている Visual Studio の最新 |
| 15 | Visual Studio 2017 |
| 16 | Visual Studio 2019 |
| 2017 | Visual Studio 2017 |
| 2019 | Visual Studio 2019 |
| NUM_VSVERSION | 使用される Visual Studio のバージョン |
| -------------- | -------------------------------------- |
| (未定義) | インストールされている最新のバージョン |
| 15 | Visual Studio 2017 |
| 16 | Visual Studio 2019 |
| 17 | Visual Studio 2022 |

### 検索ロジック

1. `ARG_VSVERSION` から`VC++`のバージョン指定(`NUM_VSVERSION`)を判断する。
1. `ARG_VSVERSION` 未指定の場合、`15`が指定されたものとみなす。
1. `ARG_VSVERSION` が`2017`の場合、`15`が指定されたものとみなす。
1. `ARG_VSVERSION` が`2019`の場合、`16`が指定されたものとみなす。
1. `ARG_VSVERSION` が`latest`の場合、最新バージョンを取得する。
1. `ARG_VSVERSION` が上記以外の場合、`%ARG_VSVERSION%`が指定されたものとみなす。
1. 指定されたバージョンのVC++がインストールされているかチェックする。
1. `vswhere -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath -version [%NUM_VSVERSION%, %NUM_VSVERSION% + 1)` を実行する。
1. 取得したパスが存在していたら、バージョン指定(`NUM_VSVERSION`)は正しいとみなす。
1. 取得したパスが存在していなかったら、最新バージョンを取得する。
1. インストール済み`VC++`の最新バージョンを取得する。
1. `vswhere -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationVersion -latest` を実行する。
1. 取得したバージョンが指定されたものとみなす。(`NUM_VSVERSION`に代入する。)
1. 指定されたバージョンの`MsBuild.exe`を検索する。
1. `-find`オプションを付けて`MsBuild.exe`を検索する。(`vswhere -requires Microsoft.Component.MSBuild -find MSBuild\**\Bin\MSBuild.exe -version [%NUM_VSVERSION%, %NUM_VSVERSION% + 1)`)
1. `vswhere` が VS2019 以降ver の場合、`MSBuild.exe` が見つかるので検索終了。
1. `vswhere` が VS2017 以前ver の場合、`MSBuild.exe` が見つからない(エラーになる)ので検索続行。
1. VS2017 の `MsBuild.exe` を検索する。
1. VS2017 のインストールパスを検索する。(`vswhere -requires Microsoft.Component.MSBuild -property installationPath -version [15^,16^)`)
1. VS2017 のインストールパス配下の所定位置(`%Vs2017InstallRoot%\MSBuild\15.0\Bin`)に`MSBuild.exe`が存在する場合、そのパスを `MSBuild.exe` のパスとみなす。
この場合、バージョン指定(`NUM_VSVERSION`)に`15`が指定されたものとみなす。
1. バッチファイルの引数をチェックする。
1. 引数が指定されていない場合、`NUM_VSVERSION`が定義されていればその値を、そうでなければ`latest`を指定したものとみなす。
2. 引数にプロダクトバージョン(例:`2019`)が指定されている場合は値をメジャーバージョンに変換する。
`latest`を指定した場合は、実行環境にインストールされている最新のメジャーバージョンを取得する。
3. 指定したバージョンがインストールされているか確認し、見つからなければ引数の指定はなかったものとみなしてチェックをやり直す。
4. `NUM_VSVERSION`が指定されている場合に限り、設定されている値とここまでのチェックで見つかったバージョンが同じであるか確認する。
もし異なっている場合は環境変数を初期化した上で引数チェックをやり直す。
2. 引数チェックで決定したバージョンの MSBuild を探す。
- Visual Studio 2017 が選択された場合
- VS2017 のインストールパスを取得し、配下の所定位置に`MSBuild.exe`が存在する場合、そのパスを`MSBuild`のパスとして利用する。
- CMakeのジェネレータ名を示す`CMAKE_G_PARAM`に`Visual Studio 15 2017`を設定する。
- Visual Studio 2019 以降が選択された場合
- Visual Studio Locator の`-find`オプションを利用して`MSBuild.exe`を検索し、見つかったパスを`MSBuild`のパスとして利用する。
- `NUM_VSVERSION`と別途取得したプロダクトバージョンからCMakeのジェネレータ名を生成し、`CMAKE_G_PARAM`に設定する。

### 参照
* https://github.com/Microsoft/vswhere
Expand Down