Hi, what you're describing is the technique what I coined the term "dual mode support" for in my presentations. I've added it to {fmt} in 2021 to enable the use of the library as both #include and import; MS-STL adopted it for their implementation of the standard library Please take into account that I usually also add something along xxx_ATTACH_TO_GLOBAL_MODULE (in this case xxx = BOOST) to avoid potential ODR violations for projects that use a library either as module or through headers. Otherwise users may end up with conflicting, but apparently *identical* definitions that they cannot decipher the reason for: one definition is attached to the named module, the other to the global module. The compiler will be very upset. Linkers usually work. Boost libraries that intend to support modules *must* also *add* tests that check that the exported entities are * available on the consumer side * instantiation and name lookup works when called from the consumer side Module implementation units have two relevant interfaces, not one. Almost all libraries that claim module capability support, and that I've seen so far, fail to do that. In rare cases I have forks that add this missing piece. Lacking those gives users horrible experiences and modules a bad reputation. On the standard library: *all* C++ implementers of the standard library have agreed to support C++20 modules also for C++20 build modes. So you're not tied to C++23. And lastly, there is BMI compatibility and the story of compiler flags matching. But that's for a different day. Dani Am 06.07.2024 um 14:20 schrieb Antony Polukhin via Boost:
Hi,
C++20 modules seem to be a good tool to improve compile times and to hide the implementation details of the libraries.
I've been looking throught the sources of {fmt} library. Looks like the fmt library approach to C++20 modularization seems to fit Boost quite well.
How about adding the following macro to Boost: * BOOST_BEGIN_MODULE_EXPORT - starts the scope of things to export if Boost is build as a C++20 module * BOOST_END_MODULE_EXPORT - ends the scope of things to export if Boost is build as a C++20 module * BOOST_MODULE_EXPORT - for a single entity export if Boost is build as a C++20 module
As a result, if Boost is build as a module the above macros are defined in the following way:
#define BOOST_MODULE_EXPORT export #define BOOST_BEGIN_MODULE_EXPORT export { #define BOOST_END_MODULE_EXPORT }
Helper macro BOOST_NO_CXX23_IMPORT_STD for detecting availability of `import std` also seems useful.
Macro BOOST_NO_CXX20_MODULES - for notifying the libraries that compiler does not support modules or Boost modules are not compiled.
With all the above macros the Boost libraries could look like:
/// header
#include
#ifdef BOOST_NO_CXX20_MODULES #include
#else import Boost.LibraryThatSupportsModules; #endif #ifdef BOOST_NO_CXX23_IMPORT_STD #include <iostream> #else import std; #endif
namespace boost { namespace detail { template <class T> bool try_do(const T&); }
BOOST_BEGIN_MODULE_EXPORT
template
bool try_lexiacal_convert(const From& f, T& to) { /*impl*/ } template
T lexiacal_cast(const From& f) { /*impl*/ } BOOST_END_MODULE_EXPORT }
/// module src file
export module Boost.MyLibraryName;
#ifdef BOOST_NO_CXX20_MODULES #error ??? #endif
#include
-- PGP/GPG: 2CCB 3ECB 0954 5CD3 B0DB 6AA0 BA03 56A1 2C4638C5