boost v1.85.0までのバージョンをVisual Studio 2022でビルドできない不具合について

2024年7月にboostv1.85.0のwindows版インストールをしようとして詰まりました。
最近Visual Studio 2022をインストールしてboost v1.85.0もしくはv1.85.0より前のバージョンをビルドしようとしている方はぜひご一読ください。

# 対象バージョン
- Visual Studio 2022のv17.10.xとこれより新しいバージョン<br>VS2022を新規インストールした場合であり、v17.10.xやこれ以降のバージョンにアップデートした場合は問題ない。
- boost v1.85.0とこれより前のバージョン(=b2がv5.1.0かそれより前のバージョンである)

# 経緯
C++環境を構築するために、以下の手順でVisual Studio 2022とboost v1.85.0のインストールを試みた。
1. 公式からダウンロードしたzipファイルを解凍
2. 解凍したフォルダをCドライブ直下へ配置(C:\boost_1_85_0)
3. 「x64 Native Tools Command Prompt for VS 2022」を起動し、以下のコマンドを順番に実行
```bat
$ cd C:\boost_1_85_0

$ bootstrap.bat

$ .\b2
```
手順3は、下記の公式ページに書いてあった手順である。
今回はVisual C++を用いているため、リンク内の「5.1 Simplified Build From Source」を参照した。
https://www.boost.org/doc/libs/1_85_0/more/getting_started/windows.html#simplified-build-from-source

## 発生した問題
手順3を実施したが、ライブラリらしきファイルがどこにも出来ていない。
stageフォルダにはcmakeファイルが存在しており、かつ、
上記公式ページの5.2.1章に記載がある中間フォルダ(`./bin.b2/`)は存在しているが、成果物らしきファイルは見当たらない状態。

このときのコンソールログをページの最後に貼り付けておく。

boostのビルドを行うのが初めてだったため、この状態が成功なのか失敗なのか判断ができなかったが、
以下の2点を根拠に何らかの原因でコマンド実行中に落ちてる(クラッシュしている)と推定した。
 - コンソールに`Build Success/Failed`などと出力されず、コマンドがいきなり終了している
 - ビルドに時間がかかると聞いていたが、コマンド叩いてから1分かからずに終了している

# 原因
最近(2024年6月から7月まで)の情報に絞って検索をかけたところ、
日本語で書かれた同様の事象についての情報を運良く見つけた。
事象と解決方法について、こちらのページに分かりやすく書かれている。

http://local.comvic.mydns.jp/%E9%96%8B%E7%99%BA%E8%80%85%E3%81%AE%E7%8B%AC%E3%82%8A%E8%A8%80/

このページによると、`bin.v2\config.log`を見ればヒントがあったようだ。

b2 v1.5.0までのMSVCについてのjamファイルの実装の問題で、ビルドツールセットを14.3までしか検知出来ないようになっていることが原因で
Visual Studioがv17.10.~になったとき、MSVCのバージョンがv14.4系にインクリメントしたため発生した不具合のようである。

そして、Githubにもissueが立っていた。
こちらも非常に参考になった。

https://github.com/boostorg/boost/issues/914

このページ内に、

>This issue does not happen if one updates the Visual Studio version from e.g. 17.8 to 17.10.It happens if Visual Studio 17.10 is the only Visual Studio version which has been installed on the system.

と書かれているように、Visual Studio 2022 v17.10.xを新規にインストールした場合にこの事象は発生する。
Visual Studio 2022を以前のバージョンからアップデートした場合は、ローカルにMSVC14.4より前のバージョンのMSVCが入っているため、
この事象は発生しない。

また、冒頭で主張したように、この事象は一時的に発生しているだけではないことに注意が必要である。
**Visual Studio 2022 v17.10.xおよびこれ以降のバージョンを新規インストールして、boost v1.85.0とこれより前のバージョンをビルドしたすべての場合でこの事象が発生する**と考えられる。
よって、今後同様の事象で困る人が増加するのではないだろうか。

