Skip to content

Modules: Add C++20 modules component#4999

Merged
matejk merged 20 commits intopocoproject:mainfrom
mikomikotaishi:main
Sep 19, 2025
Merged

Modules: Add C++20 modules component#4999
matejk merged 20 commits intopocoproject:mainfrom
mikomikotaishi:main

Conversation

@mikomikotaishi
Copy link
Copy Markdown
Contributor

@mikomikotaishi mikomikotaishi commented Aug 17, 2025

This pull request adds support for C++20 modules, which aggregate all header files. Modules must be built after the rest of the library is built, and modules match the namespace name (Poco.* matches Poco::*), and also has a single module Poco for importing all modules. It is enabled using ENABLE_MODULES. A CI test has also been added to test compiling the module. I am sure many users of C++20 and future would be interested in using the Poco libraries as a module, so this library hopefully satisfies this.

This exports all documented classes in https://docs.pocoproject.org/, and also the libraries Poco::PDF and Poco::SevenZip. Modules also match the activated ENABLE_* options configured in CMakeLists.txt.

@aleks-f aleks-f requested a review from matejk August 18, 2025 00:19
@aleks-f aleks-f self-requested a review August 18, 2025 00:19
Copy link
Copy Markdown
Member

@aleks-f aleks-f left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There should be some test and CI to verify it actually works

@matejk matejk added this to the Release 1.15.0 milestone Aug 18, 2025
@matejk
Copy link
Copy Markdown
Contributor

matejk commented Aug 18, 2025

Just checked: *Impl classes must be exported unconditionally.

@mikomikotaishi

@andrewauclair
Copy link
Copy Markdown
Contributor

Awesome. I tried this several times myself over the last few years. I actually found some ICEs in GCC trying to make Poco modules, which I believe are fixed in GCC 15.

@mikomikotaishi
Copy link
Copy Markdown
Contributor Author

The only problem I am having now is determining which header inclusions need to be determined by platform. Modules should add all symbols, but because some symbols are platform-specific there must be conditional compilation over the operating system. Is there a list of what classes and what headers are platform specific?

@matejk
Copy link
Copy Markdown
Contributor

matejk commented Aug 18, 2025

The only problem I am having now is determining which header inclusions need to be determined by platform. Modules should add all symbols, but because some symbols are platform-specific there must be conditional compilation over the operating system. Is there a list of what classes and what headers are platform specific?

Headers without a suffix are generic for all platforms. Platform-specific headers have suffixes like _WIN32, _WIN32U, _POSIX. See also cmake/PocoMacros.cmake.

Macros are used to prepare a list of headers during build process. Perhaps they could be reused to prepare modules and generate cppm files during build?

@mikomikotaishi
Copy link
Copy Markdown
Contributor Author

I also wonder if there are single-include headers to include entire sections of the Poco library? I initially thought that was what some like Poco/Foundation.h would do but it turns out those just contain macros.

@matejk
Copy link
Copy Markdown
Contributor

matejk commented Aug 18, 2025

I also wonder if there are single-include headers to include entire sections of the Poco library? I initially thought that was what some like Poco/Foundation.h would do but it turns out those just contain macros.

There are no such headers.

@mikomikotaishi
Copy link
Copy Markdown
Contributor Author

There are no such headers.

Then I guess the modules will solve this problem for those who can use them

@mikomikotaishi
Copy link
Copy Markdown
Contributor Author

There should be some test and CI to verify it actually works

I have no experience writing CI tests but I tried writing one, hopefully it is sufficient to test building the modules

@mikomikotaishi
Copy link
Copy Markdown
Contributor Author

OK, I have made my best attempt to address all the comments and suggestions made to this PR. Please let me know what else can be fixed before this can be merged.

@mikomikotaishi mikomikotaishi requested a review from aleks-f August 19, 2025 04:30
@matejk
Copy link
Copy Markdown
Contributor

matejk commented Aug 19, 2025

OK, I have made my best attempt to address all the comments and suggestions made to this PR. Please let me know what else can be fixed before this can be merged.

I will take some time to build and use it on different platforms however I can't promise that it will happen this week.

@andrewauclair
Copy link
Copy Markdown
Contributor

In my opinion the modules should not be enabled by default, even with C++20 enabled. The user should have to explicitly enable them for now. I've done some research and can't find any evidence of a good/direct way to detect whether the current compiler and generator support C++ modules. This appears to be why so many of the CI steps are failing right now. C++20 is enabled, modules are enabled by default, and the Unix Makefiles generator is used.

@mikomikotaishi
Copy link
Copy Markdown
Contributor Author

I agree with that, while modules are a standard feature of the language compilers still have unreliable support for them, and mostly bleeding-edge codebases are using them right now rather than widespread adoption replacing headers. To my understanding only GCC 14+, Clang 17+, and MSVC 2022 version 17.6+ support modules, and module support is dependent on build system too. I will make it opt-in for now, Makefiles with CMake do not support modules which is what the CI tests use

@mikomikotaishi
Copy link
Copy Markdown
Contributor Author

I apologise for the silence/inactivity on this pull request, I have been busy with some other obligations. I will continue progress on this task soon.

@matejk
Copy link
Copy Markdown
Contributor

matejk commented Sep 10, 2025

No problem. There is no deadline.

@mikomikotaishi
Copy link
Copy Markdown
Contributor Author

I added the samples as requested which tests basic functionality with importing.

@mikomikotaishi
Copy link
Copy Markdown
Contributor Author

@matejk Sorry about the delays. I tried to get some work on this task the other day, let me know at your own availability if there are any other concerns to address. I just test sample files and tested one or two classes (DateTime and URI), since the objective is just to test that importing as a module works. I ended up having to write another macro for installing/exporting as well, which hopefully that's okay

@matejk
Copy link
Copy Markdown
Contributor

matejk commented Sep 17, 2025

Thank you very much for your effort.

I tried this on Ubuntu 25.04, clang++ 20. Everything compiles and installs fine.

I noticed in the installed file lib/cmake/Poco/PocoModulesTargets.cmake that local paths to my git clone are included for some reason.

See IMPORTED_CXX_MODULES_INCLUDE_DIRECTORIES below:


# Compute the installation prefix relative to this file.
get_filename_component(_IMPORT_PREFIX "${CMAKE_CURRENT_LIST_FILE}" PATH)
get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH)
get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH)
get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH)
if(_IMPORT_PREFIX STREQUAL "/")
  set(_IMPORT_PREFIX "")
endif()

# Create imported target Poco::Modules
add_library(Poco::Modules SHARED IMPORTED)

set_target_properties(Poco::Modules PROPERTIES
  CXX_MODULE_STD ""
  IMPORTED_CXX_MODULES_COMPILE_DEFINITIONS "ENABLE_FOUNDATION;ENABLE_ENCODINGS;ENABLE_ACTIVERECORD;ENABLE_CRYPTO;ENABLE_DATA;ENABLE_DATA_MYSQL;ENABLE_DATA_ODBC;ENABLE_DATA_POSTGRESQL;ENABLE_DATA_SQLITE;ENABLE_JSON;ENABLE_JWT;ENABLE_MONGODB;ENABLE_NET;ENABLE_PROMETHEUS;ENABLE_REDIS;ENABLE_UTIL;ENABLE_XML;ENABLE_ZIP;POCO_DLL;POCO_CMAKE"
  IMPORTED_CXX_MODULES_COMPILE_FEATURES "cxx_std_20"
  IMPORTED_CXX_MODULES_INCLUDE_DIRECTORIES "${_IMPORT_PREFIX}/include;/Users/matejk/git/github/poco/include;/Users/matejk/git/github/poco/modules/src;${_IMPORT_PREFIX}/include"
  IMPORTED_CXX_MODULES_LINK_LIBRARIES "Poco::Foundation;Poco::Encodings;Poco::ActiveRecord;Poco::Crypto;Poco::Data;Poco::DataMySQL;Poco::DataODBC;Poco::DataPostgreSQL;Poco::DataSQLite;Poco::JSON;Poco::JWT;Poco::MongoDB;Poco::Net;Poco::Prometheus;Poco::Redis;Poco::Util;Poco::XML;Poco::Zip"
  INTERFACE_COMPILE_DEFINITIONS "ENABLE_FOUNDATION;ENABLE_ENCODINGS;ENABLE_ACTIVERECORD;ENABLE_CRYPTO;ENABLE_DATA;ENABLE_DATA_MYSQL;ENABLE_DATA_ODBC;ENABLE_DATA_POSTGRESQL;ENABLE_DATA_SQLITE;ENABLE_JSON;ENABLE_JWT;ENABLE_MONGODB;ENABLE_NET;ENABLE_PROMETHEUS;ENABLE_REDIS;ENABLE_UTIL;ENABLE_XML;ENABLE_ZIP"
  INTERFACE_COMPILE_FEATURES "cxx_std_20"
  INTERFACE_INCLUDE_DIRECTORIES "${_IMPORT_PREFIX}/include;${_IMPORT_PREFIX}/include"
  INTERFACE_LINK_LIBRARIES "Poco::Foundation;Poco::Encodings;Poco::ActiveRecord;Poco::Crypto;Poco::Data;Poco::DataMySQL;Poco::DataODBC;Poco::DataPostgreSQL;Poco::DataSQLite;Poco::JSON;Poco::JWT;Poco::MongoDB;Poco::Net;Poco::Prometheus;Poco::Redis;Poco::Util;Poco::XML;Poco::Zip"
)

