diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index d56a7b9..c70ada2 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -31,4 +31,4 @@ jobs: run: | cmake --preset debug-gcc cmake --build --preset debug-gcc --parallel - ctest --test-dir build/debug --output-on-failure -V + ctest --test-dir ../build-shumlib-debug-gcc --output-on-failure -V diff --git a/.gitignore b/.gitignore index 815c880..c86f647 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,8 @@ _build/ build/ +Testing/ + # Virtual environment .venv/ uv.lock diff --git a/CMakeLists.txt b/CMakeLists.txt index 4b9588d..736dbaa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -110,3 +110,47 @@ if(BUILD_TESTS) ENVIRONMENT SHUM_TMPDIR=/tmp) endif() + +# Generate legacy compatibility header for wgdos version API. +configure_file( + ${CMAKE_CURRENT_SOURCE_DIR}/common/src/c_shum_wgdos_packing_version.h.in + ${CMAKE_CURRENT_BINARY_DIR}/c_shum_wgdos_packing_version.h + @ONLY +) +# Generate legacy compatibility header for data conversion version API. +configure_file( + ${CMAKE_CURRENT_SOURCE_DIR}/common/src/c_shum_data_conv_version.h.in + ${CMAKE_CURRENT_BINARY_DIR}/c_shum_data_conv_version.h + @ONLY +) + +# Install additional headers expected by downstream users. +install(FILES + ${CMAKE_CURRENT_SOURCE_DIR}/common/src/shumlib_version.h + ${CMAKE_CURRENT_BINARY_DIR}/c_shum_wgdos_packing_version.h + ${CMAKE_CURRENT_BINARY_DIR}/c_shum_data_conv_version.h + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} +) + +# Install standalone sub-libraries requested by packaging. +install(TARGETS + shum_constants + shum_string_conv + shum_wgdos_packing + shum_byteswap + shum_spiral_search + shum_data_conv + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} +) + +# Create install prefix symlink: lib -> lib64 (when lib64 exists). +# Variables are escaped (\$) so they evaluate at install time, not configure time. +install(CODE +"if(EXISTS \"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/lib64\" + AND NOT EXISTS \"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/lib\") + execute_process(COMMAND \"${CMAKE_COMMAND}\" -E create_symlink + lib64 \"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/lib\") +endif()" +) diff --git a/CMakePresets.json b/CMakePresets.json index fe7e172..0b81cdc 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -1,11 +1,18 @@ { - "version": 2, + "version": 3, + "cmakeMinimumRequired": { + "major": 3, + "minor": 21, + "patch": 0 + }, "configurePresets": [ { - "name": "debug", - "displayName": "Debug", + "name": "base-debug", + "displayName": "Base Debug Configuration", + "description": "Abstract base preset for debug builds", + "hidden": true, "generator": "Unix Makefiles", - "binaryDir": "build/debug", + "binaryDir": "${sourceParentDir}/build-${sourceDirName}-${presetName}", "cacheVariables": { "CMAKE_BUILD_TYPE": "Debug" } @@ -13,21 +20,19 @@ { "name": "debug-gcc", "displayName": "GCC Debug", - "inherits": "debug", + "inherits": "base-debug", "cacheVariables": { - "CMAKE_BUILD_TYPE": "Debug", "CMAKE_C_COMPILER": "gcc", "CMAKE_Fortran_COMPILER": "gfortran", - "CMAKE_C_FLAGS_INIT": "-g -Wall -Wextra -Werror -Wformat=2 -Winit-self -Wfloat-equal -Wpointer-arith -Wbad-function-cast -Wcast-qual -Wcast-align -Wconversion -Wlogical-op -Wstrict-prototypes -Wmissing-declarations -Wredundant-decls -Wnested-externs -Woverlength-strings -Wshadow -Wall -Wextra -Wpedantic -fdiagnostics-show-option", + "CMAKE_C_FLAGS_INIT": "-g -Wall -Wextra -Werror -Wformat=2 -Winit-self -Wfloat-equal -Wpointer-arith -Wbad-function-cast -Wcast-qual -Wcast-align -Wconversion -Wlogical-op -Wstrict-prototypes -Wmissing-declarations -Wredundant-decls -Wnested-externs -Woverlength-strings -Wshadow -Wpedantic -fdiagnostics-show-option", "CMAKE_Fortran_FLAGS_INIT": "-g -std=f2018 -pedantic -pedantic-errors -fno-range-check -Wall -Wextra -Werror -Wno-compare-reals -Wconversion -Wno-unused-dummy-argument -Wno-c-binding-type -fdiagnostics-show-option" } }, { "name": "debug-cce", "displayName": "Cray CCE Debug", - "inherits": "debug", + "inherits": "base-debug", "cacheVariables": { - "CMAKE_BUILD_TYPE": "Debug", "CMAKE_C_COMPILER": "cc", "CMAKE_Fortran_COMPILER": "ftn", "CMAKE_C_FLAGS_INIT": "-g -Weverything -Wno-vla -Wno-padded -Wno-missing-noreturn -Wno-declaration-after-statement -Werror -pedantic -pedantic-errors -fdiagnostics-show-option -DSHUM_X86_INTRINSIC", @@ -37,9 +42,19 @@ { "name": "debug-nvhpc", "displayName": "nvidia HPC Debug", - "inherits": "debug", + "inherits": "base-debug", + "cacheVariables": { + "CMAKE_C_COMPILER": "nvc", + "CMAKE_Fortran_COMPILER": "nvfortran", + "CMAKE_C_FLAGS_INIT": "-g -Minform=inform", + "CMAKE_Fortran_FLAGS_INIT": "-g -Minform=inform" + } + }, + { + "name": "debug-nvhpcc", + "displayName": "nvidia HPC Cuda Debug", + "inherits": "base-debug", "cacheVariables": { - "CMAKE_BUILD_TYPE": "Debug", "CMAKE_C_COMPILER": "nvcc", "CMAKE_Fortran_COMPILER": "nvfortran", "CMAKE_C_FLAGS_INIT": "-g", @@ -48,23 +63,72 @@ } ], "buildPresets": [ + { + "name": "base-build", + "hidden": true, + "jobs": 0 + }, { "name": "debug-gcc", "displayName": "GCC Debug Build", - "configurePreset": "debug", - "configuration": "Debug" + "inherits": "base-build", + "configurePreset": "debug-gcc" }, { "name": "debug-cce", "displayName": "Cray CCE Debug Build", - "configurePreset": "debug", - "configuration": "Debug" + "inherits": "base-build", + "configurePreset": "debug-cce" }, { "name": "debug-nvhpc", "displayName": "nvidia HPC Debug Build", - "configurePreset": "debug", - "configuration": "Debug" + "inherits": "base-build", + "configurePreset": "debug-nvhpc" + }, + { + "name": "debug-nvhpcc", + "displayName": "nvidia HPC Cuda Debug Build", + "inherits": "base-build", + "configurePreset": "debug-nvhpcc" + } + ], + "testPresets": [ + { + "name": "base-test", + "hidden": true, + "execution": { + "stopOnFailure": false, + "jobs": 0, + "noTestsAction": "error" + }, + "output": { + "outputOnFailure": true + } + }, + { + "name": "debug-gcc", + "displayName": "GCC Debug Tests", + "inherits": "base-test", + "configurePreset": "debug-gcc" + }, + { + "name": "debug-cce", + "displayName": "Cray CCE Debug Tests", + "inherits": "base-test", + "configurePreset": "debug-cce" + }, + { + "name": "debug-nvhpc", + "displayName": "nvidia HPC Debug Tests", + "inherits": "base-test", + "configurePreset": "debug-nvhpc" + }, + { + "name": "debug-nvhpcc", + "displayName": "nvidia HPC Cuda Debug Tests", + "inherits": "base-test", + "configurePreset": "debug-nvhpcc" } ] } diff --git a/cmake/ShumOptions.cmake b/cmake/ShumOptions.cmake index c6a931b..cc51e6b 100644 --- a/cmake/ShumOptions.cmake +++ b/cmake/ShumOptions.cmake @@ -41,7 +41,44 @@ endif() if(BUILD_OPENMP) # FIXME: this probably needs newer version of cmake on the Cray - find_package(OpenMP 3.0 REQUIRED) + # UPDATE: Doesn't work with cmake 3.31.9 + # A little hack to check supported OMP spec on Cray + # --- + if(CMAKE_Fortran_COMPILER_ID MATCHES "Cray" OR CMAKE_C_COMPILER_ID MATCHES "Cray") + # Cray's OpenMP is compiler-managed (no separate runtime library). + # CMake's FindOpenMP fails on Cray because it can't resolve LIB_NAMES. + # Verify the minimum required OpenMP spec date manually instead. + # See OpenMP Spec dates + include(CheckFortranSourceRuns) + set(CMAKE_REQUIRED_FLAGS "-homp") + check_fortran_source_runs( + "program check\n if (_OPENMP < 200805) stop 1\nend program\n" + CRAY_OMP_MEETS_MINIMUM SRC_EXT F90 + ) + unset(CMAKE_REQUIRED_FLAGS) + if(NOT CRAY_OMP_MEETS_MINIMUM) + message(FATAL_ERROR "shumlib requires OpenMP >= 3.0 (date 200805); Cray compiler does not meet this.") + endif() + + # Create the standard imported targets so downstream consumers work normally + if(NOT TARGET OpenMP::OpenMP_Fortran) + add_library(OpenMP::OpenMP_Fortran INTERFACE IMPORTED) + set_target_properties(OpenMP::OpenMP_Fortran PROPERTIES + INTERFACE_COMPILE_OPTIONS "-homp" + INTERFACE_LINK_OPTIONS "-homp") + endif() + if(NOT TARGET OpenMP::OpenMP_C) + add_library(OpenMP::OpenMP_C INTERFACE IMPORTED) + set_target_properties(OpenMP::OpenMP_C PROPERTIES + INTERFACE_COMPILE_OPTIONS "-fopenmp" + INTERFACE_LINK_OPTIONS "-fopenmp") + endif() + set(OpenMP_FOUND TRUE) + set(OpenMP_Fortran_FOUND TRUE) + set(OpenMP_C_FOUND TRUE) + else() + find_package(OpenMP 3.0 REQUIRED) + endif() if(BUILD_FTHREADS) message(VERBOSE "Using shumlib with Fortran OpenMP threading") diff --git a/common/src/c_shum_data_conv_version.h.in b/common/src/c_shum_data_conv_version.h.in new file mode 100644 index 0000000..cd3ded2 --- /dev/null +++ b/common/src/c_shum_data_conv_version.h.in @@ -0,0 +1,14 @@ +#ifndef C_SHUM_DATA_CONV_VERSION_H +#define C_SHUM_DATA_CONV_VERSION_H + +#if !defined(SHUMLIB_VERSION) +#define SHUMLIB_VERSION @SHUMLIB_VERSION@ +#endif + +#define SHUMLIB_CMAKE 1 +#include "shumlib_version.h" +#undef SHUMLIB_CMAKE + +#define get_shum_data_conv_version GET_SHUMLIB_VERSION + +#endif diff --git a/common/src/c_shum_wgdos_packing_version.h.in b/common/src/c_shum_wgdos_packing_version.h.in new file mode 100644 index 0000000..6e328b3 --- /dev/null +++ b/common/src/c_shum_wgdos_packing_version.h.in @@ -0,0 +1,20 @@ +#ifndef C_SHUM_WGDOS_PACKING_VERSION_H +#define C_SHUM_WGDOS_PACKING_VERSION_H + +/* Ensure downstream consumers do not need to define SHUMLIB_VERSION */ +#if !defined(SHUMLIB_VERSION) +#define SHUMLIB_VERSION @SHUMLIB_VERSION@ +#endif + +/* + * Reuse the CMake-mode API in shumlib_version.h and expose the legacy + * function-like name expected by external applications. + */ +#define SHUMLIB_CMAKE 1 +#include "shumlib_version.h" +#undef SHUMLIB_CMAKE + +/* Legacy compatibility symbol name */ +#define get_shum_wgdos_packing_version GET_SHUMLIB_VERSION + +#endif diff --git a/shum_byteswap/src/CMakeLists.txt b/shum_byteswap/src/CMakeLists.txt index 3e2df18..9ab82ee 100644 --- a/shum_byteswap/src/CMakeLists.txt +++ b/shum_byteswap/src/CMakeLists.txt @@ -15,3 +15,23 @@ target_sources(shum FILES c_shum_byteswap.h c_shum_byteswap_opt.h) + +add_library(shum_byteswap) +target_sources(shum_byteswap + PRIVATE + c_shum_byteswap.c + f_shum_byteswap.f90 + ${PROJECT_SOURCE_DIR}/common/src/shumlib_version.c + ${PROJECT_BINARY_DIR}/f_shum_byteswap_version_mod.f90) + +target_compile_definitions(shum_byteswap PUBLIC ${SHUM_DEFINES}) + +set_target_properties(shum_byteswap PROPERTIES + Fortran_MODULE_DIRECTORY ${PROJECT_BINARY_DIR}/modules_shum_byteswap) + +target_include_directories(shum_byteswap + PUBLIC + ${PROJECT_BINARY_DIR}/modules_shum_byteswap + ${PROJECT_SOURCE_DIR}/common/src) + +target_link_libraries(shum_byteswap PUBLIC shum_string_conv) diff --git a/shum_constants/src/CMakeLists.txt b/shum_constants/src/CMakeLists.txt index d0356bc..4d63e9b 100644 --- a/shum_constants/src/CMakeLists.txt +++ b/shum_constants/src/CMakeLists.txt @@ -11,3 +11,25 @@ target_sources(shum f_shum_ztables.f90 f_shum_rel_mol_mass_mod.f90 f_shum_water_constants_mod.f90) + +add_library(shum_constants) +target_sources(shum_constants + PRIVATE + f_shum_chemistry_constants_mod.f90 + f_shum_conversions_mod.f90 + f_shum_planet_earth_constants_mod.f90 + f_shum_ztables.f90 + f_shum_rel_mol_mass_mod.f90 + f_shum_water_constants_mod.f90 + ${PROJECT_SOURCE_DIR}/common/src/shumlib_version.c + ${PROJECT_BINARY_DIR}/f_shum_constants_version_mod.f90) + +target_compile_definitions(shum_constants PUBLIC ${SHUM_DEFINES}) + +set_target_properties(shum_constants PROPERTIES + Fortran_MODULE_DIRECTORY ${PROJECT_BINARY_DIR}/modules_shum_constants) + +target_include_directories(shum_constants + PUBLIC + ${PROJECT_BINARY_DIR}/modules_shum_constants + ${PROJECT_SOURCE_DIR}/common/src) diff --git a/shum_data_conv/src/CMakeLists.txt b/shum_data_conv/src/CMakeLists.txt index ca3eee1..2525611 100644 --- a/shum_data_conv/src/CMakeLists.txt +++ b/shum_data_conv/src/CMakeLists.txt @@ -14,3 +14,23 @@ target_sources(shum TYPE HEADERS FILES c_shum_data_conv.h) + +add_library(shum_data_conv) +target_sources(shum_data_conv + PRIVATE + c_shum_data_conv.c + f_shum_data_conv.f90 + ${PROJECT_SOURCE_DIR}/common/src/shumlib_version.c + ${PROJECT_BINARY_DIR}/f_shum_data_conv_version_mod.f90) + +target_compile_definitions(shum_data_conv PUBLIC ${SHUM_DEFINES}) + +set_target_properties(shum_data_conv PROPERTIES + Fortran_MODULE_DIRECTORY ${PROJECT_BINARY_DIR}/modules_shum_data_conv) + +target_include_directories(shum_data_conv + PUBLIC + ${PROJECT_BINARY_DIR}/modules_shum_data_conv + ${PROJECT_SOURCE_DIR}/common/src) + +target_link_libraries(shum_data_conv PUBLIC shum_string_conv) diff --git a/shum_spiral_search/src/CMakeLists.txt b/shum_spiral_search/src/CMakeLists.txt index e6b01c2..cb75dbb 100644 --- a/shum_spiral_search/src/CMakeLists.txt +++ b/shum_spiral_search/src/CMakeLists.txt @@ -14,3 +14,23 @@ target_sources(shum TYPE HEADERS FILES c_shum_spiral_search.h) + +add_library(shum_spiral_search) +target_sources(shum_spiral_search + PRIVATE + f_shum_spiral_search.f90 + c_shum_spiral_search.f90 + ${PROJECT_SOURCE_DIR}/common/src/shumlib_version.c + ${PROJECT_BINARY_DIR}/f_shum_spiral_search_version_mod.f90) + +target_compile_definitions(shum_spiral_search PUBLIC ${SHUM_DEFINES}) + +set_target_properties(shum_spiral_search PROPERTIES + Fortran_MODULE_DIRECTORY ${PROJECT_BINARY_DIR}/modules_shum_spiral_search) + +target_include_directories(shum_spiral_search + PUBLIC + ${PROJECT_BINARY_DIR}/modules_shum_spiral_search + ${PROJECT_SOURCE_DIR}/common/src) + +target_link_libraries(shum_spiral_search PUBLIC shum_constants shum_string_conv) diff --git a/shum_string_conv/src/CMakeLists.txt b/shum_string_conv/src/CMakeLists.txt index 1253803..9338d25 100644 --- a/shum_string_conv/src/CMakeLists.txt +++ b/shum_string_conv/src/CMakeLists.txt @@ -6,3 +6,20 @@ target_sources(shum PRIVATE f_shum_string_conv.f90) + +add_library(shum_string_conv) +target_sources(shum_string_conv + PRIVATE + f_shum_string_conv.f90 + ${PROJECT_SOURCE_DIR}/common/src/shumlib_version.c + ${PROJECT_BINARY_DIR}/f_shum_string_conv_version_mod.f90) + +target_compile_definitions(shum_string_conv PUBLIC ${SHUM_DEFINES}) + +set_target_properties(shum_string_conv PROPERTIES + Fortran_MODULE_DIRECTORY ${PROJECT_BINARY_DIR}/modules_shum_string_conv) + +target_include_directories(shum_string_conv + PUBLIC + ${PROJECT_BINARY_DIR}/modules_shum_string_conv + ${PROJECT_SOURCE_DIR}/common/src) diff --git a/shum_wgdos_packing/src/CMakeLists.txt b/shum_wgdos_packing/src/CMakeLists.txt index b8f6743..5f8e1c0 100644 --- a/shum_wgdos_packing/src/CMakeLists.txt +++ b/shum_wgdos_packing/src/CMakeLists.txt @@ -14,3 +14,23 @@ target_sources(shum TYPE HEADERS FILES c_shum_wgdos_packing.h) + +add_library(shum_wgdos_packing) +target_sources(shum_wgdos_packing + PRIVATE + c_shum_wgdos_packing.f90 + f_shum_wgdos_packing.f90 + ${PROJECT_SOURCE_DIR}/common/src/shumlib_version.c + ${PROJECT_BINARY_DIR}/f_shum_wgdos_packing_version_mod.f90) + +target_compile_definitions(shum_wgdos_packing PUBLIC ${SHUM_DEFINES}) + +set_target_properties(shum_wgdos_packing PROPERTIES + Fortran_MODULE_DIRECTORY ${PROJECT_BINARY_DIR}/modules_shum_wgdos_packing) + +target_include_directories(shum_wgdos_packing + PUBLIC + ${PROJECT_BINARY_DIR}/modules_shum_wgdos_packing + ${PROJECT_SOURCE_DIR}/common/src) + +target_link_libraries(shum_wgdos_packing PUBLIC shum_constants shum_string_conv)