# 解決状況について
この事象の発端であるb2は、v5.2.0のリリースで既に修正されている。
次のboostv1.86.xで、このb2 v5.2.0が取り込まれることが予想されますが
boostの最新は現時点でv1.85.xであるため、暫定対処が必要である。


## 暫定対処法
この事象を避けてv1.85.0をビルドする方法は以下3通り考えられる。
### Visual Studio以外のコンパイラを使用する
この場合、上で紹介した手順とは実行するバッチファイルの場所が異なるため注意する。
手順は、[手順のセクションでも紹介した公式ページ](https://www.boost.org/doc/libs/1_85_0/more/getting_started/windows.html#or-build-binaries-from-source)の「5.2 Or, Build Binaries From Source」を参照する。


### Visual Studio 2022をダウングレードする
V17.10.xとこれより先のバージョンを避けて、これらより前のバージョンにすれば良い。
### 原因となっているmsvc.jamを直接修正する
くれぐれも自己責任で実施していただくことになるが、boostフォルダ内の`tools\build\src\tools\msvc.jam`を自分で修正してビルドを行うことも可能である。
修正方法は下記2つのページを真似しました。

http://local.comvic.mydns.jp/%E9%96%8B%E7%99%BA%E8%80%85%E3%81%AE%E7%8B%AC%E3%82%8A%E8%A8%80/

上記サイトから引用

>“tools\build\src\tools\msvc.jam”の内容をチェックすると、#1140でcl.exeのversionをチェックしている。(略)“14.3”を”14.4″に書き換えることで正常にビルドできるようになった。

https://github.com/bfgroup/b2/pull/394/files

上記サイトも参考になる。

私は以下のように修正した。
```diff:tools\build\src\tools\msvc.jam$L1140
-            if [ MATCH "(14.3)" : $(version) ]
+            if [ MATCH "(14.4)" : $(version) ]
```

# その他
- b2実行時のコンソールログ抜粋
```bat
C:\boost_1_85_0>.\b2
Performing configuration checks

    - default address-model    : none [1]
    - default architecture     : none [1]

Building the Boost C++ Libraries.


    - x86                      : no [2]
    - arm                      : no [2]
    - mips1                    : no [2]
    - power                    : no [2]
    - sparc                    : no [2]
    - cxx11_static_assert      : no [2]
    - x86                      : no [3]
    - arm                      : no [3]
    - mips1                    : no [3]
    - power                    : no [3]
    - sparc                    : no [3]
    - cxx11_static_assert      : no [3]
    - cxx11_variadic_templates : no [2]
    - cxx11_variadic_templates : no [3]
    - cxx11_hdr_ratio          : no [2]
    - cxx11_hdr_ratio          : no [3]
    - cxx20_hdr_concepts       : no [2]
    - cxx20_hdr_concepts       : no [3]
error: No best alternative for libs/context/build/asm_sources with <abi>ms <address-model>32 <asynch-exceptions>off <binary-format>pe <boost.cobalt.executor>any_io_executor <boost.cobalt.pmr>std <context-impl>fcontext <coverage>off <debug-store>object <debug-symbols>on <embed-manifest-via>linker <embed-manifest>on <exception-handling>on <extern-c-nothrow>off <inlining>off <link>static <midl-robust>yes <midl-stubless-proxy>yes <optimization>off <os>NT <pch>on <preserve-test-targets>on <profiling>off <python-debugging>off <relevant>abi <relevant>address-model <relevant>architecture <relevant>binary-format <relevant>toolset <rtti>on <runtime-debugging>on <runtime-link>shared <stdlib>native <strip>off <target-os>windows <testing.execute>on <threadapi>win32 <threading>multi <toolset-msvc:version>14.3 <toolset>msvc <variant>debug <vectorize>off <visibility>hidden <warnings-as-errors>off <warnings>on <windows-api>desktop
    no match: <abi>aapcs <address-model>32 <architecture>arm <binary-format>elf <threading>multi <toolset>clang
    no match: <abi>aapcs <address-model>32 <architecture>arm <binary-format>elf <threading>multi <toolset>gcc
    no match: <abi>aapcs <address-model>32 <architecture>arm <binary-format>elf <threading>multi <toolset>qcc
    no match: <abi>aapcs <address-model>32 <architecture>arm <binary-format>mach-o <threading>multi <toolset>clang
    no match: <abi>aapcs <address-model>32 <architecture>arm <binary-format>mach-o <threading>multi <toolset>darwin
    no match: <abi>aapcs <address-model>32 <architecture>arm <binary-format>pe <threading>multi <toolset>msvc
    no match: <abi>aapcs <address-model>64 <architecture>arm <binary-format>elf <threading>multi <toolset>clang
    no match: <abi>aapcs <address-model>64 <architecture>arm <binary-format>elf <threading>multi <toolset>gcc
    no match: <abi>aapcs <address-model>64 <architecture>arm <binary-format>mach-o <threading>multi <toolset>clang
    no match: <abi>aapcs <address-model>64 <architecture>arm <binary-format>mach-o <threading>multi <toolset>darwin
    no match: <abi>aapcs <address-model>64 <architecture>arm <binary-format>mach-o <threading>multi <toolset>gcc
    no match: <abi>aapcs <address-model>64 <architecture>arm <binary-format>pe <threading>multi <toolset>msvc
    no match: <abi>sysv <address-model>64 <architecture>loongarch <binary-format>elf <threading>multi <toolset>gcc
    no match: <abi>o32 <address-model>32 <architecture>mips <binary-format>elf <threading>multi <toolset>clang
    no match: <abi>o32 <address-model>32 <architecture>mips <binary-format>elf <threading>multi <toolset>gcc
    no match: <abi>n64 <address-model>64 <architecture>mips <binary-format>elf <threading>multi <toolset>clang
    no match: <abi>n64 <address-model>64 <architecture>mips <binary-format>elf <threading>multi <toolset>gcc
    no match: <abi>sysv <address-model>32 <architecture>power <binary-format>elf <threading>multi <toolset>clang
    no match: <abi>sysv <address-model>32 <architecture>power <binary-format>elf <threading>multi <toolset>gcc
    no match: <abi>sysv <address-model>32 <architecture>power <binary-format>mach-o <threading>multi <toolset>clang
    no match: <abi>sysv <address-model>32 <architecture>power <binary-format>mach-o <threading>multi <toolset>gcc
    no match: <abi>sysv <address-model>32 <architecture>power <binary-format>mach-o <threading>multi <toolset>darwin
    no match: <abi>sysv <address-model>32 <architecture>power <binary-format>xcoff <threading>multi <toolset>clang
    no match: <abi>sysv <address-model>32 <architecture>power <binary-format>xcoff <threading>multi <toolset>gcc
    no match: <abi>sysv <address-model>64 <architecture>power <binary-format>elf <threading>multi <toolset>clang
    no match: <abi>sysv <address-model>64 <architecture>power <binary-format>elf <threading>multi <toolset>gcc
    no match: <abi>sysv <address-model>64 <architecture>power <binary-format>mach-o <threading>multi <toolset>clang
    no match: <abi>sysv <address-model>64 <architecture>power <binary-format>mach-o <threading>multi <toolset>gcc
    no match: <abi>sysv <address-model>64 <architecture>power <binary-format>mach-o <threading>multi <toolset>darwin
    no match: <abi>sysv <address-model>64 <architecture>power <binary-format>xcoff <threading>multi <toolset>clang
    no match: <abi>sysv <address-model>64 <architecture>power <binary-format>xcoff <threading>multi <toolset>gcc
    no match: <abi>sysv <address-model>32_64 <architecture>power <binary-format>mach-o <threading>multi
    no match: <abi>sysv <address-model>64 <architecture>riscv <binary-format>elf <threading>multi <toolset>clang
    no match: <abi>sysv <address-model>64 <architecture>riscv <binary-format>elf <threading>multi <toolset>gcc
    no match: <abi>sysv <address-model>64 <architecture>sparc <binary-format>elf <threading>multi <toolset>clang
    no match: <abi>sysv <address-model>64 <architecture>sparc <binary-format>elf <threading>multi <toolset>gcc
    no match: <abi>sysv <address-model>64 <architecture>s390x <binary-format>elf <threading>multi <toolset>gcc
    no match: <abi>sysv <address-model>64 <architecture>s390x <binary-format>elf <threading>multi <toolset>clang
    no match: <abi>sysv <address-model>32 <architecture>x86 <binary-format>elf <threading>multi <toolset>clang
    no match: <abi>sysv <address-model>32 <architecture>x86 <binary-format>elf <threading>multi <toolset>gcc
    no match: <abi>sysv <address-model>32 <architecture>x86 <binary-format>elf <threading>multi <toolset>intel
    no match: <abi>sysv <address-model>32 <architecture>x86 <binary-format>mach-o <threading>multi <toolset>clang
    no match: <abi>sysv <address-model>32 <architecture>x86 <binary-format>mach-o <threading>multi <toolset>darwin
    no match: <abi>ms <address-model>32 <architecture>x86 <binary-format>pe <threading>multi <toolset>clang
    no match: <abi>ms <address-model>32 <architecture>x86 <binary-format>pe <threading>multi <toolset>clang-win
    no match: <abi>ms <address-model>32 <architecture>x86 <binary-format>pe <threading>multi <toolset>gcc
    no match: <abi>ms <address-model>32 <architecture>x86 <binary-format>pe <threading>multi <toolset>intel
    no match: <abi>ms <address-model>32 <architecture>x86 <binary-format>pe <threading>multi <toolset>msvc
    no match: <abi>ms <address-model>32 <architecture>x86 <binary-format>pe <threading>multi <toolset>embarcadero
    no match: <abi>ms <address-model>32 <architecture>x86 <binary-format>pe <threading>multi <toolset>borland
    no match: <abi>sysv <address-model>64 <architecture>x86 <binary-format>elf <threading>multi <toolset>clang
    no match: <abi>sysv <address-model>64 <architecture>x86 <binary-format>elf <threading>multi <toolset>gcc
    no match: <abi>sysv <address-model>64 <architecture>x86 <binary-format>elf <threading>multi <toolset>intel
    no match: <abi>sysv <address-model>64 <architecture>x86 <binary-format>mach-o <threading>multi <toolset>clang
    no match: <abi>sysv <address-model>64 <architecture>x86 <binary-format>mach-o <threading>multi <toolset>gcc
    no match: <abi>sysv <address-model>64 <architecture>x86 <binary-format>mach-o <threading>multi <toolset>darwin
    no match: <abi>sysv <address-model>64 <architecture>x86 <binary-format>mach-o <threading>multi <toolset>intel
    no match: <abi>ms <address-model>64 <architecture>x86 <binary-format>pe <threading>multi <toolset>clang
    no match: <abi>ms <address-model>64 <architecture>x86 <binary-format>pe <threading>multi <toolset>clang-win
    no match: <abi>ms <address-model>64 <architecture>x86 <binary-format>pe <threading>multi <toolset>gcc
    no match: <abi>ms <address-model>64 <architecture>x86 <binary-format>pe <threading>multi <toolset>intel
    no match: <abi>ms <address-model>64 <architecture>x86 <binary-format>pe <threading>multi <toolset>msvc

～省略～

...skipped <pbin.v2\libs\container\build\msvc-14.3\debug\address-model-32\link-static\threading-multi>libboost_container-vc143-mt-gd-1_85.lib for lack of <pbin.v2\libs\container\build\msvc-14.3\debug\address-model-32\link-static\threading-multi>alloc_lib.obj...
...skipped <pC:\boost_1_85_0\stage\lib>libboost_container-vc143-mt-gd-1_85.lib for lack of <pbin.v2\libs\container\build\msvc-14.3\debug\address-model-32\link-static\threading-multi>libboost_container-vc143-mt-gd-1_85.lib...
...skipped <pbin.v2\libs\container\build\msvc-14.3\debug\address-model-32\link-static\threading-multi>libboost_container-variant-vc143-mt-gd-1_85-static.cmake for lack of <pbin.v2\libs\container\build\msvc-14.3\debug\address-model-32\link-static\threading-multi>libboost_container-vc143-mt-gd-1_85.lib...
...skipped <pC:\boost_1_85_0\stage\lib\cmake\boost_container-1.85.0>libboost_container-variant-vc143-mt-gd-1_85-static.cmake for lack of <pbin.v2\libs\container\build\msvc-14.3\debug\address-model-32\link-static\threading-multi>libboost_container-variant-vc143-mt-gd-1_85-static.cmake...
common.copy C:\boost_1_85_0\stage\lib\cmake\Boost-1.85.0\BoostConfigVersion.cmake
bin.v2\tools\boost_install\BoostConfigVersion.cmake
        1 file(s) copied.
common.copy C:\boost_1_85_0\stage\lib\cmake\boost_container-1.85.0\boost_container-config.cmake
bin.v2\libs\container\build\stage\boost_container-config.cmake
        1 file(s) copied.
common.copy C:\boost_1_85_0\stage\lib\cmake\boost_container-1.85.0\boost_container-config-version.cmake
bin.v2\libs\container\build\stage\boost_container-config-version.cmake
        1 file(s) copied.
boost-install.generate-cmake-config- bin.v2\libs\headers\build\stage\boost_headers-config.cmake
boost-install.generate-cmake-config-version- bin.v2\libs\headers\build\stage\boost_headers-config-version.cmake
common.copy C:\boost_1_85_0\stage\lib\cmake\boost_headers-1.85.0\boost_headers-config.cmake
bin.v2\libs\headers\build\stage\boost_headers-config.cmake
        1 file(s) copied.
common.copy C:\boost_1_85_0\stage\lib\cmake\boost_headers-1.85.0\boost_headers-config-version.cmake
bin.v2\libs\headers\build\stage\boost_headers-config-version.cmake
        1 file(s) copied.

...updated 365 targets...

...skipped 562 targets...
   <pC:\boost_1_85_0\stage\lib>libboost_container-vc143-mt-1_85.lib
   <pC:\boost_1_85_0\stage\lib>libboost_container-vc143-mt-gd-1_85.lib
   <pC:\boost_1_85_0\stage\lib>libboost_context-vc143-mt-1_85.lib

～省略～

   <pbin.v2\libs\timer\build\msvc-14.3\release\address-model-32\link-static\threading-multi>auto_timers_construction.obj
   <pbin.v2\libs\timer\build\msvc-14.3\release\address-model-32\link-static\threading-multi>cpu_timer.obj
   <pbin.v2\libs\timer\build\msvc-14.3\release\address-model-32\link-static\threading-multi>libboost_timer-variant-vc143-mt-1_85-static.cmake
   <pbin.v2\libs\timer\build\msvc-14.3\release\address-model-32\link-static\threading-multi>libboost_timer-vc143-mt-1_85.lib
   <pbin.v2\libs\timer\build\msvc-14.3\release\address-model-64\link-static\threading-multi>auto_timers_construction.obj
   <pbin.v2\libs\timer\build\msvc-14.3\release\address-model-64\link-static\threading-multi>cpu_timer.obj
   <pbin.v2\libs\timer\build\msvc-14.3\release\address-model-64\link-static\threading-multi>libboost_timer-variant-vc143-mt-1_85-static.cmake
   <pbin.v2\libs\timer\build\msvc-14.3\release\address-model-64\link-static\threading-multi>libboost_timer-vc143-mt-1_85.lib


```

ここまででコマンド実行が終了していた。