Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
84536c9
Add optional C++20 module interface (import boost.program_options)
soroshsabz Oct 21, 2026
f061e24
Move the module interface to modules/boost_program_options.cppm
soroshsabz Oct 21, 2026
6c34fd3
Add modules/usage_sample.cpp and document the wrapper design
soroshsabz Oct 21, 2026
e41ab9a
Switch module interface to the export-block style (like Boost.Any/PFR)
soroshsabz Oct 22, 2026
fcddfd7
Document why the module interface does not use import std yet
soroshsabz Oct 22, 2026
198475e
Fix export block scoping in detail/value_semantic.hpp; keep typeindex…
soroshsabz Oct 22, 2026
a593506
Build the module with module implementation units; support import std
soroshsabz Oct 22, 2026
940fe21
Expand the typeindex re-export comment for the implementation-unit de…
soroshsabz Oct 22, 2026
ca72d03
Restore the thin wrapper interface; keep all changes under src/
soroshsabz Oct 22, 2026
2043e04
Make the existing src/*.cpp double as module implementation units
soroshsabz Oct 22, 2026
7eef6c8
Minimize the module-unit preludes in src/*.cpp to what each file uses
soroshsabz Oct 22, 2026
89962fa
Follow the boostorg/config#535 compatibility-header pattern for std i…
soroshsabz Oct 23, 2026
2d8cb55
Add std-header compatibility guards per boostorg/config#535; wire BOO…
soroshsabz Oct 23, 2026
85128c2
Move the module interface to the root-level modules/ directory
soroshsabz Oct 23, 2026
8eb1568
Remove duplicated includes between the module preludes and the classi…
soroshsabz Oct 23, 2026
9578881
Remove the duplicated module prelude; keep the original includes with…
soroshsabz Oct 23, 2026
1577395
Restore convert.cpp's original include order
soroshsabz Oct 23, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
113 changes: 113 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -612,3 +612,116 @@ jobs:
run: |
cd ../boost-root/__build__
ctest --output-on-failure --no-tests=error -C Release

posix-cmake-modules:
strategy:
fail-fast: false
matrix:
include:
- name: "gcc-15"
packages: "g++-15 ninja-build"
cmake-args: "-DCMAKE_CXX_COMPILER=g++-15"
- name: "clang-21"
packages: "clang-21 ninja-build"
cmake-args: "-DCMAKE_CXX_COMPILER=clang++-21"

name: CMake modules ${{ matrix.name }}

runs-on: ubuntu-latest
container: ubuntu:26.04

defaults:
run:
shell: bash

steps:
- name: Setup container environment
run: |
apt-get update
apt-get -y install sudo python3 git g++ cmake

- name: Install packages
run: |
sudo apt-get update
sudo apt-get -y install ${{matrix.packages}}

- uses: actions/checkout@v6

- name: Setup Boost
run: |
echo GITHUB_REPOSITORY: $GITHUB_REPOSITORY
LIBRARY=${GITHUB_REPOSITORY#*/}
echo LIBRARY: $LIBRARY
echo "LIBRARY=$LIBRARY" >> $GITHUB_ENV
echo GITHUB_BASE_REF: $GITHUB_BASE_REF
echo GITHUB_REF: $GITHUB_REF
REF=${GITHUB_BASE_REF:-$GITHUB_REF}
REF=${REF#refs/heads/}
echo REF: $REF
BOOST_BRANCH=develop && [ "$REF" == "master" ] && BOOST_BRANCH=master || true
echo BOOST_BRANCH: $BOOST_BRANCH
cd ..
git clone -b $BOOST_BRANCH --depth 1 https://github.com/boostorg/boost.git boost-root
cd boost-root
cp -r $GITHUB_WORKSPACE/* libs/$LIBRARY
git submodule update --init tools/boostdep
python3 tools/boostdep/depinst/depinst.py --git_args "--jobs 3" $LIBRARY

- name: Configure
run: |
cd ../boost-root
mkdir __build__ && cd __build__
cmake -DBOOST_INCLUDE_LIBRARIES=$LIBRARY -DBUILD_TESTING=ON -DBOOST_PROGRAM_OPTIONS_BUILD_MODULES=ON -DCMAKE_CXX_STANDARD=20 ${{matrix.cmake-args}} -G Ninja ..

- name: Build and run module test
run: |
cd ../boost-root/__build__
cmake --build . --target program_options_module_test
ctest --output-on-failure --no-tests=error -R program_options_module_test

windows-cmake-modules:
runs-on: windows-latest

steps:
- uses: actions/checkout@v6

- name: Setup Boost
shell: cmd
run: |
echo GITHUB_REPOSITORY: %GITHUB_REPOSITORY%
for /f %%i in ("%GITHUB_REPOSITORY%") do set LIBRARY=%%~nxi
echo LIBRARY: %LIBRARY%
echo LIBRARY=%LIBRARY%>>%GITHUB_ENV%
echo GITHUB_BASE_REF: %GITHUB_BASE_REF%
echo GITHUB_REF: %GITHUB_REF%
if "%GITHUB_BASE_REF%" == "" set GITHUB_BASE_REF=%GITHUB_REF%
set BOOST_BRANCH=develop
for /f %%i in ("%GITHUB_BASE_REF%") do if "%%~nxi" == "master" set BOOST_BRANCH=master
echo BOOST_BRANCH: %BOOST_BRANCH%
cd ..
git clone -b %BOOST_BRANCH% --depth 1 https://github.com/boostorg/boost.git boost-root
cd boost-root
xcopy /s /e /q %GITHUB_WORKSPACE% libs\%LIBRARY%\
git submodule update --init tools/boostdep
python tools/boostdep/depinst/depinst.py --git_args "--jobs 3" %LIBRARY%

- name: Configure
shell: cmd
run: |
cd ../boost-root
mkdir __build__ && cd __build__
cmake -DBOOST_INCLUDE_LIBRARIES=%LIBRARY% -DBUILD_TESTING=ON -DBOOST_PROGRAM_OPTIONS_BUILD_MODULES=ON -G "Visual Studio 17 2022" ..

- name: Build and run module test (Debug)
shell: cmd
run: |
cd ../boost-root/__build__
cmake --build . --config Debug --target program_options_module_test
ctest --output-on-failure --no-tests=error -C Debug -R program_options_module_test

- name: Build and run module test (Release)
shell: cmd
run: |
cd ../boost-root/__build__
cmake --build . --config Release --target program_options_module_test
ctest --output-on-failure --no-tests=error -C Release -R program_options_module_test
130 changes: 130 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,136 @@ else()
target_compile_definitions(boost_program_options PUBLIC BOOST_PROGRAM_OPTIONS_STATIC_LINK)
endif()

# C++20 module interface for the library ('import boost.program_options;').
# Entirely optional and off by default: the header-based interface is unchanged.

option(BOOST_PROGRAM_OPTIONS_BUILD_MODULES "Build the C++20 module interface (boost.program_options)" OFF)

# Modules mode of the boostorg/config PR #535 pattern ("Adds support for
# C++20 modules"): the standard-library compatibility guards in the headers
# and sources route their #include <...> directives to 'import std;'.
# Requires the module build above and a toolchain-provided std module.
# Note: full activation also needs the PR #535 ecosystem (modularized
# dependencies): under this flag, already-converted dependencies such as
# Boost.TypeIndex switch their headers to importing their own modules,
# which supersedes the textual preloads used here until then.
option(BOOST_USE_MODULES "Modules mode: consume the standard library through 'import std;' (boostorg/config#535 pattern)" OFF)

if(BOOST_USE_MODULES AND NOT BOOST_PROGRAM_OPTIONS_BUILD_MODULES)
set(BOOST_PROGRAM_OPTIONS_BUILD_MODULES ON)
endif()

if(BOOST_PROGRAM_OPTIONS_BUILD_MODULES)

if(CMAKE_GENERATOR MATCHES "Visual Studio")
if(CMAKE_VERSION VERSION_LESS 3.30)
message(FATAL_ERROR "boost_program_options_modules: the ${CMAKE_GENERATOR} generator requires CMake 3.30 or later for C++20 modules.")
endif()
elseif(CMAKE_VERSION VERSION_LESS 3.28)
message(FATAL_ERROR "boost_program_options_modules: building C++20 modules requires CMake 3.28 or later and a Ninja generator.")
endif()

# The module interface plus the library sources, compiled as module
# implementation units (BOOST_PROGRAM_OPTIONS_MODULE_UNIT in src/*.cpp):
# declarations in the module purview attach to the module, and their
# definitions must carry the same attachment (some compilers mangle
# module-attached functions differently), so they cannot be taken from
# the classic library. In classic builds the same sources compile
# unchanged.
add_library(boost_program_options_modules
src/cmdline.cpp
src/config_file.cpp
src/convert.cpp
src/options_description.cpp
src/parsers.cpp
src/positional_options.cpp
src/split.cpp
src/utf8_codecvt_facet.cpp
src/value_semantic.cpp
src/variables_map.cpp
src/winmain.cpp
)
add_library(Boost::program_options_modules ALIAS boost_program_options_modules)

target_sources(boost_program_options_modules
PUBLIC FILE_SET CXX_MODULES
BASE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/modules"
FILES modules/boost_program_options.cppm
)

target_compile_features(boost_program_options_modules PUBLIC cxx_std_20)

# Scan all sources of the target: the src/*.cpp module implementation
# units are recognized as such and compiled against the interface's BMI.
set_target_properties(boost_program_options_modules PROPERTIES CXX_SCAN_FOR_MODULES ON)

target_include_directories(boost_program_options_modules PRIVATE include)

target_compile_definitions(boost_program_options_modules
PUBLIC BOOST_PROGRAM_OPTIONS_NO_LIB
PRIVATE BOOST_PROGRAM_OPTIONS_SOURCE BOOST_PROGRAM_OPTIONS_MODULE_UNIT
)

# Same dependencies as the classic library.
target_link_libraries(boost_program_options_modules
PUBLIC
Boost::any
Boost::config
Boost::core
Boost::detail
Boost::function
Boost::iterator
Boost::lexical_cast
Boost::smart_ptr
Boost::throw_exception
Boost::type_traits
PRIVATE
Boost::bind
Boost::tokenizer
)

# Standard-library consumption of the module units.
#
# BOOST_USE_MODULES (the flag used by the compatibility guards, following
# boostorg/config PR #535) activates the modules mode: the guards replace
# the textual standard includes with 'import std;'. It requires the
# std module (CMake 3.30+, -DCMAKE_CXX_MODULE_STD=ON and a C++ standard
# listed in CMAKE_CXX_COMPILER_IMPORT_STD).
#
# Without it, the standard library is preloaded textually in the global
# module fragment of each module unit, and 'import std;' is additionally
# used when the toolchain provides it (like in other modularized Boost
# libraries).
if(BOOST_USE_MODULES)
if(NOT (CMAKE_CXX_MODULE_STD AND CMAKE_CXX_STANDARD IN_LIST CMAKE_CXX_COMPILER_IMPORT_STD))
message(FATAL_ERROR
"BOOST_USE_MODULES requires the C++ std module: use CMake 3.30+, set "
"-DCMAKE_CXX_MODULE_STD=ON, choose a -DCMAKE_CXX_STANDARD=... listed in "
"CMAKE_CXX_COMPILER_IMPORT_STD, and, where required by the CMake version, "
"set CMAKE_EXPERIMENTAL_CXX_IMPORT_STD.")
endif()
set_target_properties(boost_program_options_modules PROPERTIES CXX_MODULE_STD ON)
target_compile_definitions(boost_program_options_modules
PRIVATE BOOST_USE_MODULES
PUBLIC BOOST_PROGRAM_OPTIONS_USE_STD_MODULE)
message(STATUS "boost_program_options_modules: modules mode (BOOST_USE_MODULES), 'import std;'")
elseif(CMAKE_CXX_MODULE_STD AND CMAKE_CXX_STANDARD IN_LIST CMAKE_CXX_COMPILER_IMPORT_STD)
set_target_properties(boost_program_options_modules PROPERTIES CXX_MODULE_STD ON)
target_compile_definitions(boost_program_options_modules PUBLIC BOOST_PROGRAM_OPTIONS_USE_STD_MODULE)
message(STATUS "boost_program_options_modules: using 'import std;' (C++${CMAKE_CXX_STANDARD})")
else()
message(STATUS "boost_program_options_modules: using textual standard library preloads")
endif()

if(NOT BOOST_SKIP_INSTALL_RULES AND NOT CMAKE_SKIP_INSTALL_RULES)
# Install the module interface source next to the headers, so that it is
# available to build systems that do not produce BMIs from installed
# packages (e.g. MSBuild projects adding the .cppm/.ixx directly).
install(FILES modules/boost_program_options.cppm DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/boost")
endif()

endif()

if(BUILD_TESTING AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/test/CMakeLists.txt")

add_subdirectory(test)
Expand Down
70 changes: 61 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,57 @@ Distributed under the [Boost Software License, Version 1.0](http://www.boost.org

* C++11
* Requires Linking
* Optional C++20 module interface (`import boost.program_options;`)

### C++20 module support

The library ships an optional C++20 module interface, so that instead of

```cpp
#include <boost/program_options.hpp>
```

you can write

```cpp
import boost.program_options;
```

and keep using the `boost::program_options` namespace unchanged.

The interface (`modules/boost_program_options.cppm`) preloads the library's
dependencies in the global module fragment and includes the umbrella header
in the module purview inside an `export { ... }` block, so the public
declarations are exported without modifying any header. The library's
sources in `src/*.cpp` carry a `BOOST_PROGRAM_OPTIONS_MODULE_UNIT`
conditional that compiles them, in the module build, as module
implementation units providing matching module-attached definitions; in
classic builds the same files compile unchanged. (The header export-block
style of Boost.Any/Boost.PFR is not needed for this: no header carries
module machinery at all.)

The standard-header includes in the library's headers and sources are
wrapped in a compatibility guard following the pattern of
`<boost/config/std/...>` from [boostorg/config PR
#535](https://github.com/boostorg/config/pull/535) ("Adds support for
C++20 modules", not merged yet): plain `#include <...>` today, `import
std;` in the modules mode (`-DBOOST_USE_MODULES=ON`, which requires a
toolchain-provided std module). Once that PR is merged, the guards are
to be replaced with `<boost/config/std/...>` (TODO comments at each
guard).

The module is not built by default. Enable it by configuring CMake with
`-DBOOST_PROGRAM_OPTIONS_BUILD_MODULES=ON`, which creates the additional
`Boost::program_options_modules` target (it links the classic compiled
library automatically). Building the module requires CMake 3.28+ with the
Ninja generator (CMake 3.30+ with the Visual Studio generator) and a compiler
with C++20 modules support. The `test/module_test.cpp` test verifies that the
exported interface is complete and functional, without including any Boost
header.

Macros (e.g. `BOOST_PROGRAM_OPTIONS_VERSION`) are not exported by C++20
modules; include the classic headers where macros are needed. See
`doc/modules.xml` for details.

### Development

Expand All @@ -29,15 +80,16 @@ changes to re-align with the evolution of Boost C++ Libraries and C++.

### Directories

| Name | Purpose |
| --------- | ------------------------------ |
| `build` | build script for link library |
| `ci` | continuous integration scripts |
| `doc` | documentation |
| `example` | use case examples |
| `include` | headers |
| `src` | source code for link library |
| `test` | unit tests |
| Name | Purpose |
| --------- | -------------------------------- |
| `build` | build script for link library |
| `ci` | continuous integration scripts |
| `doc` | documentation |
| `example` | use case examples |
| `include` | headers |
| `modules` | C++20 module interface |
| `src` | source code for link library |
| `test` | unit tests |

### More information

Expand Down
Loading