I was not able to find out where these come from. Can you investigate this?

@matejk
Copy link
Copy Markdown
Contributor

matejk commented Sep 17, 2025

I managed to merge cmake install macros into one.

You can merge the changes from this branch: https://github.com/pocoproject/poco/tree/4999-cpp-modules

@mikomikotaishi
Copy link
Copy Markdown
Contributor Author

I managed to merge cmake install macros into one.

You can merge the changes from this branch: https://github.com/pocoproject/poco/tree/4999-cpp-modules

Thanks!

@mikomikotaishi
Copy link
Copy Markdown
Contributor Author

Thank you very much for your effort.

I tried this on Ubuntu 25.04, clang++ 20. Everything compiles and installs fine.

I noticed in the installed file lib/cmake/Poco/PocoModulesTargets.cmake that local paths to my git clone are included for some reason.

See IMPORTED_CXX_MODULES_INCLUDE_DIRECTORIES below:


# Compute the installation prefix relative to this file.
get_filename_component(_IMPORT_PREFIX "${CMAKE_CURRENT_LIST_FILE}" PATH)
get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH)
get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH)
get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH)
if(_IMPORT_PREFIX STREQUAL "/")
  set(_IMPORT_PREFIX "")
endif()

# Create imported target Poco::Modules
add_library(Poco::Modules SHARED IMPORTED)

set_target_properties(Poco::Modules PROPERTIES
  CXX_MODULE_STD ""
  IMPORTED_CXX_MODULES_COMPILE_DEFINITIONS "ENABLE_FOUNDATION;ENABLE_ENCODINGS;ENABLE_ACTIVERECORD;ENABLE_CRYPTO;ENABLE_DATA;ENABLE_DATA_MYSQL;ENABLE_DATA_ODBC;ENABLE_DATA_POSTGRESQL;ENABLE_DATA_SQLITE;ENABLE_JSON;ENABLE_JWT;ENABLE_MONGODB;ENABLE_NET;ENABLE_PROMETHEUS;ENABLE_REDIS;ENABLE_UTIL;ENABLE_XML;ENABLE_ZIP;POCO_DLL;POCO_CMAKE"
  IMPORTED_CXX_MODULES_COMPILE_FEATURES "cxx_std_20"
  IMPORTED_CXX_MODULES_INCLUDE_DIRECTORIES "${_IMPORT_PREFIX}/include;/Users/matejk/git/github/poco/include;/Users/matejk/git/github/poco/modules/src;${_IMPORT_PREFIX}/include"
  IMPORTED_CXX_MODULES_LINK_LIBRARIES "Poco::Foundation;Poco::Encodings;Poco::ActiveRecord;Poco::Crypto;Poco::Data;Poco::DataMySQL;Poco::DataODBC;Poco::DataPostgreSQL;Poco::DataSQLite;Poco::JSON;Poco::JWT;Poco::MongoDB;Poco::Net;Poco::Prometheus;Poco::Redis;Poco::Util;Poco::XML;Poco::Zip"
  INTERFACE_COMPILE_DEFINITIONS "ENABLE_FOUNDATION;ENABLE_ENCODINGS;ENABLE_ACTIVERECORD;ENABLE_CRYPTO;ENABLE_DATA;ENABLE_DATA_MYSQL;ENABLE_DATA_ODBC;ENABLE_DATA_POSTGRESQL;ENABLE_DATA_SQLITE;ENABLE_JSON;ENABLE_JWT;ENABLE_MONGODB;ENABLE_NET;ENABLE_PROMETHEUS;ENABLE_REDIS;ENABLE_UTIL;ENABLE_XML;ENABLE_ZIP"
  INTERFACE_COMPILE_FEATURES "cxx_std_20"
  INTERFACE_INCLUDE_DIRECTORIES "${_IMPORT_PREFIX}/include;${_IMPORT_PREFIX}/include"
  INTERFACE_LINK_LIBRARIES "Poco::Foundation;Poco::Encodings;Poco::ActiveRecord;Poco::Crypto;Poco::Data;Poco::DataMySQL;Poco::DataODBC;Poco::DataPostgreSQL;Poco::DataSQLite;Poco::JSON;Poco::JWT;Poco::MongoDB;Poco::Net;Poco::Prometheus;Poco::Redis;Poco::Util;Poco::XML;Poco::Zip"
)

