Skip to content

Implement C++20 module system with MPI support#90

Open
Luohaothu wants to merge 5 commits intomasterfrom
feature/cpp20-modules
Open

Implement C++20 module system with MPI support#90
Luohaothu wants to merge 5 commits intomasterfrom
feature/cpp20-modules

Conversation

@Luohaothu
Copy link
Contributor

Summary

Add complete C++20 module support with experimental module builds and MPI integration.

Changes

Build System

  • Add CMake 4.0.2+ module support with Ninja generator
  • Set up GCC 15 and Clang 21 toolchains in CI
  • Build libc++ modules on macOS when missing
  • Add module-specific compilation flags

Module Implementation

  • Create opflow.cppm and amgcl.cppm module definitions
  • Fix module export leakage to consumers
  • Trim AMGCL module for compatibility
  • Add fallback paths for libc++ modules.json

MPI & Platform Support

  • Provide dummy MPI types when MPI is disabled
  • Guard MPI definitions and includes properly
  • Add macOS SDK sysroot for Homebrew clang
  • Guard -mfma flag for non-x86 architectures
  • Fix Boost cstdint includes for macOS gcc

Test Plan

  • Build with modules enabled: cmake -DOPFLOW_ENABLE_MODULE=ON
  • Verify traditional header-only build still works
  • Test with MPI enabled: cmake -DOPFLOW_WITH_MPI=ON
  • Validate on macOS with Homebrew clang
  • Run CI matrix (GCC 15, Clang 21, with/without modules)

Dependencies

None - can be merged independently

🤖 Generated with Claude Code

Luohaothu and others added 5 commits February 4, 2026 21:39
- Configure Ninja generator for C++ module builds
- Add gcc-15/llvm-21 toolchains in CI
- Stabilize CI dependencies and pin CMake 4.0.2
- Update CMake gates for version 4.2
- Harden CI gcc-15 installation and module links
- Fix header file set install for interface targets
- Build libc++ modules on macOS when missing
- Align CI toolchain and CMake installs
- Make std-module patch resilient and non-fatal

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Fix module export leakage to consumers
- Fix INTERFACE target wiring for libc++ module detection
- Add fallback path for libc++ modules.json
- Trim amgcl module and fix MPI communication
- Fix module exports for clang and GCC
- Adjust ext.amgcl module for GCC compatibility
- Mute thread-safety warnings in modules
- Propagate MPI definitions to module builds

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Provide dummy MPI types when MPI is disabled
- Fix MPI logging macro guards
- Guard dummy MPI typedef when MPI headers present
- Include mpi.h when available in non-MPI builds
- Disable MPI C++ bindings globally
- Initialize MPI when headers are available
- Expose MPI init in module builds when headers exist
- Guard -mfma flag for non-x86 architectures
- Add macOS SDK sysroot for Homebrew clang
- Fix macOS libc++ modules.json detection
- Restore macOS gcc matrix and fix boost cstdint includes

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Replace std::print with std::format for portability
- Avoid chrono time zone APIs (require C++20 timezone support)
- Fix amgcl test includes and std::print usage
- Update C++ headers to use standard library consistently
- Apply code formatting across the codebase

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
@coderabbitai
Copy link

coderabbitai bot commented Feb 4, 2026

Important

Review skipped

Too many files!

This PR contains 221 files, which is 71 over the limit of 150.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

  • 🔍 Trigger a full review
✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/cpp20-modules

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@gemini-code-assist
Copy link

Summary of Changes

Hello @Luohaothu, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly advances the project's build infrastructure and C++ standard adoption by integrating a comprehensive C++20 module system. It introduces experimental module builds, refines MPI support for better compatibility and robustness, and includes several platform-specific fixes, particularly for macOS. The changes aim to modernize the codebase, improve build times, and ensure broader compiler and environment compatibility, while maintaining support for traditional header-only builds.

Highlights

  • C++20 Module System Integration: Full C++20 module support has been implemented, including experimental module builds and dedicated module definitions for opflow.cppm and amgcl.cppm.
  • CMake Build System Enhancements: The CMake build system has been updated to support CMake 4.0.2+ with the Ninja generator, incorporating conditional experimental feature flags and a new OPFLOW_TARGET_SCOPE for managing target properties based on module enablement.
  • MPI Support Refinements: MPI integration has been improved with proper guarding of definitions and includes, disabling deprecated C++ MPI bindings, and providing dummy MPI types when MPI is not enabled.
  • Platform Compatibility Improvements: Addressed macOS-specific issues, such as building libc++ modules, including SDK sysroot for Homebrew clang, and fixing Boost cstdint includes for macOS GCC. The -mfma flag is now conditionally applied only to x86 architectures.
  • Code Modernization & Cleanup: Replaced std::print with std::cout << std::format for broader compiler compatibility and removed redundant template keywords from emplace_back calls.
  • Copyright Year Update: Copyright notices across various files have been updated to 2026.
Changelog
  • CMakeLists.txt
    • Updated copyright year to 2026.
    • Introduced conditional CMAKE_EXPERIMENTAL_CXX_IMPORT_STD and CMAKE_EXPERIMENTAL_EXPORT_BUILD_DATABASE values based on CMake version for module support.
    • Removed redundant CMAKE_EXPERIMENTAL_EXPORT_BUILD_DATABASE and CMAKE_EXPORT_BUILD_DATABASE settings.
    • Added compile definitions OMPI_SKIP_MPICXX and MPICH_SKIP_MPICXX to disable deprecated MPI C++ bindings.
    • Introduced OPFLOW_TARGET_SCOPE variable (PUBLIC/INTERFACE) based on OPFLOW_ENABLE_MODULE for conditional target property application.
  • examples/AMR/Poisson.cpp
    • Included <chrono>, <ctime>, <string> headers.
    • Replaced std::format with std::chrono::system_clock::to_time_t and std::strftime for generating timestamped directory names, improving portability.
    • Added a newline at the end of the file.
  • examples/CMakeLists.txt
    • Guarded the -mfma compiler flag for Clang to apply only on x86_64 architectures.
    • Added a newline at the end of the file.
  • examples/LevelSet/AMRLS.cpp
    • Included <ctime> and <string> headers.
    • Replaced std::format with a make_result_root helper function using std::chrono::system_clock::to_time_t and std::strftime for timestamped directory names.
    • Added a newline at the end of the file.
  • examples/LevelSet/UniLS.cpp
    • Included <chrono>, <ctime>, <string> headers.
    • Replaced std::format with a make_result_root helper function using std::chrono::system_clock::to_time_t and std::strftime for timestamped directory names.
    • Added a newline at the end of the file.
  • external/CMakeLists.txt
    • Modified target_link_libraries and target_compile_definitions to use the OPFLOW_TARGET_SCOPE variable (PUBLIC/INTERFACE) for external dependencies (spdlog, amgcl, TBB, HYPRE, VTK, TecIO).
  • external/amgcl/amgcl/util.hpp
    • Added conditional boost::long_long_type and boost::ulong_long_type definitions for macOS GCC to fix Boost cstdint includes.
    • Included <boost/cstdint.hpp>.
  • scripts/update_copyright.sh
    • Updated copyright year in the script header to 2026.
  • src/CMakeLists.txt
    • Changed OPFLOW_USE_MODULE compile definition from PUBLIC to PRIVATE when modules are enabled.
    • Modified target_sources for header-only builds to explicitly specify BASE_DIRS for header files.
    • Modified install(TARGETS opflow) to use FILE_SET HEADERS for installation.
    • Changed target_include_directories for opflow to use OPFLOW_TARGET_SCOPE.
    • Modified target_compile_definitions for OPFLOW_OPTION flags to use OPFLOW_TARGET_SCOPE.
    • Modified target_compile_definitions for OPFLOW_DISTRIBUTE_MODEL_MPI to use OPFLOW_TARGET_SCOPE.
  • src/Core/BasicDataTypes.hpp
    • Updated copyright year to 2026.
  • src/Core/Constants.hpp
    • Updated copyright year to 2026.
  • src/Core/Environment.hpp
    • Updated copyright year to 2026.
    • Refined MPI include guards and definitions (OMPI_SKIP_MPICXX, MPICH_SKIP_MPICXX, OPFLOW_HAS_MPI) to handle cases where MPI headers are available but OPFLOW_WITH_MPI is not defined.
    • Replaced std::print with std::cout << std::format for version printing.
    • Simplified InitEnvironment and FinalizeEnvironment MPI calls using defined(OPFLOW_WITH_MPI) || defined(OPFLOW_HAS_MPI).
  • src/Core/Equation/AMGCLBackend.hpp
    • Updated copyright year to 2026.
  • src/Core/Equation/AMGCLEqnSolveHandler.hpp
    • Updated copyright year to 2026.
  • src/Core/Equation/CSRMatrixGenerator.hpp
    • Updated copyright year to 2026.
  • src/Core/Equation/EqnSolveHandler.hpp
    • Updated copyright year to 2026.
  • src/Core/Equation/Equation.hpp
    • Updated copyright year to 2026.
  • src/Core/Equation/EquationHolder.hpp
    • Updated copyright year to 2026.
  • src/Core/Equation/HYPREEqnSolveHandler.hpp
    • Updated copyright year to 2026.
    • Included <format> and <iostream>.
    • Replaced std::print with std::cout << std::format for debug output.
  • src/Core/Equation/StencilHolder.hpp
    • Updated copyright year to 2026.
  • src/Core/Equation/UnifiedSolve.hpp
    • Updated copyright year to 2026.
  • src/Core/Field/MeshBased/Structured/CartesianField.hpp
    • Removed template keyword from requests.emplace_back().
  • src/Core/Loops/RangeFor.hpp
    • Removed template keyword from arena.execute() call.
  • src/Core/Macros.hpp
    • Updated copyright year to 2026.
    • Added OMPI_SKIP_MPICXX and MPICH_SKIP_MPICXX definitions within OPFLOW_WITH_MPI block.
    • Changed inline static int getWorkerId to inline int getWorkerId.
    • Introduced dummy MPI_Comm and MPI_COMM_WORLD definitions when MPI is not explicitly enabled but <mpi.h> might be present.
    • Changed inline static Utils::StackTracer stackTracer to inline Utils::StackTracer stackTracer.
  • src/Core/Mesh/SemiStructured/CartesianAMRMesh.hpp
    • Removed template keyword from emplace_back calls.
  • src/Core/Meta.hpp
    • Updated copyright year to 2026.
  • src/Core/Parallel/ParallelInfo.hpp
    • Updated copyright year to 2026.
  • src/Core/Solvers/SemiStruct/SemiStructSolver.hpp
    • Simplified MPI_Comm comm initialization, removing conditional OPFLOW_WITH_MPI block.
  • src/Core/Solvers/Struct/StructSolver.hpp
    • Simplified MPI_Comm comm initialization, removing conditional OPFLOW_WITH_MPI block.
  • src/Core/Solvers/Struct/StructSolverCycRed.hpp
    • Simplified MPI_Comm comm initialization, removing conditional OPFLOW_WITH_MPI block.
  • src/DataStructures/Index/LinearMapper/BlockedMDRangeMapper.hpp
    • Removed template keyword from segments[i].emplace_back() call.
  • src/DataStructures/Index/LinearMapper/ColoredBlockedMDRangeMapper.hpp
    • Removed template keyword from mappers.emplace_back() calls.
  • src/DataStructures/Index/LinearMapper/ColoredMDRangeMapper.hpp
    • Removed template keyword from mappers.emplace_back() call.
  • src/Utils/Writers/IOGroup.hpp
    • Removed template keyword from streams.emplace_back() calls.
  • src/amgcl.cppm
    • Trimmed AMGCL includes to only amgcl/adapter/zero_copy.hpp and amgcl/profiler.hpp.
    • For MPI, only amgcl/mpi/util.hpp and amgcl/mpi/distributed_matrix.hpp are included.
    • Removed various specific AMGCL solver, backend, coarsening, and relaxation includes from the module interface.
    • Removed conditional includes for ParMETIS and Scotch.
    • Exported amgcl::mpi::communicator and amgcl::mpi::distributed_matrix when OPFLOW_WITH_MPI is defined.
  • src/opflow.cppm
    • Added conditional include for <omp.h> when OPFLOW_WITH_OPENMP is defined.
  • test/CMakeLists.txt
    • Updated copyright year to 2026.
  • test/Core/BC/DircBCTest.cpp
    • Added conditional include for opflow module or header.
  • test/Core/BC/NeumBCTest.cpp
    • Added conditional include for opflow module or header.
  • test/Core/BC/PeriodicBCTest.cpp
    • Added conditional include for opflow module or header.
  • test/Core/CMakeLists.txt
    • Updated copyright year to 2026.
  • test/Core/Equation/AMGCLMPITest.cpp
    • Added specific AMGCL includes for MPI solvers, backends, etc.
    • Included <format> and <iostream>.
    • Added conditional include for opflow module or header.
    • Replaced std::print with std::cerr << std::format for error messages.
  • test/Core/Equation/AMGCLTest.cpp
    • Added specific AMGCL includes for solvers, backends, etc.
    • Added conditional include for opflow module or header.
    • Added a newline at the end of the file.
  • test/Core/Equation/CSRMatrixGeneratorMPITest.cpp
    • Included <mpi.h>.
    • Added conditional include for opflow module or header.
    • Added a newline at the end of the file.
  • test/Core/Equation/CSRMatrixGeneratorTest.cpp
    • Included <format> and <iostream>.
    • Added conditional include for opflow module or header.
    • Replaced std::print with std::cout << std::format for debug output.
  • test/Core/Equation/DircEqnTest.cpp
    • Added specific AMGCL includes for solvers, backends, etc.
    • Included <format> and <iostream>.
    • Added conditional include for opflow module or header.
    • Replaced std::print with std::cerr << std::format for error messages.
    • Added a newline at the end of the file.
  • test/Core/Equation/EqnHolderTest.cpp
    • Included <format> and <iostream>.
    • Added conditional include for opflow module or header.
    • Replaced std::print with std::cerr << std::format for error messages.
  • test/Core/Equation/EqnSetMPITest.cpp
    • Added specific AMGCL includes for MPI solvers, backends, etc.
    • Included <format> and <iostream>.
    • Added conditional include for opflow module or header.
    • Replaced std::print with std::cout << std::format for debug output.
  • test/Core/Equation/EqnSetTest.cpp
    • Added specific AMGCL includes for solvers, backends, etc.
    • Included <format> and <iostream>.
    • Added conditional include for opflow module or header.
    • Replaced std::print with std::cout << std::format for debug output.
  • test/Core/Equation/NeumEqnTest.cpp
    • Added specific AMGCL includes for solvers, backends, etc.
    • Included <format> and <iostream>.
    • Added conditional include for opflow module or header.
    • Replaced std::print with std::cerr << std::format for error messages.
    • Added a newline at the end of the file.
  • test/Core/Equation/PeriodicEqnTest.cpp
    • Added specific AMGCL includes for solvers, backends, etc.
    • Included <format> and <iostream>.
    • Added conditional include for opflow module or header.
    • Replaced std::print with std::cerr << std::format for error messages.
    • Added a newline at the end of the file.
  • test/Core/Field/CartesianFieldMPITest.cpp
    • Included <format> and <iostream>.
    • Added conditional include for opflow module or header.
    • Replaced std::print with std::cout << std::format for debug output.
  • test/Core/Field/CartesianFieldTest.cpp
    • Included <format> and <iostream>.
    • Added conditional include for opflow module or header.
    • Replaced std::print with std::cerr << std::format for error messages.
  • test/Core/Loops/RangeForTest.cpp
    • Included <format> and <iostream>.
    • Added conditional include for opflow module or header.
    • Added a newline at the end of the file.
  • test/Core/Loops/RangeReduceTest.cpp
    • Added conditional include for opflow module or header.
  • test/Core/Mesh/CartesianMeshTest.cpp
    • Added conditional include for opflow module or header.
  • test/Core/MetaTest.cpp
    • Added conditional include for opflow module or header.
  • test/Core/Operator/ConditionalTest.cpp
    • Added conditional include for opflow module or header.
  • test/Core/Operator/ConvolutionTest.cpp
    • Added conditional include for opflow module or header.
  • test/Core/Operator/InterpolatorTest.cpp
    • Included <format> and <iostream>.
    • Added conditional include for opflow module or header.
    • Replaced std::print with std::cout << std::format for debug output.
    • Added a newline at the end of the file.
  • test/Core/Parallel/EvenSplitStrategyTest.cpp
    • Added conditional include for opflow module or header.
  • test/Core/Parallel/MPITest.cpp
    • Included <format> and <iostream>.
    • Added conditional include for opflow module or header.
    • Replaced std::print with std::cout << std::format for debug output.
    • Added a newline at the end of the file.
  • test/Core/Parallel/ParticleGuidedSplitStrategyTest.cpp
    • Included <format> and <iostream>.
    • Added conditional include for opflow module or header.
    • Replaced std::print with std::cout << std::format for debug output.
  • test/DataStructures/Arrays/PlainTensorTest.cpp
    • Added conditional include for opflow module or header.
  • test/DataStructures/CMakeLists.txt
    • Updated copyright year to 2026.
  • test/DataStructures/Index/BlockedMDRangeMapperTest.cpp
    • Added conditional include for opflow module or header.
  • test/DataStructures/Index/ColoredBlockedMDRangeMapperTest.cpp
    • Added conditional include for opflow module or header.
  • test/DataStructures/Index/MDIndexTest.cpp
    • Added conditional include for opflow module or header.
  • test/DataStructures/StencilPadTest.cpp
    • Added conditional include for opflow module or header.
  • test/Utils/CMakeLists.txt
    • Updated copyright year to 2026.
  • test/Utils/HDF5StreamMPITest.cpp
    • Included <format> and <iostream>.
    • Added conditional include for opflow module or header.
    • Replaced std::print with std::cerr << std::format for error messages.
    • Replaced std::print with std::cout << std::format for debug output.
  • test/Utils/HDF5StreamTest.cpp
    • Included <format>.
    • Added conditional include for opflow module or header.
  • test/Utils/IOGroupTest.cpp
    • Included <format>.
    • Added conditional include for opflow module or header.
    • Added a newline at the end of the file.
  • test/Utils/TecplotStreamMPITest.cpp
    • Added conditional include for opflow module or header.
  • test/Utils/TecplotStreamTest.cpp
    • Added conditional include for opflow module or header.
  • test/test_main.cpp
    • Added conditional include for opflow module or header.
  • test/test_main_mpi.cpp
    • Added conditional include for opflow module or header.
Ignored Files
  • Ignored by pattern: .github/workflows/** (1)
    • .github/workflows/Build.yml
Activity
  • The pull request introduces C++20 module support and MPI integration.
  • The build system has been updated to support CMake 4.0.2+ and experimental C++ module features.
  • Toolchains for GCC 15 and Clang 21 are set up in CI.
  • Module definitions for opflow.cppm and amgcl.cppm have been created.
  • MPI definitions and includes are now properly guarded, and deprecated C++ MPI bindings are skipped.
  • Platform-specific fixes for macOS, including libc++ module builds and Boost cstdint issues, have been applied.
  • The -mfma flag is now conditionally applied only to x86 architectures.
  • Copyright years have been updated to 2026 across many files.
  • std::print calls have been replaced with std::cout << std::format for wider compatibility.
  • Redundant template keywords in emplace_back calls have been removed.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e2dbc728de

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines 37 to 40
void inline InitEnvironment(int* argc, char*** argv) {
#ifdef OPFLOW_WITH_MPI
#if defined(OPFLOW_WITH_MPI) || defined(OPFLOW_HAS_MPI)
MPI_Init(argc, argv);
#endif

Choose a reason for hiding this comment

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

P1 Badge Gate MPI_Init/Finalize on OPFLOW_WITH_MPI only

When mpi.h is present, OPFLOW_HAS_MPI becomes defined and InitEnvironment now calls MPI_Init even if OPFLOW_WITH_MPI is OFF. On systems that have MPI headers installed but aren’t linking the MPI libraries (the normal case when the option is OFF), this introduces undefined references at link time and changes runtime behavior by initializing MPI unexpectedly. Please keep the MPI calls guarded by the build option rather than header availability.

Useful? React with 👍 / 👎.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces comprehensive C++20 module support and enhances MPI integration, which is a significant and well-executed update. The changes to the CMake build system are robust, correctly handling the differences between header-only and module-based builds. I appreciate the numerous portability improvements, such as replacing non-standard std::format usage, making compiler flags architecture-specific, and providing dummy MPI types for non-MPI builds. The code quality has also been improved by removing redundant keywords and correcting the usage of inline with static. Overall, this is an excellent contribution. I have one minor suggestion for code cleanup in a CMake file.

Comment on lines +95 to +99
if(OPFLOW_ENABLE_MODULE)
set(OPFLOW_TARGET_SCOPE PUBLIC)
else()
set(OPFLOW_TARGET_SCOPE INTERFACE)
endif()

Choose a reason for hiding this comment

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

medium

This block of code, which sets the OPFLOW_TARGET_SCOPE variable, is a duplication of the logic already present in the root CMakeLists.txt (lines 137-141). Since CMake variables set in a parent scope are inherited by subdirectories, this block is redundant and can be removed to improve maintainability.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant