FindBoost: needs special massage to achieve success build with static libs on Windows
Piece of code is:
set(Boost_USE_MULTITHREADED ON) set(Boost_USE_STATIC_LIBS ON) #set(Boost_USE_STATIC_RUNTIME OFF) # default, not explicitly set if (NOT TARGET Boost::context) find_package(Boost 1.61.0 REQUIRED COMPONENTS context) endif()
That works perfectly on *nix, freebsd and mac with default-installed boost (i.e. one built from sources and
./b2 install). Checked with 1.71, 1.72..76. Everywhere it automatically located boost-provided cmake config and correctly selects desired library.
On Windows this very config doesn't work. It seems that here it uses 'module' instead of boost-provided cmake, and that is because non-regular structure of the 'default' (not self-brew) installation available on boost.org.
With the same configuration code following things happens:
libboost_context-vc142-mt-gd-x64-1_75.libfor debug and
libboost_context-vc142-mt-x64-1_75.libfor release, and that is correct.
Build tries to use one of this libs (depends from configuration), but fails with error of impossible to open file
libboost_context-vc142-mt-sgd-x64-1_75.libfor debug, or
Last two libs present in the boost and is selected by configuration if also
Boost_USE_STATIC_RUNTIME is set to
ON. As obvious runaround setting that flag in original config solves the problem, but that implies that on other platforms boost should also be built with that flag. Or - that on windows it need special conditional clause to set the flag on that platform.
However that is just runaround and NOT the solution.
Digging deeper I've realized that these libraries came from deep of boost itself via linker's #pragma in source code, and that is may be disabled by provide
BOOST_ALL_NO_LIB. If it is defined - only libraries required by build system is used and build success. If it is NOT set - also compile-time injects works and that crashes the build.
So, the solution I've used first time is conditional statement after boost is found:
if (WIN32) set_property(TARGET Boost::context PROPERTY INTERFACE_COMPILE_DEFINITIONS "BOOST_ALL_NO_LIB" ) endif()
That works, but generally not so good as implies I know about internals of the problem (name of this very flag), and also it is not good as I modify already imported target. Another solution is unconditional:
set_property(TARGET Boost::context PROPERTY INTERFACE_LINK_LIBRARIES "Boost::disable_autolinking")
That looks shorter, but the same way - modifies imported target, and also links with non-existing library (as on config-mode boost there is no such target, even imported).
Both solutions looks like esoteric tricks, however they solves the problem. It would be good, however, if build would success without such strange massaging.
Boost::disable_autolinking, otherwise wrong libraries will be used.
CMake-provided boost solves the problem having INTERFACE_COMPILE_DEFINITIONS property set to "BOOST_ALL_NO_LIB" out-of-the box.
For modular it would be good either copy that solution, either provide dependency from
disable_autolinking out of the box. Without such fixture build is not success.