I was not able to find out where these come from. Can you investigate this?

I'm a little confused, should that file not be included? Is this an extraneous file to the compilation process that is not needed?

@matejk
Copy link
Copy Markdown
Contributor

matejk commented Sep 17, 2025

set_target_properties(Poco::Modules PROPERTIES
CXX_MODULE_STD ""
IMPORTED_CXX_MODULES_COMPILE_DEFINITIONS "ENABLE_FOUNDATION;ENABLE_ENCODINGS;ENABLE_ACTIVERECORD;ENABLE_CRYPTO;ENABLE_DATA;ENABLE_DATA_MYSQL;ENABLE_DATA_ODBC;ENABLE_DATA_POSTGRESQL;ENABLE_DATA_SQLITE;ENABLE_JSON;ENABLE_JWT;ENABLE_MONGODB;ENABLE_NET;ENABLE_PROMETHEUS;ENABLE_REDIS;ENABLE_UTIL;ENABLE_XML;ENABLE_ZIP;POCO_DLL;POCO_CMAKE"
IMPORTED_CXX_MODULES_COMPILE_FEATURES "cxx_std_20"
IMPORTED_CXX_MODULES_INCLUDE_DIRECTORIES "${_IMPORT_PREFIX}/include;/Users/matejk/git/github/poco/include;/Users/matejk/git/github/poco/modules/src;${_IMPORT_PREFIX}/include"
IMPORTED_CXX_MODULES_LINK_LIBRARIES "Poco::Foundation;Poco::Encodings;Poco::ActiveRecord;Poco::Crypto;Poco::Data;Poco::DataMySQL;Poco::DataODBC;Poco::DataPostgreSQL;Poco::DataSQLite;Poco::JSON;Poco::JWT;Poco::MongoDB;Poco::Net;Poco::Prometheus;Poco::Redis;Poco::Util;Poco::XML;Poco::Zip"
INTERFACE_COMPILE_DEFINITIONS "ENABLE_FOUNDATION;ENABLE_ENCODINGS;ENABLE_ACTIVERECORD;ENABLE_CRYPTO;ENABLE_DATA;ENABLE_DATA_MYSQL;ENABLE_DATA_ODBC;ENABLE_DATA_POSTGRESQL;ENABLE_DATA_SQLITE;ENABLE_JSON;ENABLE_JWT;ENABLE_MONGODB;ENABLE_NET;ENABLE_PROMETHEUS;ENABLE_REDIS;ENABLE_UTIL;ENABLE_XML;ENABLE_ZIP"
INTERFACE_COMPILE_FEATURES "cxx_std_20"
INTERFACE_INCLUDE_DIRECTORIES "${_IMPORT_PREFIX}/include;${_IMPORT_PREFIX}/include"
INTERFACE_LINK_LIBRARIES "Poco::Foundation;Poco::Encodings;Poco::ActiveRecord;Poco::Crypto;Poco::Data;Poco::DataMySQL;Poco::DataODBC;Poco::DataPostgreSQL;Poco::DataSQLite;Poco::JSON;Poco::JWT;Poco::MongoDB;Poco::Net;Poco::Prometheus;Poco::Redis;Poco::Util;Poco::XML;Poco::Zip"
)

After running cmake --install the following paths shall not be present in the exported cmake files:

/Users/matejk/git/github/poco/include;/Users/matejk/git/github/poco/modules/src;

When you install on your computer, cmake file probably contains paths to your source directory, however that is not OK. Only directories that are inside the installation directory shall be referenced.

@mikomikotaishi
Copy link
Copy Markdown
Contributor Author

I think this should address the problem with the installation-relative paths.

@mikomikotaishi
Copy link
Copy Markdown
Contributor Author

Seeing as the tests (are probably going to) pass, is this everything in line to merging the PR?

@mikomikotaishi
Copy link
Copy Markdown
Contributor Author

Anything else before we can merge this?

@matejk matejk merged commit 041e7fe into pocoproject:main Sep 19, 2025
36 checks passed
@mikomikotaishi
Copy link
Copy Markdown
Contributor Author

We did it! 🎉

@matejk
Copy link
Copy Markdown
Contributor

matejk commented Sep 19, 2025

We did it! 🎉

Yes, we did! Thank you again for your cooperation.

@matejk matejk added feature development buildsystem cmake Related to cmake build system labels Oct 15, 2025
@matejk matejk changed the title Add support for modules Modules: Add C++20 modules component Dec 20, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants