
On Sun, 22 Dec 2024 at 12:02, John Maddock via Boost
Following this approach, dependencies are automatic. But this has a number of downsides: 1. At the moment, BMIs are built with the settings used to build Boost in the first place, which causes a lot of trouble. 2. The installation generates many more binaries than in the headers world. It is uncertain whether these binaries will be compatible if build flags change. 3. Some libraries support configuration macros. For instance, Boost::throw_exception supports BOOST_NO_EXCEPTIONS. This is used by other Boost libraries to support builds that disable exceptions. In the current world, the end user defines BOOST_NO_EXCEPTIONS in their code, includes the library, and everything works. Using a scheme like the one I suggested requires the user to build all the Boost modules using BOOST_NO_EXCEPTIONS, which is more involved than what we have today.
Yup, my feeling is that this puts us back where we were before auto-linking with msvc - which is to say with a huge number of hard to diagnose bug reports from folks with some obscure binary incompatibility.
OK, maybe not that huge yet, given modules niche usage, but hopefully growing over time.
I think this is a completely valid concern. Once I have a minimal prototype working, I will try to investigate how much of a problem this is.
At the risk of going off at a tangent, I would also suggest a "core" boost module containing all the commonly used small libraries - the lesson from the std module appears to be that bigger is better, at least up to some point.
For now, I'm doing a single module per library, because it maps much easier to the current CMake infrastructure. Given the current state of modules, I don't want to waste too much time.
For this reason, it makes sense to consider whether there is a way to completely avoid the generation and installation of these binaries for header-only libraries, and follow a model similar to standard modules. In this ideal model, installing Boost with CMake would only install the headers and module code for each header-only library, and no binary artifacts. The consuming project would build both the BMIs and the objects containing the module initializers with the adequate build flags, as many times as required by the different targets.
Ideally, the following syntax would work and do what I'm suggesting:
# This does NOT work as of today add_library(boost_variant2 INTERFACE) # Don't build the library in the current project target_sources(boost_variant2 INTERFACE FILE_SET CXX_MODULES FILES modules/variant2.cxx) target_include_directories(boost_variant2 INTERFACE include) target_link_libraries(boost_variant2 INTERFACE Boost::assert Boost::config Boost::mp11 )
Having CMake do it all for us would be great, thinking out loud here, is there a way to publish a CMake code fragment that users could cut-and-paste into their own CMake file? Still not ideal I know...
I've had the same thoughts, too. Best I can think of is a CMake function. For instance: # In the user's CMakeLists.txt # This means "I want to build the Boost.Variant2 module and its dependencies. # Create a target called my_variant2_module boost_add_cxx20_module(variant2 TARGET_NAME my_variant2_module ) # Now use the module add_executable(main main.cpp) target_link_libraries(main PRIVATE my_variant2_module) There are at least 2 unsolved problems here: 1) How does the user specify build options for the module? That is, how do they specify that they want C++23, a certain visibility, and BOOST_DISABLE_EXCEPTIONS? This is a problem because options must be specified not only to the my_variant2_module, but to all the dependent Boost modules (e.g. Boost::assert and Boost::mp11, in this case). 2) How does this work for compiled libraries? A possibility I can think for 1) is making boost_add_cxx20_module accept a CMake interface target with the user options. All targets created by boost_add_cxx20_module would be linked to this target: # An interface target to specify that we want BOOST_DISABLE_EXCEPTIONS add_library(my_options_lib INTERFACE) target_compile_definitions(my_options_lib INTERFACE BOOST_DISABLE_EXCEPTIONS) # Create the Boost modules, defining BOOST_DISABLE_EXCEPTIONS boost_add_cxx20_module(variant2 TARGET_NAME my_variant2_module LINK_TO my_options_lib ) I'm pretty sure this approach has problems I'm not seeing right now. I'm reluctant to this kind of ad-hoc approach - it'd be best if CMake did it. I haven't thought about 2) yet.
And finally... if anyone wants to experiment/road test a module with source, then Regex in develop is all module friendly now (but has no module build files).
If I have the time, I will include it in the prototype, although I promise nothing yet. I'm trying to get some of the foundational libraries (assert, throw_exception, config, core and mp11) and their tests building for both compilers before anything else.
Thanks for this! Best, John.
Thanks, Ruben.