Search code examples
c++windowsboostcmakevisual-studio-2019

Unable to change compiler version FindBoost.cmake searches for in Boost, causing linker errors with VS2019 and VS2022


I am experiencing an issue with changing the compiler version that FindBoost.cmake is searching for when working with Boost. By default, it searches for the vc140 toolset, but I am trying to use the vc142 or vc143 toolsets with both Visual Studio 2019 and Visual Studio 2022.

This is my CMakeList.txt where I try to set the correct hints for findboost. The _boost_COMPILER remains vc140 no matter what I do.

set(BOOST_ROOT "D:/Bladesense/boost_1_82_0")

set(Boost_DEBUG ON)
set(Boost_COMPILER "-vc143")
set(BOOST_COMPILER  "-vc143")
set(_boost_COMPILER "-vc143")
message(STATUS "BOOST_COMPILER ${BOOST_COMPILER}")
message(STATUS "MSVC_TOOLSET_VERSION ${MSVC_TOOLSET_VERSION}")

find_package(Boost 1.82 REQUIRED COMPONENTS serialization filesystem system) 

This is the FindBoost debug output (relevant _boost_COMPILER on the last line):

[CMake] -- MSVC_TOOLSET_VERSION 142
1> [CMake] -- [ :1658 ] _boost_TEST_VERSIONS = <unset>
1> [CMake] -- [ :1659 ] Boost_USE_MULTITHREADED = "ON"
1> [CMake] -- [ :1660 ] Boost_USE_STATIC_LIBS = "OFF"
1> [CMake] -- [ :1661 ] Boost_USE_STATIC_RUNTIME = <unset>
1> [CMake] -- [ :1662 ] Boost_ADDITIONAL_VERSIONS = <unset>
1> [CMake] -- [ :1663 ] Boost_NO_SYSTEM_PATHS = <unset>
1> [CMake] -- [ :1695 ] BOOST_ROOT = "D:/Bladesense/boost_1_82_0"
1> [CMake] -- [ :1696 ] ENV{BOOST_ROOT} = <unset>
1> [CMake] -- [ :1697 ] BOOST_INCLUDEDIR = <unset>
1> [CMake] -- [ :1698 ] ENV{BOOST_INCLUDEDIR} = <unset>
1> [CMake] -- [ :1699 ] BOOST_LIBRARYDIR = <unset>
1> [CMake] -- [ :1700 ] ENV{BOOST_LIBRARYDIR} = <unset>
1> [CMake] -- [ :1772 ] _boost_INCLUDE_SEARCH_DIRS = "D:/Bladesense/boost_1_82_0/include;D:/Bladesense/boost_1_82_0;PATHS;C:/boost/include;C:/boost;/sw/local/include"
1> [CMake] -- [ :1773 ] _boost_PATH_SUFFIXES = <unset>
1> [CMake] -- [ :1788 ] location of version.hpp: D:/Bladesense/boost_1_82_0/boost/version.hpp
1> [CMake] -- [ :1828 ] Boost_VERSION = "108200"
1> [CMake] -- [ :1829 ] Boost_VERSION_STRING = "1.82.0"
1> [CMake] -- [ :1830 ] Boost_VERSION_MACRO = "108200"
1> [CMake] -- [ :1831 ] Boost_VERSION_MAJOR = "1"
1> [CMake] -- [ :1832 ] Boost_VERSION_MINOR = "82"
1> [CMake] -- [ :1833 ] Boost_VERSION_PATCH = "0"
1> [CMake] -- [ :1834 ] Boost_VERSION_COUNT = "3"
1> [CMake] -- [ :1858 ] Boost_LIB_PREFIX = ""
1> [CMake] -- [ :1859 ] Boost_NAMESPACE = "boost"
1> [CMake] -- [ :1881 ] _boost_COMPILER = "-vc140" (user-specified via Boost_COMPILER)

I don't understand why _boost_COMPILER is still -vc140 here. When I install boost which was compiled with the vc140 toolset the CmakeCache.txt is generated correctly:

//Build shared libraries (DLLs).
BUILD_SHARED_LIBS:BOOL=OFF

