From 597b60019bdc4dd9ebb4b09215503cbff6988a10 Mon Sep 17 00:00:00 2001 From: Sebastian Beyer Date: Sun, 3 May 2026 21:00:49 +0200 Subject: [PATCH] build: integrate CVMix via FetchContent instead of download script Replace the custom download_cvmix.sh + add_custom_command + IMPORTED-target plumbing with FetchContent_MakeAvailable. CVMix is now built as a regular CMake subproject inside the build tree (no source-tree pollution, no separate sub-cmake invocation). For builds on internet-restricted machines, point at a manually placed checkout with -DFETCHCONTENT_SOURCE_DIR_CVMIX=/path/to/CVMix-src and pass -DFETCHCONTENT_FULLY_DISCONNECTED=ON. --- .gitignore | 3 +- src/CMakeLists.txt | 81 +++++++---------------- src/cvmix_driver/download_cvmix.sh | 100 ----------------------------- 3 files changed, 24 insertions(+), 160 deletions(-) delete mode 100644 src/cvmix_driver/download_cvmix.sh diff --git a/.gitignore b/.gitignore index 4a6e7bc68..c7f681645 100644 --- a/.gitignore +++ b/.gitignore @@ -14,6 +14,5 @@ lib/*.so /work_* Makefile.in mesh_part/build -test/output_pi -src/cvmix_driver/CVMix-* +test/output_pi .claude/ diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e400cf295..8753d398e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -199,65 +199,30 @@ target_include_directories(${PROJECT_NAME} PUBLIC $) target_link_libraries(${PROJECT_NAME} PRIVATE MPI::MPI_Fortran) -# build CVMix library if CVMIX is ON -if (CVMIX) +# Pull CVMix in via FetchContent and build it as part of FESOM's build tree. +# Offline workflow: +# - point at a manually placed checkout: -DFETCHCONTENT_SOURCE_DIR_CVMIX=/path/to/CVMix-src +# - or pre-populate /_deps/cvmix-src and pass -DFETCHCONTENT_FULLY_DISCONNECTED=ON +if(CVMIX) message(STATUS "CVMIX: ${CVMIX}") - - # read CVMix install and src directories from the download script, so that there - # is only one place where they are defined - execute_process(COMMAND bash ${src_home}/cvmix_driver/download_cvmix.sh --print-src_dir - OUTPUT_VARIABLE CVMIX_DIR_src OUTPUT_STRIP_TRAILING_WHITESPACE) - execute_process(COMMAND bash ${src_home}/cvmix_driver/download_cvmix.sh --print-prefix - OUTPUT_VARIABLE CVMIX_DIR_install OUTPUT_STRIP_TRAILING_WHITESPACE) - - # set default CVMix installation path - set(CVMIX_ROOT "${src_home}/cvmix_driver/${CVMIX_DIR_install}_${CMAKE_Fortran_COMPILER_ID}") - message(STATUS "set default CVMIX_ROOT=${CVMIX_ROOT}") - - # Where library is located --> fix in download_cvmix.sh that it as always installed - # in /lib and not in /lib64 - set(CVMIX_LIB "${CVMIX_ROOT}/lib/libcvmix.a") - - # Create parent directory early so CMake does not fail on missing include paths - file(MAKE_DIRECTORY ${CVMIX_ROOT}) - file(MAKE_DIRECTORY ${CVMIX_ROOT}/include/cvmix) - - # Collect CVMix source files so that CMake knows what changes triggers a - # possible rebuild of the CVMix library - file(GLOB_RECURSE CVMIX_SOURCES - "${src_home}/cvmix_driver/${CVMIX_DIR_src}/src/*.F90" - "${src_home}/cvmix_driver/${CVMIX_DIR_src}/src/*/*.F90") - - # Add script dependency (rebuild if script changes) - set(CVMIX_DOWNLOAD "${src_home}/cvmix_driver/download_cvmix.sh") - - # Custom command: build CVMix if not yet built - add_custom_command( - OUTPUT ${CVMIX_LIB} - COMMAND bash ${src_home}/cvmix_driver/download_cvmix.sh --prefix ${CVMIX_ROOT} - WORKING_DIRECTORY ${src_home}/cvmix_driver - DEPENDS ${CVMIX_SOURCES} ${CVMIX_DOWNLOAD} # trigger rebuild if source or download script change - COMMENT "Downloading and building CVMix into ${CVMIX_ROOT}" - VERBATIM) - - # check if ${CVMIX_ROOT}/lib/libcvmix.a exist or not, only if it does not - # exist build library - add_custom_target(cvmix_autobuild DEPENDS ${CVMIX_LIB}) - - # build cvmix external libray - add_library(cvmix_external STATIC IMPORTED GLOBAL) - set_target_properties(cvmix_external PROPERTIES - IMPORTED_LOCATION ${CVMIX_LIB} - INTERFACE_INCLUDE_DIRECTORIES "${CVMIX_ROOT}/include/cvmix") - - # cvmix_autobuild is a custom target that runs your download_cvmix.sh script - # and produces libcvmix.a. cvmix_external is an imported library, meaning CMake - # doesn’t build it — it just points to an existing file (libcvmix.a). - add_dependencies(cvmix_external cvmix_autobuild) - - # Link CVMix library to fesom, build chain becomes: fesom → cvmix_external → cvmix_autobuild - target_link_libraries(${PROJECT_NAME} PRIVATE cvmix_external) - + + include(FetchContent) + set(CVMIX_BUILD_SHARED_LIBS OFF CACHE BOOL "" FORCE) + set(CVMIX_BUILD_DRIVER OFF CACHE BOOL "" FORCE) + FetchContent_Declare(cvmix + GIT_REPOSITORY https://github.com/CVMix/CVMix-src.git + GIT_TAG v1.0.0 + ) + FetchContent_MakeAvailable(cvmix) + + # CVMix's own CMakeLists exposes its module dir only via INSTALL_INTERFACE and + # writes .mod files to ${CMAKE_BINARY_DIR}/modules (top-level build dir, set + # in the subdirectory scope). Expose that path on the BUILD_INTERFACE so + # FESOM's wrapper sources in cvmix_driver/ can find the CVMix .mod files. + target_include_directories(cvmix_static INTERFACE + $) + + target_link_libraries(${PROJECT_NAME} PRIVATE cvmix_static) endif() set_target_properties(${PROJECT_NAME} PROPERTIES LINKER_LANGUAGE Fortran) diff --git a/src/cvmix_driver/download_cvmix.sh b/src/cvmix_driver/download_cvmix.sh deleted file mode 100644 index 4d126297c..000000000 --- a/src/cvmix_driver/download_cvmix.sh +++ /dev/null @@ -1,100 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -# Clone and build CVMix-src locally for FESOM2 -# Usage: -# ./get_cvmix.sh [--branch ] [--prefix ] -# Defaults: -# branch: master -# prefix: $(pwd)/CVMix-install -# Result: -# Installs CVMix to , producing: -# /lib/libcvmix.a -# /include/*.mod -# -# Then configure FESOM with CMake options: -# -DUSE_EXTERNAL_CVMIX=ON \ -# -DCVMIX_ROOT= -# or -# -DCVMIX_LIB_DIR=/lib -DCVMIX_MOD_DIR=/include -REPO_URL="https://github.com/CVMix/CVMix-src.git" -BRANCH="" #"master" -TAG="v1.0.0" -PREFIX="CVMix-install" -SRC_DIR="CVMix-src" -BUILD_DIR="CVMix-build" - -# to extract the proper src and install dir for cmake, so the are always -# synchronized with the download script -[[ "${1:-}" == "--print-prefix" ]] && { - echo "$PREFIX" - exit 0 -} -[[ "${1:-}" == "--print-src_dir" ]] && { - echo "$PREFIX" - exit 0 -} -[[ "${1:-}" == "--print-build_dir" ]] && { - echo "$PREFIX" - exit 0 -} -PREFIX=$(pwd)/${PREFIX} -SRC_DIR=$(pwd)/${SRC_DIR} -BUILD_DIR=$(pwd)/${BUILD_DIR} - - -while [[ $# -gt 0 ]]; do - case "$1" in - --branch) - BRANCH="$2"; TAG=""; shift 2;; - --tag) - TAG="$2"; BRANCH=""; shift 2;; - --prefix) - PREFIX="$2"; shift 2;; - *) echo "Unknown arg: $1"; exit 1;; - esac -done - -mkdir -p "$(dirname "$PREFIX")" - -if [[ ! -d "$SRC_DIR/.git" ]]; then - if [[ -n "$TAG" ]]; then - echo "Cloning CVMix-src at tag $TAG ..." - git clone --branch "$TAG" --depth 1 "$REPO_URL" "$SRC_DIR" - else - echo "Cloning CVMix-src at branch $BRANCH ..." - git clone --branch "$BRANCH" --depth 1 "$REPO_URL" "$SRC_DIR" - fi -else - echo "Updating existing CVMix-src ..." - - if [[ -n "$TAG" ]]; then - git -C "$SRC_DIR" fetch --tags - git -C "$SRC_DIR" checkout -q "tags/$TAG" - else - git -C "$SRC_DIR" fetch --depth 1 origin "$BRANCH" - git -C "$SRC_DIR" checkout -q "$BRANCH" - git -C "$SRC_DIR" reset --hard "origin/$BRANCH" - fi -fi - -rm -rf "$BUILD_DIR" -mkdir -p "$BUILD_DIR" - -cd "$BUILD_DIR" -cmake -DCMAKE_BUILD_TYPE=Release \ - -DCMAKE_Fortran_MODULE_DIRECTORY="$PREFIX/include" \ - -DCMAKE_INSTALL_PREFIX="$PREFIX" \ - -DCMAKE_INSTALL_LIBDIR=lib \ - "$SRC_DIR" - -cmake --build . --config Release -- -j -cmake --install . - -echo -echo "CVMix installed to: $PREFIX" -echo " lib: $PREFIX/lib" -echo " mods: $PREFIX/include" -echo -echo "Configure FESOM CMake with:" -echo " -DUSE_EXTERNAL_CVMIX=ON -DCVMIX_ROOT=$PREFIX"