Skip to content

Fix e3sm.exe link order so PnetCDF comes after SCORPIO's piof/pioc - #8655

Open
rljacob wants to merge 1 commit into
masterfrom
rljacob/cmake/fix-netcdf-gce
Open

Fix e3sm.exe link order so PnetCDF comes after SCORPIO's piof/pioc#8655
rljacob wants to merge 1 commit into
masterfrom
rljacob/cmake/fix-netcdf-gce

Conversation

@rljacob

@rljacob rljacob commented Aug 21, 2026

Copy link
Copy Markdown
Member

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.


The changes introduced in #8605 broke the build on GCE. It did not affect any other GNU builds. Claude came up with this fix.

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 <noreply@anthropic.com>
@rljacob
rljacob requested review from bartgol and ndkeen August 21, 2026 05:18
@rljacob rljacob self-assigned this Aug 21, 2026
@ndkeen

ndkeen commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

Yea that's a bummer my fix for vista broke it on another actually tested machine.
I can test it

@bartgol bartgol left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Relying on order of operations always feels brittle. Maybe a more idiomatic way to do it would be to change our create_netcdf_target to create the target as IMPORTED (rather than INTERFACE). Something like

if(NOT TARGET PnetCDF::PnetCDF)
  add_library(PnetCDF::PnetCDF UNKNOWN IMPORTED)
  set_target_properties(PnetCDF::PnetCDF PROPERTIES
    IMPORTED_LOCATION "${pnetcdf_lib}"
    INTERFACE_INCLUDE_DIRECTORIES "${pnetcdf_incdir}"
  )
endif()
if(NOT TARGET NetCDF::NetCDF)
  add_library(NetCDF::NetCDF UNKNOWN IMPORTED)
  set_target_properties(NetCDF::NetCDF PROPERTIES
    IMPORTED_LOCATION "${GET_NETCDF_LIBS_RESULT}"
    INTERFACE_INCLUDE_DIRECTORIES "${netcdf_c_incdir};${netcdf_f_incdir}"
    INTERFACE_LINK_LIBRARIES "PnetCDF::PnetCDF"
  )
endif()

This will force CMake to correctly evaluate the dependency graph, since IMPORTED tgts are concrete graph nodes, while INTERFACE ones are wrappers around other stuff. Therefore, an INTERFACE tgt is simply replaced with its properties at the 1st occurrence, and downstream occurrences in the link line are removed (resulting in the error you notifced).

I am approving, since this seems to fix the issue. But I feel like we're just sweeping dust under the rug, and it will bite us back the next time our cmake files are modified a bit.

@ndkeen

ndkeen commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

OK, I tested this on Vista and it built/ran ok (simple SMS_Vmct_D.ne4pg2_oQU480.F2010.vista-gg_gnu)

I cant build with MOAB as it's not installed, but nbd for now

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants