From 17fc106322f2abc3e2bca76a8121edc3663a8db9 Mon Sep 17 00:00:00 2001 From: Robert Jacob Date: Fri, 21 Aug 2026 00:13:11 -0500 Subject: [PATCH] Fix e3sm.exe link order so PnetCDF comes after SCORPIO's piof/pioc Linking the netcdf interface target (which bundles libpnetcdf.a) directly onto e3sm.exe pinned it ahead of piof/pioc on the static link line, since CMake collapses repeated references to the same target to one position. GNU ld resolves static archives in a single pass, so piof/pioc's calls into PnetCDF (ncmpi_*) went unresolved, failing the link. Only pull netcdf's include dirs onto the cpl target directly, and let its link libraries reach the executable exclusively through csm_share -> spio, where PnetCDF is already ordered after piof/pioc. Co-Authored-By: Claude Sonnet 5 --- components/cmake/build_model.cmake | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/components/cmake/build_model.cmake b/components/cmake/build_model.cmake index 18d5ab728bdd..d9c489640ccb 100644 --- a/components/cmake/build_model.cmake +++ b/components/cmake/build_model.cmake @@ -263,19 +263,31 @@ macro(build_model COMP_CLASS COMP_NAME) add_executable(${TARGET_NAME}) target_sources(${TARGET_NAME} PRIVATE ${REAL_SOURCES}) - # driver-mct/main sources (e.g. cime_comp_mod.F90) use netcdf directly, but - # the component libraries only link netcdf PRIVATEly (via csm_share), so - # its usage requirements (e.g. include dirs for netcdf.mod) do not - # propagate up to this exe target. Find/link it explicitly here too. - find_package(NETCDF REQUIRED) - target_link_libraries(${TARGET_NAME} netcdf) - foreach(ITEM IN LISTS COMP_CLASSES) if (NOT ITEM STREQUAL "cpl") target_link_libraries(${TARGET_NAME} ${ITEM}) endif() endforeach() + # driver-mct/main sources (e.g. cime_comp_mod.F90) use netcdf directly, but + # the component libraries only link netcdf PRIVATEly (via csm_share), so + # its usage requirements (e.g. include dirs for netcdf.mod) do not + # propagate up to this exe target. Pull in just the include dirs here. + # + # Deliberately NOT using target_link_libraries(${TARGET_NAME} netcdf): + # CMake treats "netcdf" as a single graph node, so linking it directly to + # this executable pins its (and PnetCDF's) position to wherever it's + # first encountered, ahead of the component libraries below that also + # transitively link it via csm_share -> spio. But piof/pioc (also pulled + # in via csm_share -> spio) reference PnetCDF symbols, so libpnetcdf.a + # must come after them on the link line, or the linker drops its symbols + # before piof/pioc need them. Only requesting the include dirs avoids + # adding that extra, mis-ordering link edge, while the link libraries + # still reach this target correctly ordered via csm_share -> spio. + find_package(NETCDF REQUIRED) + get_target_property(NETCDF_INTERFACE_INCLUDE_DIRS netcdf INTERFACE_INCLUDE_DIRECTORIES) + target_include_directories(${TARGET_NAME} PRIVATE ${NETCDF_INTERFACE_INCLUDE_DIRS}) + if (USE_MOAB) target_link_libraries(${TARGET_NAME} ${MOAB_LIBRARIES}) target_include_directories(${TARGET_NAME} PRIVATE ${MOAB_INCLUDE_DIRS})