//Boost filesystem library (debug)
Boost_FILESYSTEM_LIBRARY_DEBUG:FILEPATH=D:/Bladesense/boost_1_82_0/lib64-msvc-14.0/boost_filesystem-vc140-mt-gd-x64-1_82.lib

//Boost filesystem library (release)
Boost_FILESYSTEM_LIBRARY_RELEASE:FILEPATH=D:/Bladesense/boost_1_82_0/lib64-msvc-14.0/boost_filesystem-vc140-mt-x64-1_82.lib

//Path to a file.
Boost_INCLUDE_DIR:PATH=D:/Bladesense/boost_1_82_0

//Boost library directory DEBUG
Boost_LIBRARY_DIR_DEBUG:PATH=D:/Bladesense/boost_1_82_0/lib64-msvc-14.0

//Boost library directory RELEASE
Boost_LIBRARY_DIR_RELEASE:PATH=D:/Bladesense/boost_1_82_0/lib64-msvc-14.0

//Boost serialization library (debug)
Boost_SERIALIZATION_LIBRARY_DEBUG:FILEPATH=D:/Bladesense/boost_1_82_0/lib64-msvc-14.0/boost_serialization-vc140-mt-gd-x64-1_82.lib

//Boost serialization library (release)
Boost_SERIALIZATION_LIBRARY_RELEASE:FILEPATH=D:/Bladesense/boost_1_82_0/lib64-msvc-14.0/boost_serialization-vc140-mt-x64-1_82.lib

//Boost system library (debug)
Boost_SYSTEM_LIBRARY_DEBUG:FILEPATH=D:/Bladesense/boost_1_82_0/lib64-msvc-14.0/boost_system-vc140-mt-gd-x64-1_82.lib

//Boost system library (release)
Boost_SYSTEM_LIBRARY_RELEASE:FILEPATH=D:/Bladesense/boost_1_82_0/lib64-msvc-14.0/boost_system-vc140-mt-x64-1_82.lib

However, then I get a linker error during the build.

[37/181] cmd.exe /C "cd . && D:\VS\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin\cmake.exe -E vs_link_exe --intdir=CMakeFiles\bin2c.dir --rc=C:\PROGRA~2\WI3CF2~1\10\bin\100190~1.0\x64\rc.exe --mt=C:\PROGRA~2\WI3CF2~1\10\bin\100190~1.0\x64\mt.exe --manifests  -- D:\VS\VC\Tools\MSVC\14.29.30133\bin\Hostx64\x64\link.exe /nologo CMakeFiles\bin2c.dir\bin2c_autogen\mocs_compilation.cpp.obj CMakeFiles\bin2c.dir\libvis\src\bin2c\main.cc.obj  /out:bin2c.exe /implib:bin2c.lib /pdb:bin2c.pdb /version:0.0 /machine:x64 /debug /INCREMENTAL /subsystem:console  D:\Bladesense\boost_1_82_0\lib64-msvc-14.0\boost_serialization-vc140-mt-gd-x64-1_82.lib  D:\Bladesense\boost_1_82_0\lib64-msvc-14.0\boost_filesystem-vc140-mt-gd-x64-1_82.lib  D:\Bladesense\boost_1_82_0\lib64-msvc-14.0\boost_system-vc140-mt-gd-x64-1_82.lib  kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib && cmd.exe /C "cd /D D:\Bladesense\badslam\out\build\x64-Debug && C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -noprofile -executionpolicy Bypass -file D:/Bladesense/vcpkg/scripts/buildsystems/msbuild/applocal.ps1 -targetBinary D:/Bladesense/badslam/out/build/x64-Debug/bin2c.exe -installedDir D:/Bladesense/vcpkg/installed/x64-windows/debug/bin -OutVariable out""
  FAILED: bin2c.exe 
  cmd.exe /C "cd . && D:\VS\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin\cmake.exe -E vs_link_exe --intdir=CMakeFiles\bin2c.dir --rc=C:\PROGRA~2\WI3CF2~1\10\bin\100190~1.0\x64\rc.exe --mt=C:\PROGRA~2\WI3CF2~1\10\bin\100190~1.0\x64\mt.exe --manifests  -- D:\VS\VC\Tools\MSVC\14.29.30133\bin\Hostx64\x64\link.exe /nologo CMakeFiles\bin2c.dir\bin2c_autogen\mocs_compilation.cpp.obj CMakeFiles\bin2c.dir\libvis\src\bin2c\main.cc.obj  /out:bin2c.exe /implib:bin2c.lib /pdb:bin2c.pdb /version:0.0 /machine:x64 /debug /INCREMENTAL /subsystem:console  D:\Bladesense\boost_1_82_0\lib64-msvc-14.0\boost_serialization-vc140-mt-gd-x64-1_82.lib  D:\Bladesense\boost_1_82_0\lib64-msvc-14.0\boost_filesystem-vc140-mt-gd-x64-1_82.lib  D:\Bladesense\boost_1_82_0\lib64-msvc-14.0\boost_system-vc140-mt-gd-x64-1_82.lib  kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib && cmd.exe /C "cd /D D:\Bladesense\badslam\out\build\x64-Debug && C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -noprofile -executionpolicy Bypass -file D:/Bladesense/vcpkg/scripts/buildsystems/msbuild/applocal.ps1 -targetBinary D:/Bladesense/badslam/out/build/x64-Debug/bin2c.exe -installedDir D:/Bladesense/vcpkg/installed/x64-windows/debug/bin -OutVariable out""
  LINK Pass 1: command "D:\VS\VC\Tools\MSVC\14.29.30133\bin\Hostx64\x64\link.exe /nologo CMakeFiles\bin2c.dir\bin2c_autogen\mocs_compilation.cpp.obj CMakeFiles\bin2c.dir\libvis\src\bin2c\main.cc.obj /out:bin2c.exe /implib:bin2c.lib /pdb:bin2c.pdb /version:0.0 /machine:x64 /debug /INCREMENTAL /subsystem:console D:\Bladesense\boost_1_82_0\lib64-msvc-14.0\boost_serialization-vc140-mt-gd-x64-1_82.lib D:\Bladesense\boost_1_82_0\lib64-msvc-14.0\boost_filesystem-vc140-mt-gd-x64-1_82.lib D:\Bladesense\boost_1_82_0\lib64-msvc-14.0\boost_system-vc140-mt-gd-x64-1_82.lib kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib /MANIFEST /MANIFESTFILE:CMakeFiles\bin2c.dir/intermediate.manifest CMakeFiles\bin2c.dir/manifest.res" failed (exit code 1104) with the following output:
D:\Bladesense\badslam\LINK : fatal error LNK1104: cannot open file 'libboost_filesystem-vc142-mt-gd-x64-1_82.lib'

I don't understand why it tries to link against libboost_filesystem-vc142-mt-gd-x64-1_82.lib. libboost_filesystem-vc140-mt-gd-x64-1_82.lib is present in the directory and is pointed to in the CMakeCache.txt. It is coincidental that vc142 corresponds to my current msvc toolset version. When I use boost version 1.69 or lower I get the same linker error with libboost_filesystem-vc141-mt-gd-x64-1_69.lib.

The problem persists across Boost versions 1.55, 1.69, and 1.82, using both self-compiled and precompiled libraries.

As a workaround for this issue, I tried to use vcpkg which works. However, I need version 1.55 of boost which is not available in vcpkg.


Solution

  • The behaviour experienced here is apparently still a result of the vcpkg integration, even when installing a non-vcpkg version of Boost. This is because vcpkg has a special case for Boost that overwrites any user-defined Boost_COMPILER settings when using find_package and the vcpkg integration. The following links provide more information:

    Issue discussion on vcpkg GitHub

    Relevant code in vcpkg.cmake

    In my particular situation, I still require vcpkg for other libraries, so I came up with a less-than-ideal workaround. Since I can't modify the compiler version enforced by vcpkg, I created a copy of the DLLs (compiled with the correct vc toolchain) and renamed them to match the version vcpkg is erroneously looking for. Surprisingly, the linking process will still use the correct DLL versions, allowing my program to build successfully. This workaround is not recommended and should be used with caution.