From 38ce7b2f276b344c1900f34d86729cfe48778aa0 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Fri, 7 Aug 2026 19:00:49 -0500 Subject: [PATCH 1/2] Build C++ unit tests against a static library --- CMakeLists.txt | 95 ++++++++++++++++------------- tests/cpp_unit_tests/CMakeLists.txt | 2 +- 2 files changed, 55 insertions(+), 42 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9c3e6a947d2..d874d7a9879 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -497,16 +497,27 @@ list(APPEND libopenmc_SOURCES src/external/quartic_solver.cpp src/external/Faddeeva.cc) +# Compile the OpenMC sources once so that they can be used by both the +# production library and the static library used by the C++ unit tests. +add_library(libopenmc_objects OBJECT ${libopenmc_SOURCES}) +set_target_properties(libopenmc_objects PROPERTIES POSITION_INDEPENDENT_CODE ON) + # For Visual Studio compilers if(MSVC) # Use static library (otherwise explicit symbol portings are needed) - add_library(libopenmc STATIC ${libopenmc_SOURCES}) + add_library(libopenmc STATIC) # To use the shared HDF5 libraries on Windows, the H5_BUILT_AS_DYNAMIC_LIB # compile definition must be specified. - target_compile_definitions(libopenmc PRIVATE -DH5_BUILT_AS_DYNAMIC_LIB) + target_compile_definitions(libopenmc_objects PRIVATE -DH5_BUILT_AS_DYNAMIC_LIB) else() - add_library(libopenmc SHARED ${libopenmc_SOURCES}) + add_library(libopenmc SHARED) +endif() +target_link_libraries(libopenmc PUBLIC libopenmc_objects) + +if(OPENMC_BUILD_TESTS) + add_library(libopenmc_test STATIC) + target_link_libraries(libopenmc_test PUBLIC libopenmc_objects) endif() add_library(OpenMC::libopenmc ALIAS libopenmc) @@ -516,48 +527,52 @@ if(NOT MSVC) set_target_properties(libopenmc PROPERTIES OUTPUT_NAME openmc) endif() -target_include_directories(libopenmc +target_include_directories(libopenmc_objects PUBLIC $ $ ${HDF5_INCLUDE_DIRS} ) -# Set compile flags -target_compile_options(libopenmc PRIVATE ${cxxflags}) - # Add include directory for configured version file -target_include_directories(libopenmc +target_include_directories(libopenmc_objects PUBLIC $) +# Ensure C++17 standard is used and turn off GNU extensions +target_compile_features(libopenmc_objects PUBLIC cxx_std_17) +set_target_properties(libopenmc_objects PROPERTIES CXX_EXTENSIONS OFF) + +# Set compile flags +target_compile_options(libopenmc_objects PRIVATE ${cxxflags}) + if (HDF5_IS_PARALLEL) - target_compile_definitions(libopenmc PRIVATE -DPHDF5) + target_compile_definitions(libopenmc_objects PRIVATE -DPHDF5) endif() if (OPENMC_USE_MPI) - target_compile_definitions(libopenmc PUBLIC -DOPENMC_MPI) + target_compile_definitions(libopenmc_objects PUBLIC -DOPENMC_MPI) if (OPENMC_HAVE_MPI_REDUCE_C) - target_compile_definitions(libopenmc PRIVATE -DOPENMC_HAVE_MPI_REDUCE_C) + target_compile_definitions(libopenmc_objects PRIVATE -DOPENMC_HAVE_MPI_REDUCE_C) endif() endif() # target_link_libraries treats any arguments starting with - but not -l as # linker flags. Thus, we can pass both linker flags and libraries together. -target_link_libraries(libopenmc ${ldflags} ${HDF5_LIBRARIES} ${HDF5_HL_LIBRARIES} - fmt::fmt ${CMAKE_DL_LIBS}) +target_link_libraries(libopenmc_objects PUBLIC ${ldflags} ${HDF5_LIBRARIES} + ${HDF5_HL_LIBRARIES} fmt::fmt ${CMAKE_DL_LIBS}) if(TARGET pugixml::pugixml) - target_link_libraries(libopenmc pugixml::pugixml) + target_link_libraries(libopenmc_objects PUBLIC pugixml::pugixml) else() - target_link_libraries(libopenmc pugixml) + target_link_libraries(libopenmc_objects PUBLIC pugixml) endif() if(OPENMC_USE_DAGMC) - target_compile_definitions(libopenmc PUBLIC OPENMC_DAGMC_ENABLED) - target_link_libraries(libopenmc dagmc-shared) + target_compile_definitions(libopenmc_objects PUBLIC OPENMC_DAGMC_ENABLED) + target_link_libraries(libopenmc_objects PUBLIC dagmc-shared) if(OPENMC_USE_UWUW) - target_compile_definitions(libopenmc PRIVATE OPENMC_UWUW_ENABLED) - target_link_libraries(libopenmc uwuw-shared) + target_compile_definitions(libopenmc_objects PRIVATE OPENMC_UWUW_ENABLED) + target_link_libraries(libopenmc_objects PUBLIC uwuw-shared) endif() elseif(OPENMC_USE_UWUW) set(OPENMC_USE_UWUW OFF) @@ -565,43 +580,43 @@ elseif(OPENMC_USE_UWUW) endif() if(OPENMC_USE_LIBMESH) - target_compile_definitions(libopenmc PRIVATE OPENMC_LIBMESH_ENABLED) - target_link_libraries(libopenmc PkgConfig::LIBMESH) + target_compile_definitions(libopenmc_objects PRIVATE OPENMC_LIBMESH_ENABLED) + target_link_libraries(libopenmc_objects PUBLIC PkgConfig::LIBMESH) endif() if (PNG_FOUND) - target_compile_definitions(libopenmc PRIVATE USE_LIBPNG) - target_link_libraries(libopenmc PNG::PNG) + target_compile_definitions(libopenmc_objects PRIVATE USE_LIBPNG) + target_link_libraries(libopenmc_objects PUBLIC PNG::PNG) endif() if (OPENMC_USE_OPENMP) - target_link_libraries(libopenmc OpenMP::OpenMP_CXX) + target_link_libraries(libopenmc_objects PUBLIC OpenMP::OpenMP_CXX) endif() if (OPENMC_USE_MPI) - target_link_libraries(libopenmc MPI::MPI_CXX) -endif() - -if (OPENMC_BUILD_TESTS) - # Add cpp tests directory - include(CTest) - add_subdirectory(tests/cpp_unit_tests) + target_link_libraries(libopenmc_objects PUBLIC MPI::MPI_CXX) endif() #=============================================================================== # Log build info that this executable can report later #=============================================================================== -target_compile_definitions(libopenmc PRIVATE BUILD_TYPE=${CMAKE_BUILD_TYPE}) -target_compile_definitions(libopenmc PRIVATE COMPILER_ID=${CMAKE_CXX_COMPILER_ID}) -target_compile_definitions(libopenmc PRIVATE COMPILER_VERSION=${CMAKE_CXX_COMPILER_VERSION}) +target_compile_definitions(libopenmc_objects PRIVATE BUILD_TYPE=${CMAKE_BUILD_TYPE}) +target_compile_definitions(libopenmc_objects PRIVATE COMPILER_ID=${CMAKE_CXX_COMPILER_ID}) +target_compile_definitions(libopenmc_objects PRIVATE COMPILER_VERSION=${CMAKE_CXX_COMPILER_VERSION}) if (OPENMC_ENABLE_PROFILE) - target_compile_definitions(libopenmc PRIVATE PROFILINGBUILD) + target_compile_definitions(libopenmc_objects PRIVATE PROFILINGBUILD) endif() if (OPENMC_ENABLE_COVERAGE) - target_compile_definitions(libopenmc PRIVATE COVERAGEBUILD) + target_compile_definitions(libopenmc_objects PRIVATE COVERAGEBUILD) endif() if (OPENMC_ENABLE_STRICT_FP) - target_compile_definitions(libopenmc PRIVATE OPENMC_ENABLE_STRICT_FP) + target_compile_definitions(libopenmc_objects PRIVATE OPENMC_ENABLE_STRICT_FP) +endif() + +if(OPENMC_BUILD_TESTS) + # Add cpp tests directory + include(CTest) + add_subdirectory(tests/cpp_unit_tests) endif() #=============================================================================== @@ -613,10 +628,8 @@ target_compile_options(openmc PRIVATE ${cxxflags}) target_include_directories(openmc PRIVATE ${CMAKE_BINARY_DIR}/include) target_link_libraries(openmc libopenmc) -# Ensure C++17 standard is used and turn off GNU extensions target_compile_features(openmc PUBLIC cxx_std_17) -target_compile_features(libopenmc PUBLIC cxx_std_17) -set_target_properties(openmc libopenmc PROPERTIES CXX_EXTENSIONS OFF) +set_target_properties(openmc PROPERTIES CXX_EXTENSIONS OFF) #=============================================================================== # Python package @@ -634,7 +647,7 @@ add_custom_command(TARGET libopenmc POST_BUILD include(CMakePackageConfigHelpers) set(INSTALL_CONFIGDIR ${CMAKE_INSTALL_LIBDIR}/cmake/OpenMC) -install(TARGETS openmc libopenmc +install(TARGETS openmc libopenmc libopenmc_objects EXPORT openmc-targets RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} diff --git a/tests/cpp_unit_tests/CMakeLists.txt b/tests/cpp_unit_tests/CMakeLists.txt index 9f01f0c5416..991f219f528 100644 --- a/tests/cpp_unit_tests/CMakeLists.txt +++ b/tests/cpp_unit_tests/CMakeLists.txt @@ -16,6 +16,6 @@ set(TEST_NAMES foreach(test ${TEST_NAMES}) add_executable(${test} ${test}.cpp) - target_link_libraries(${test} Catch2::Catch2WithMain libopenmc) + target_link_libraries(${test} Catch2::Catch2WithMain libopenmc_test) add_test(NAME ${test} COMMAND ${test} WORKING_DIRECTORY ${UNIT_TEST_BIN_OUTPUT_DIR}) endforeach() From 0ad4d2afc420f231ead9312496e507a2a1ad8adf Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 13 Aug 2026 11:57:35 -0500 Subject: [PATCH 2/2] Update CMakeLists.txt per @shimwell suggestion Co-authored-by: Jonathan Shimwell --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index d874d7a9879..62c2ac8a151 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -517,6 +517,7 @@ target_link_libraries(libopenmc PUBLIC libopenmc_objects) if(OPENMC_BUILD_TESTS) add_library(libopenmc_test STATIC) + set_target_properties(libopenmc_test PROPERTIES OUTPUT_NAME openmc_test) target_link_libraries(libopenmc_test PUBLIC libopenmc_objects) endif()