From e6e992dc7921c5f8145dd72739a266fb1959185a Mon Sep 17 00:00:00 2001 From: Spencer Bryngelson Date: Wed, 1 Apr 2026 00:29:05 -0400 Subject: [PATCH 1/2] Fix nvfortran two-pass IPO causing full rebuild on every build --- CMakeLists.txt | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2b0cbabddc..a6774349ec 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -495,7 +495,17 @@ function(MFC_SETUP_TARGET) # Here we need to split into "library" and "executable" to perform IPO on the NVIDIA compiler. # A little hacky, but it *is* an edge-case for *one* compiler. if (NVHPC_USE_TWO_PASS_IPO AND NOT(MFC_OpenMP AND ARGS_OpenMP)) + # nvfortran -Mextract does not produce .o files, only inline library + # data. An OBJECT library with -Mextract causes CMake to rebuild + # everything on every build because the expected .o outputs never + # exist. We use a wrapper script as RULE_LAUNCH_COMPILE that runs + # the compiler and then touches the expected .o output file. + set(_ipo_wrapper "${CMAKE_BINARY_DIR}/${ARGS_TARGET}_extract_wrapper.sh") + file(WRITE "${_ipo_wrapper}" "#!/bin/sh\n\"$@\"\nfor arg; do :; done\ntouch \"$arg\"\n") + file(CHMOD "${_ipo_wrapper}" PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE) add_library(${ARGS_TARGET}_lib OBJECT ${ARGS_SOURCES}) + set_target_properties(${ARGS_TARGET}_lib PROPERTIES + RULE_LAUNCH_COMPILE "${_ipo_wrapper}") target_compile_options(${ARGS_TARGET}_lib PRIVATE $<$:-Mextract=lib:${ARGS_TARGET}_lib> $<$:-Minline> From 220cff85e702825e23ce765f3d94c07fcb13b62f Mon Sep 17 00:00:00 2001 From: Spencer Bryngelson Date: Wed, 1 Apr 2026 07:27:54 -0400 Subject: [PATCH 2/2] Harden IPO wrapper: propagate exit status and parse -o flag --- CMakeLists.txt | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a6774349ec..4ef43b0bf9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -501,7 +501,22 @@ function(MFC_SETUP_TARGET) # exist. We use a wrapper script as RULE_LAUNCH_COMPILE that runs # the compiler and then touches the expected .o output file. set(_ipo_wrapper "${CMAKE_BINARY_DIR}/${ARGS_TARGET}_extract_wrapper.sh") - file(WRITE "${_ipo_wrapper}" "#!/bin/sh\n\"$@\"\nfor arg; do :; done\ntouch \"$arg\"\n") + file(WRITE "${_ipo_wrapper}" [=[#!/bin/sh +# Find the -o argument (the object file CMake expects) +out= +prev= +for arg do + if [ "$prev" = "-o" ]; then out="$arg"; break; fi + prev="$arg" +done +# Run the compiler; propagate its exit status on failure +"$@" +status=$? +[ "$status" -eq 0 ] || exit "$status" +# Touch the .o so CMake's dependency tracking sees it +[ -n "$out" ] && touch "$out" +exit 0 +]=]) file(CHMOD "${_ipo_wrapper}" PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE) add_library(${ARGS_TARGET}_lib OBJECT ${ARGS_SOURCES}) set_target_properties(${ARGS_TARGET}_lib PROPERTIES