Skip to content

Expose version module using C++20 modules #6761

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

kylehaokunwu
Copy link

Fixes #

Proposed Changes

  • Added hpx_core.ixx umbrella module interface exposing the version module
  • Integrated version module into HPX build system using target_sources(... FILE_SET ...)
  • Enabled C++20 modules conditionally via HPX_USE_MODULES
  • Added install rules for the new hpx_core_modules FILE_SET

Any background context you want to provide?

This is part of the ongoing GSoC project to expose HPX using C++20 modules. This PR exposes the version module as a starting point. Follow-up PRs will expose additional modules one at a time. HPX was successfully built with -DHPX_USE_MODULES=ON, and the version_api_test passed

Checklist

Not all points below apply to all pull requests.

  • I have added a new feature

@kylehaokunwu kylehaokunwu requested a review from hkaiser as a code owner August 3, 2025 03:09
@StellarBot
Copy link

Can one of the admins verify this patch?

Copy link
Member

@hkaiser hkaiser left a comment

Choose a reason for hiding this comment

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

Very nice! Could you please enable testing against using C++ modules as well? Will that require changes to. e.g. <hpx/modules/version.hpp>?

@kylehaokunwu
Copy link
Author

Very nice! Could you please enable testing against using C++ modules as well? Will that require changes to. e.g. <hpx/modules/version.hpp>?

I updated version_api.cpp to conditionally use import HPX.Core when HPX_WITH_CXX_MODULES is defined, and it builds and runs successfully. No additional changes are needed. Would you like me to include this change in the PR?

@hkaiser
Copy link
Member

hkaiser commented Aug 5, 2025

Very nice! Could you please enable testing against using C++ modules as well? Will that require changes to. e.g. <hpx/modules/version.hpp>?

I updated version_api.cpp to conditionally use import HPX.Core when HPX_WITH_CXX_MODULES is defined, and it builds and runs successfully. No additional changes are needed. Would you like me to include this change in the PR?

Well, yes! Just we have to do it in a way that the test has not to be touched. We may have to change the generated (HPX) modules files for this (e.g., <hpx/modules/version.hpp>, though (see: https://github.com/STEllAR-GROUP/hpx/blob/master/cmake/templates/global_module_header.hpp.in, generated here: https://github.com/STEllAR-GROUP/hpx/blob/master/cmake/HPX_AddModule.cmake#L135-L161)

@kylehaokunwu
Copy link
Author

https://github.com/STEllAR-GROUP/hpx/blob/master/cmake/templates/global_module_header.hpp.in

Very nice! Could you please enable testing against using C++ modules as well? Will that require changes to. e.g. <hpx/modules/version.hpp>?

I updated version_api.cpp to conditionally use import HPX.Core when HPX_WITH_CXX_MODULES is defined, and it builds and runs successfully. No additional changes are needed. Would you like me to include this change in the PR?

Well, yes! Just we have to do it in a way that the test has not to be touched. We may have to change the generated (HPX) modules files for this (e.g., <hpx/modules/version.hpp>, though (see: https://github.com/STEllAR-GROUP/hpx/blob/master/cmake/templates/global_module_header.hpp.in, generated here: https://github.com/STEllAR-GROUP/hpx/blob/master/cmake/HPX_AddModule.cmake#L135-L161)

Just to confirm — would it be appropriate to add the following to global_module_header.hpp.in?

#pragma once

#if defined(HPX_WITH_CXX_MODULES)
import HPX.Core;
#else
#include <hpx/version.hpp>
#endif

Then update version_api.cpp to include:
#include <hpx/global_module.hpp>

@hkaiser
Copy link
Member

hkaiser commented Aug 7, 2025

Just to confirm — would it be appropriate to add the following to global_module_header.hpp.in?

#pragma once

#if defined(HPX_WITH_CXX_MODULES)
import HPX.Core;
#else
#include <hpx/version.hpp>
#endif

Then update version_api.cpp to include: #include <hpx/global_module.hpp>

Yes and no. This is how it should look like for the version module (except for the #if defined(HPX_WITH_CXX_MODULES), which should be #if defined(HPX_HAVE_CXX_MODULES)). But this template file is used to generate the module headers for all modules.

So we probably need to add a if()/else()/endif() to the file cmake/HPX_AddModule.cmake that switches between different template files (one as is and one that supports C++ modules) that is controlled by a new GLOBAL_HEADER_MODULE_GEN. As we adapt HPX modules this has to be added to those we touch. We can remove this again once we're done.

This should go here: https://github.com/kylehaokunwu/hpx/blob/expose/version-module/cmake/HPX_AddModule.cmake#L157-L160, here: https://github.com/kylehaokunwu/hpx/blob/expose/version-module/libs/core/version/CMakeLists.txt#L35 (and obviously here: https://github.com/kylehaokunwu/hpx/blob/expose/version-module/cmake/HPX_AddModule.cmake#L13 and here: https://github.com/kylehaokunwu/hpx/blob/expose/version-module/.cmake-format.py#L359).

I hope this makes sense.

kylehaokunwu pushed a commit to kylehaokunwu/hpx that referenced this pull request Aug 9, 2025
@kylehaokunwu kylehaokunwu force-pushed the expose/version-module branch from 648d7b5 to d705337 Compare August 9, 2025 04:33
Copy link

Coverage summary from Codacy

See diff coverage on Codacy

Coverage variation Diff coverage
Report missing for c4028b91
Coverage variation details
Coverable lines Covered lines Coverage
Common ancestor commit (c4028b9) Report Missing Report Missing Report Missing
Head commit (d705337) 59585 0 0.00%

Coverage variation is the difference between the coverage for the head and common ancestor commits of the pull request branch: <coverage of head commit> - <coverage of common ancestor commit>

Diff coverage details
Coverable lines Covered lines Diff coverage
Pull request (#6761) 0 0 ∅ (not applicable)

Diff coverage is the percentage of lines that are covered by tests out of the coverable lines that the pull request added or modified: <covered lines added or modified>/<coverable lines added or modified> * 100%

See your quality gate settings    Change summary preferences

Footnotes

  1. Codacy didn't receive coverage data for the commit, or there was an error processing the received data. Check your integration for errors and validate that your coverage setup is correct.

Copy link
Member

@hkaiser hkaiser left a comment

Choose a reason for hiding this comment

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

@kylehaokunwu Excellent work!

@@ -17,6 +17,10 @@

cmake_minimum_required(VERSION 3.18 FATAL_ERROR)

if(HPX_WITH_CXX_MODULES)
cmake_minimum_required(VERSION 3.29...3.29.99 FATAL_ERROR)
Copy link
Member

Choose a reason for hiding this comment

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

Shouldn't it work with newer versions (than 3.29) as well?

Suggested change
cmake_minimum_required(VERSION 3.29...3.29.99 FATAL_ERROR)
if (NOT (CMAKE_VERSION VERSION_GREATER_EQUAL "3.29"))
hpx_fatal("Please use a version of CMake newer than V3.28 in order to enable C++ module support for HPX")
endif()

Copy link
Author

Choose a reason for hiding this comment

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

Thanks for the catch! I will switch from the fixed range to a VERSION_GREATER_EQUAL 3.29 check. I will keep it inside if(HPX_WITH_CXX_MODULES) so non‑module builds still work with CMake ≥ 3.18.

Comment on lines +159 to +175
if(DEFINED ${modulename}_GLOBAL_HEADER_MODULE_GEN
AND ${modulename}_GLOBAL_HEADER_MODULE_GEN
)
set(global_header
"${CMAKE_CURRENT_BINARY_DIR}/include/hpx/global_module.hpp"
)
set(template_file
"${HPX_SOURCE_DIR}/cmake/templates/global_module_header_modules.hpp.in"
)
else()
set(global_header
"${CMAKE_CURRENT_BINARY_DIR}/include/hpx/modules/${modulename}.hpp"
)
set(template_file
"${PROJECT_SOURCE_DIR}/cmake/templates/global_module_header.hpp.in"
)
endif()
Copy link
Member

Choose a reason for hiding this comment

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

The name of the generated file should be the same in both cases:

Suggested change
if(DEFINED ${modulename}_GLOBAL_HEADER_MODULE_GEN
AND ${modulename}_GLOBAL_HEADER_MODULE_GEN
)
set(global_header
"${CMAKE_CURRENT_BINARY_DIR}/include/hpx/global_module.hpp"
)
set(template_file
"${HPX_SOURCE_DIR}/cmake/templates/global_module_header_modules.hpp.in"
)
else()
set(global_header
"${CMAKE_CURRENT_BINARY_DIR}/include/hpx/modules/${modulename}.hpp"
)
set(template_file
"${PROJECT_SOURCE_DIR}/cmake/templates/global_module_header.hpp.in"
)
endif()
set(global_header
"${CMAKE_CURRENT_BINARY_DIR}/include/hpx/modules/${modulename}.hpp"
)
if(${modulename}_GLOBAL_HEADER_MODULE_GEN)
set(template_file
"${HPX_SOURCE_DIR}/cmake/templates/global_module_header_modules.hpp.in"
)
else()
set(template_file
"${PROJECT_SOURCE_DIR}/cmake/templates/global_module_header.hpp.in"
)
endif()

#if defined(HPX_HAVE_CXX_MODULES)
import HPX.Core;
#else
#include <hpx/version.hpp>
Copy link
Member

Choose a reason for hiding this comment

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

For all HPX modules to be converted in the future, the generated module header should still include all necessary files as before:

Suggested change
#include <hpx/version.hpp>
@module_headers@

@@ -32,7 +32,8 @@ endif()
include(HPX_AddModule)
add_hpx_module(
core version
GLOBAL_HEADER_GEN OFF
GLOBAL_HEADER_GEN ON
GLOBAL_HEADER_MODULE_GEN TRUE
Copy link
Member

Choose a reason for hiding this comment

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

Just for consistency:

Suggested change
GLOBAL_HEADER_MODULE_GEN TRUE
GLOBAL_HEADER_MODULE_GEN ON


export module HPX.Core;

#include "version/include/hpx/version.hpp"
Copy link
Member

@hkaiser hkaiser Aug 9, 2025

Choose a reason for hiding this comment

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

Now that we're generating the module headers correctly, shouldn't we add them here (one by one as we adapt the HPX modules):

Suggested change
#include "version/include/hpx/version.hpp"
#include <hpx/modules/version.hpp>


// Define module-specific macros before including config
#define HPX_BUILD_MODULE
#include "config/include/hpx/config.hpp"
Copy link
Member

@hkaiser hkaiser Aug 9, 2025

Choose a reason for hiding this comment

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

I think this should be:

Suggested change
#include "config/include/hpx/config.hpp"
#include <hpx/config.hpp>

If you would like to minimize the #included content, this could be:

Suggested change
#include "config/include/hpx/config.hpp"
#include <hpx/config/defines.hpp>

which contains all the HPX_HAVE_XXX macro definitions.

if(HPX_WITH_CXX_MODULES)
hpx_info("HPX will build and install C++20 module interface units for downstream users.")
hpx_info("Note: HPX itself will still be built using traditional headers.")
add_compile_definitions(HPX_HAVE_CXX_MODULES)
Copy link
Member

Choose a reason for hiding this comment

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

Generally, all preprocessor macros are put into a special file (<hpx/config/defines.hpp>) instead of being added to the compiler's command line. This ensures that all targets that depend on HPX (even external ones) will see a consistent set of preprocessor definitions.

Suggested change
add_compile_definitions(HPX_HAVE_CXX_MODULES)
hpx_add_config_define(HPX_HAVE_CXX_MODULES)

@@ -4,8 +4,8 @@
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

#include <hpx/global_module.hpp>
Copy link
Member

@hkaiser hkaiser Aug 9, 2025

Choose a reason for hiding this comment

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

Let's stick with the conventions:

Suggested change
#include <hpx/global_module.hpp>
#include <hpx/modules/version.hpp>

Alternatively (to avoid having to touch all files that currently #include <hpx/version.hpp>), we could add #include <hpx/modules/version.hpp> in that file.

Not sure if this wouldn't create a circular #include sequence, though. In this case, we need to reshuffle the content slightly:

@@ -17,56 +17,56 @@
namespace hpx {

// Returns the major HPX version.
[[nodiscard]] HPX_CORE_EXPORT std::uint8_t major_version();
HPX_MODULE_EXTERN_CORE [[nodiscard]] std::uint8_t major_version();
Copy link
Member

Choose a reason for hiding this comment

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

I think this has to be in a reverse sequence, it may generate compilation errors otherwise.

Suggested change
HPX_MODULE_EXTERN_CORE [[nodiscard]] std::uint8_t major_version();
[[nodiscard]] HPX_MODULE_EXTERN_CORE std::uint8_t major_version();

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants