Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
38 changes: 21 additions & 17 deletions .github/workflows/Build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ on:
jobs:
generate:
name: MPI${{ matrix.mpi }}/${{ matrix.mode }}
runs-on: ubuntu-24.04
container:
image: luohaothu/gcc-trunk:latest
runs-on: ubuntu-latest
container:
image: gcc:14
strategy:
fail-fast: false
matrix:
Expand All @@ -39,6 +39,20 @@ jobs:
with:
submodules: recursive
fetch-depth: 0
- name: Install dependencies
run: |
apt-get update && apt-get install -y \
wget \
ninja-build \
libhdf5-dev \
libhdf5-openmpi-dev \
libboost-all-dev \
python3-pip \
python3-sphinx \
doxygen \
openmpi-bin \
libopenmpi-dev \
&& gcc --version && g++ --version
- name: Make directory
run: mkdir -p build
- name: Generate
Expand All @@ -48,21 +62,11 @@ jobs:
chmod +x cmake-4.0.2-linux-x86_64.sh
mkdir -p cmake
./cmake-4.0.2-linux-x86_64.sh --skip-license --prefix=$(pwd)/cmake
apt update && apt install -y ninja-build libhdf5-dev libhdf5-openmpi-dev libboost-all-dev python3-pip python3-sphinx doxygen
export PATH=$(pwd)/cmake/bin:$PATH
cmake -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -G Ninja -B build \
cmake -S .. -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -G Ninja -B . \
-DCMAKE_INSTALL_PREFIX=$(pwd)/install -DOPFLOW_BUILD_ALL=ON -DOPFLOW_ENABLE_MODULE=ON \
-DCMAKE_BUILD_TYPE=${{ matrix.mode }} -DOPFLOW_WITH_HDF5=ON -DOPFLOW_WITH_MPI=${{ matrix.mpi }}
if [ "$RUNNER_OS" == "Linux" ]; then
cmake --build build -t All_CI --parallel $(nproc) --config ${{ matrix.mode }}
else
cmake --build build -t All_CI --parallel $(nproc) --config ${{ matrix.mode }}
fi
-DCMAKE_BUILD_TYPE=${{ matrix.mode }} -DOPFLOW_WITH_HDF5=ON -DOPFLOW_WITH_MPI=${{ matrix.mpi }}
cmake --build . -t All_CI --parallel $(nproc) --config ${{ matrix.mode }}
- name: Test
working-directory: ./build
run: |
if [ "$RUNNER_OS" == "Linux" ]; then
ctest --parallel $(nproc) -C ${{ matrix.mode }} -VV
else
ctest --parallel $(nproc) -C ${{ matrix.mode }} -VV
fi
run: ctest --parallel $(nproc) -C ${{ matrix.mode }} -VV
163 changes: 121 additions & 42 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# ----------------------------------------------------------------------------
#
# Copyright (c) 2019 - 2025 by the OpFlow developers
# Copyright (c) 2019 - 2026 by the OpFlow developers
#
# This file is part of OpFlow.
#
Expand All @@ -20,7 +20,7 @@ set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD
# This specific value changes as experimental support evolves. See
# `Help/dev/experimental.rst` in the CMake source corresponding to
# your CMake build for the exact value to use.
"a9e1cf81-9932-4810-974b-6eccaf14e457")
d0edc3af-4c50-42ea-a356-e2862fe7a444)
set(CMAKE_EXPERIMENTAL_EXPORT_BUILD_DATABASE 4bd552e2-b7fb-429a-ab23-c83ef53f3f13)
set(CMAKE_EXPORT_BUILD_DATABASE 1)

Expand All @@ -44,7 +44,36 @@ message(STATUS "Build opflow: ${OPFLOW_VERSION_STRING}")
set(CMAKE_EXPERIMENTAL_EXPORT_BUILD_DATABASE 4bd552e2-b7fb-429a-ab23-c83ef53f3f13)
set(CMAKE_EXPORT_BUILD_DATABASE 1)

set(CMAKE_CXX_MODULE_STD 1)
# Enable CMake's experimental `import std` support only when the toolchain
# provides the required stdlib module resource file. Otherwise CMake errors out
# at generate time (e.g. missing `libstdc++.modules.json`).
set(CMAKE_CXX_MODULE_STD 0)

set(_opflow_has_stdlib_modules_json 0)
if(CMAKE_CXX_COMPILER)
execute_process(
COMMAND "${CMAKE_CXX_COMPILER}" -print-resource-dir
OUTPUT_VARIABLE _opflow_clang_resource_dir
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_QUIET)
if(_opflow_clang_resource_dir)
foreach(_opflow_candidate
"${_opflow_clang_resource_dir}/libstdc++.modules.json"
"${_opflow_clang_resource_dir}/libc++.modules.json"
"${_opflow_clang_resource_dir}/share/libstdc++.modules.json"
"${_opflow_clang_resource_dir}/share/libc++.modules.json")
if(EXISTS "${_opflow_candidate}")
set(_opflow_has_stdlib_modules_json 1)
endif()
endforeach()
endif()
endif()

if(_opflow_has_stdlib_modules_json)
set(CMAKE_CXX_MODULE_STD 1)
else()
message(STATUS "C++ stdlib modules resource not found; disabling CMAKE_CXX_MODULE_STD")
endif()

include(GNUInstallDirs)

Expand Down Expand Up @@ -130,6 +159,14 @@ option(OPFLOW_BUILD_WARNINGS "Enable compiler warnings" OFF)
option(OPFLOW_NO_EXCEPTIONS "Compile with -fno-exceptions" OFF)
option(OPFLOW_ENABLE_MODULE "Enable C++ modules support" OFF)

# Usage requirements scope for the `opflow` target.
# When OPFLOW_ENABLE_MODULE=OFF, `opflow` is an INTERFACE library.
if(OPFLOW_ENABLE_MODULE)
set(OPFLOW_USAGE_SCOPE PUBLIC)
else()
set(OPFLOW_USAGE_SCOPE INTERFACE)
endif()

# install options
option(OPFLOW_INSTALL "Generate the install target" ${PROJECT_IS_TOP_LEVEL})
# the default behavior is to use bundled HYPRE, VTK & TBB
Expand All @@ -150,19 +187,22 @@ if(OPFLOW_TIDY)
endif()

message(STATUS "Build type: " ${CMAKE_BUILD_TYPE})
add_subdirectory(src)

# ----------------------------------------------------------------------------
# External dependencies
# ----------------------------------------------------------------------------
add_subdirectory(external)
# Ensure bundled dependency install steps (run during configure when OPFLOW_INSTALL=ON)
# do not attempt to write to system locations like /usr/local.
if(OPFLOW_INSTALL AND CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
set(CMAKE_INSTALL_PREFIX "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}" CACHE PATH "" FORCE)
message(STATUS "Install prefix set to: ${CMAKE_INSTALL_PREFIX}")
endif()

add_subdirectory(src)

# ----------------------------------------------------------------------------
# Find MPI
# ----------------------------------------------------------------------------
if(OPFLOW_WITH_MPI)
find_package(MPI REQUIRED)
target_link_libraries(opflow INTERFACE MPI::MPI_C MPI::MPI_CXX)
target_link_libraries(opflow ${OPFLOW_USAGE_SCOPE} MPI::MPI_C MPI::MPI_CXX)

list(APPEND PKG_CONFIG_REQUIRES MPI)
endif()
Expand All @@ -179,34 +219,78 @@ if(OPFLOW_WITH_OPENMP)
link_directories("/opt/homebrew/lib")
endif()
endif()
if(CMAKE_C_COMPILER_ID MATCHES "Clang")
set(OpenMP_C "${CMAKE_C_COMPILER}")
set(OpenMP_C_FLAGS "-fopenmp=libomp -Wno-unused-command-line-argument -Wno-deprecated-pragma")
set(OpenMP_C_LIB_NAMES "omp")
set(OpenMP_omp_LIBRARY ${OpenMP_C_LIB_NAMES})
endif()
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
set(OpenMP_CXX "${CMAKE_CXX_COMPILER}")
set(OpenMP_CXX_FLAGS "-fopenmp=libomp -Wno-unused-command-line-argument")
set(OpenMP_CXX_LIB_NAMES "omp")
set(OpenMP_omp_LIBRARY ${OpenMP_CXX_LIB_NAMES})
if(CMAKE_C_COMPILER_ID MATCHES "Clang" OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
# Prefer libgomp on Linux environments without libomp.
find_library(OPFLOW_OPENMP_LIBRARY NAMES gomp)
if(NOT OPFLOW_OPENMP_LIBRARY)
find_library(OPFLOW_OPENMP_LIBRARY NAMES gomp
PATHS
/usr/lib/gcc/x86_64-linux-gnu/14
/usr/lib/gcc/x86_64-linux-gnu/13)
endif()
if(NOT OPFLOW_OPENMP_LIBRARY)
find_library(OPFLOW_OPENMP_LIBRARY NAMES omp)
endif()

if(OPFLOW_OPENMP_LIBRARY AND OPFLOW_OPENMP_LIBRARY MATCHES "libgomp")
set(_opflow_openmp_runtime "libgomp")
set(_opflow_openmp_lib_name "gomp")
else()
set(_opflow_openmp_runtime "libomp")
set(_opflow_openmp_lib_name "omp")
endif()

set(_opflow_openmp_include_dir "")
if(EXISTS "/usr/lib/gcc/x86_64-linux-gnu/14/include/omp.h")
set(_opflow_openmp_include_dir "/usr/lib/gcc/x86_64-linux-gnu/14/include")
elseif(EXISTS "/usr/lib/gcc/x86_64-linux-gnu/13/include/omp.h")
set(_opflow_openmp_include_dir "/usr/lib/gcc/x86_64-linux-gnu/13/include")
endif()
if(_opflow_openmp_include_dir)
# Make omp.h discoverable without overriding Clang's own headers
# (e.g. avoid picking up GCC's immintrin.h).
set(_opflow_openmp_include_arg "-idirafter ${_opflow_openmp_include_dir}")
else()
set(_opflow_openmp_include_arg "")
endif()

if(CMAKE_C_COMPILER_ID MATCHES "Clang")
set(OpenMP_C "${CMAKE_C_COMPILER}" CACHE FILEPATH "" FORCE)
set(OpenMP_C_FLAGS "-fopenmp=${_opflow_openmp_runtime} ${_opflow_openmp_include_arg} -Wno-unused-command-line-argument -Wno-deprecated-pragma" CACHE STRING "" FORCE)
set(OpenMP_C_LIB_NAMES "${_opflow_openmp_lib_name}" CACHE STRING "" FORCE)
endif()
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
set(OpenMP_CXX "${CMAKE_CXX_COMPILER}" CACHE FILEPATH "" FORCE)
set(OpenMP_CXX_FLAGS "-fopenmp=${_opflow_openmp_runtime} ${_opflow_openmp_include_arg} -Wno-unused-command-line-argument" CACHE STRING "" FORCE)
set(OpenMP_CXX_LIB_NAMES "${_opflow_openmp_lib_name}" CACHE STRING "" FORCE)
endif()

if(OPFLOW_OPENMP_LIBRARY)
# FindOpenMP's required vars vary by compiler/runtime; make the path available.
set(OpenMP_omp_LIBRARY "${OPFLOW_OPENMP_LIBRARY}" CACHE FILEPATH "" FORCE)
set(OpenMP_gomp_LIBRARY "${OPFLOW_OPENMP_LIBRARY}" CACHE FILEPATH "" FORCE)
endif()
endif()
find_package(OpenMP REQUIRED)
target_link_libraries(opflow INTERFACE OpenMP::OpenMP_C OpenMP::OpenMP_CXX)
target_compile_options(opflow INTERFACE ${OpenMP_CXX_FLAGS})
target_link_libraries(opflow ${OPFLOW_USAGE_SCOPE} OpenMP::OpenMP_C OpenMP::OpenMP_CXX)

list(APPEND PKG_CONFIG_REQUIRES OpenMP)
endif()

# ----------------------------------------------------------------------------
# External dependencies
# ----------------------------------------------------------------------------
add_subdirectory(external)

# ----------------------------------------------------------------------------
# Platform detection
# ----------------------------------------------------------------------------
if(UNIX)
target_compile_definitions(opflow INTERFACE OPFLOW_PLATFORM_UNIX)
target_compile_definitions(opflow ${OPFLOW_USAGE_SCOPE} OPFLOW_PLATFORM_UNIX)
elseif(APPLE)
target_compile_definitions(opflow INTERFACE OPFLOW_PLATFORM_APPLE)
target_compile_definitions(opflow ${OPFLOW_USAGE_SCOPE} OPFLOW_PLATFORM_APPLE)
elseif(WIN32)
target_compile_definitions(opflow INTERFACE OPFLOW_PLATFORM_WIN)
target_compile_definitions(opflow ${OPFLOW_USAGE_SCOPE} OPFLOW_PLATFORM_WIN)
endif()

# ----------------------------------------------------------------------------
Expand All @@ -215,7 +299,7 @@ endif()
include(CheckIncludeFiles)
check_include_files("sys/mman.h" HAS_SYS_MMAN_H)
if(HAS_SYS_MMAN_H)
target_compile_definitions(opflow INTERFACE OPFLOW_HAS_MMAN_H)
target_compile_definitions(opflow ${OPFLOW_USAGE_SCOPE} OPFLOW_HAS_MMAN_H)
endif()

# ----------------------------------------------------------------------------
Expand All @@ -227,28 +311,28 @@ foreach(
OPFLOW_WITH_MPI
OPFLOW_WITH_OPENMP)
if(${OPFLOW_OPTION})
target_compile_definitions(opflow INTERFACE ${OPFLOW_OPTION})
target_compile_definitions(opflow ${OPFLOW_USAGE_SCOPE} ${OPFLOW_OPTION})
endif()
endforeach()
if(OPFLOW_WITH_MPI)
target_compile_definitions(opflow INTERFACE OPFLOW_DISTRIBUTE_MODEL_MPI)
target_compile_definitions(opflow ${OPFLOW_USAGE_SCOPE} OPFLOW_DISTRIBUTE_MODEL_MPI)
endif()

if(OPFLOW_NO_EXCEPTIONS AND NOT MSVC)
target_compile_options(opflow INTERFACE -fno-exceptions)
target_compile_options(opflow ${OPFLOW_USAGE_SCOPE} -fno-exceptions)
endif()

# sanitizer flags
target_compile_options(opflow
INTERFACE $<$<BOOL:${OPFLOW_SANITIZE_ADDRESS}>: -fsanitize=address>
INTERFACE $<$<BOOL:${OPFLOW_SANITIZE_LEAK}>: -fsanitize=leak>
INTERFACE $<$<BOOL:${OPFLOW_SANITIZE_THREAD}>: -fsanitize=thread>
INTERFACE $<$<BOOL:${OPFLOW_SANITIZE_UB}>: -fsanitize=undefined>)
${OPFLOW_USAGE_SCOPE} $<$<BOOL:${OPFLOW_SANITIZE_ADDRESS}>: -fsanitize=address>
${OPFLOW_USAGE_SCOPE} $<$<BOOL:${OPFLOW_SANITIZE_LEAK}>: -fsanitize=leak>
${OPFLOW_USAGE_SCOPE} $<$<BOOL:${OPFLOW_SANITIZE_THREAD}>: -fsanitize=thread>
${OPFLOW_USAGE_SCOPE} $<$<BOOL:${OPFLOW_SANITIZE_UB}>: -fsanitize=undefined>)
target_link_options(opflow
INTERFACE $<$<BOOL:${OPFLOW_SANITIZE_ADDRESS}>: -fsanitize=address>
INTERFACE $<$<BOOL:${OPFLOW_SANITIZE_LEAK}>: -fsanitize=leak>
INTERFACE $<$<BOOL:${OPFLOW_SANITIZE_THREAD}>: -fsanitize=thread>
INTERFACE $<$<BOOL:${OPFLOW_SANITIZE_UB}>: -fsanitize=undefined>)
${OPFLOW_USAGE_SCOPE} $<$<BOOL:${OPFLOW_SANITIZE_ADDRESS}>: -fsanitize=address>
${OPFLOW_USAGE_SCOPE} $<$<BOOL:${OPFLOW_SANITIZE_LEAK}>: -fsanitize=leak>
${OPFLOW_USAGE_SCOPE} $<$<BOOL:${OPFLOW_SANITIZE_THREAD}>: -fsanitize=thread>
${OPFLOW_USAGE_SCOPE} $<$<BOOL:${OPFLOW_SANITIZE_UB}>: -fsanitize=undefined>)

# ----------------------------------------------------------------------------
# All_CI target (= AllExamples + AllBenchmarks + AllTests)
Expand Down Expand Up @@ -281,7 +365,6 @@ if(OPFLOW_BUILD_BENCHMARKS OR OPFLOW_BUILD_ALL)
set(BENCHMARK_ENABLE_INSTALL OFF)
set(BENCHMARK_ENABLE_TESTING OFF)
set(BENCHMARK_ENABLE_GTEST_TESTS OFF)
add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/external/benchmark EXCLUDE_FROM_ALL)
add_subdirectory(benchmark)
Comment on lines 365 to 368

Choose a reason for hiding this comment

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

P2 Badge Ensure benchmark dependency for OPFLOW_BUILD_ALL

When OPFLOW_BUILD_ALL is ON but OPFLOW_BUILD_BENCHMARKS is OFF (the default), this block still adds the benchmarks, but Google Benchmark is now only added in external/CMakeLists.txt under if(OPFLOW_BUILD_BENCHMARKS). In that configuration benchmark::benchmark is never defined, so benchmark/CMakeLists.txt fails to configure/link. Consider extending the external benchmark condition to include OPFLOW_BUILD_ALL or re-adding the subdirectory here.

Useful? React with 👍 / 👎.

endif()

Expand Down Expand Up @@ -334,10 +417,6 @@ endif()
# ----------------------------------------------------------------------------
if(OPFLOW_INSTALL)
message(STATUS "Generating install")
IF(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
SET(CMAKE_INSTALL_PREFIX "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}" CACHE PATH "" FORCE)
message(STATUS "Install prefix set to: ${CMAKE_INSTALL_PREFIX}")
ENDIF(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
set(project_config_in "${CMAKE_CURRENT_LIST_DIR}/cmake/opflowConfig.cmake.in")
set(project_config_out "${CMAKE_CURRENT_BINARY_DIR}/opflowConfig.cmake")
set(version_config_file "${CMAKE_CURRENT_BINARY_DIR}/opflowConfigVersion.cmake")
Expand Down
51 changes: 50 additions & 1 deletion cmake/HYPREConfig.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,54 @@

macro(CONFIG_AND_INSTALL_HYPRE)
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/hypre-build)

# HYPRE uses find_package(OpenMP). With Clang, CMake may default to libomp,
# which might not be available on the system. Provide a libgomp fallback.
set(_opflow_openmp_cache_args "")
if(OPFLOW_WITH_OPENMP AND CMAKE_C_COMPILER_ID MATCHES "Clang")
# Prefer libgomp on Linux environments without libomp.
find_library(_opflow_openmp_runtime_lib NAMES gomp)
if(NOT _opflow_openmp_runtime_lib)
find_library(_opflow_openmp_runtime_lib NAMES gomp
PATHS
/usr/lib/gcc/x86_64-linux-gnu/14
/usr/lib/gcc/x86_64-linux-gnu/13)
endif()
if(_opflow_openmp_runtime_lib)
set(_opflow_openmp_runtime "libgomp")
set(_opflow_openmp_lib_name "gomp")
set(_opflow_openmp_lib_var "OpenMP_gomp_LIBRARY")
else()
find_library(_opflow_openmp_runtime_lib NAMES omp)
set(_opflow_openmp_runtime "libomp")
set(_opflow_openmp_lib_name "omp")
set(_opflow_openmp_lib_var "OpenMP_omp_LIBRARY")
endif()

set(_opflow_openmp_include_dir "")
if(EXISTS "/usr/lib/gcc/x86_64-linux-gnu/14/include/omp.h")
set(_opflow_openmp_include_dir "/usr/lib/gcc/x86_64-linux-gnu/14/include")
elseif(EXISTS "/usr/lib/gcc/x86_64-linux-gnu/13/include/omp.h")
set(_opflow_openmp_include_dir "/usr/lib/gcc/x86_64-linux-gnu/13/include")
endif()
if(_opflow_openmp_include_dir)
# Match top-level OpenMP handling: make omp.h discoverable without
# overriding Clang's own headers.
set(_opflow_openmp_include_arg "-idirafter ${_opflow_openmp_include_dir}")
else()
set(_opflow_openmp_include_arg "")
endif()

list(APPEND _opflow_openmp_cache_args
"-DOpenMP_C_FLAGS=-fopenmp=${_opflow_openmp_runtime} ${_opflow_openmp_include_arg} -Wno-unused-command-line-argument -Wno-deprecated-pragma"
"-DOpenMP_C_LIB_NAMES=${_opflow_openmp_lib_name}"
"-DOpenMP_CXX_FLAGS=-fopenmp=${_opflow_openmp_runtime} ${_opflow_openmp_include_arg} -Wno-unused-command-line-argument"
"-DOpenMP_CXX_LIB_NAMES=${_opflow_openmp_lib_name}"
)
if(_opflow_openmp_runtime_lib)
list(APPEND _opflow_openmp_cache_args "-D${_opflow_openmp_lib_var}=${_opflow_openmp_runtime_lib}")
endif()
endif()
string(JOIN " " HYPRE_OPTIONS
"-DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}"
"-DHYPRE_BUILD_TYPE=${CMAKE_BUILD_TYPE}"
Expand All @@ -35,6 +83,7 @@ macro(CONFIG_AND_INSTALL_HYPRE)
-DHYPRE_ENABLE_OPENMP=${OPFLOW_WITH_OPENMP}
-DHYPRE_ENABLE_MPI=${OPFLOW_WITH_MPI}
-DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX}
${_opflow_openmp_cache_args}
${CMAKE_CURRENT_LIST_DIR}/../external/hypre/src
RESULT_VARIABLE _result
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/hypre-build)
Expand All @@ -56,4 +105,4 @@ macro(CONFIG_AND_INSTALL_HYPRE)
message(FATAL_ERROR "Install step for HYPRE failed: ${_result}")
endif ()

endmacro()
endmacro()
Loading
Loading