Skip to content

Shared library builds with Intel ifx hide the entire Fortran API since 1.15.0 #242

Closed

Description

@xylar

Since 1.15.0, configure.ac checks whether the Fortran compiler accepts -fvisibility=hidden and, if so, adds it to F77_VISIBILITY_FLAGS/F90_VISIBILITY_FLAGS (used in src/binding/f77, src/binding/f90 and src/libs). With Intel oneAPI (icx/icpx/ifx) and --enable-shared --enable-fortran, make then fails in benchmarks/FLASH-IO with undefined reference to nfmpi_* for every F77 API call, as noted in doc/README.CRAY.md. We hit this in Spack's CI when adding 1.15.0/1.15.1 (e.g. https://gitlab.spack.io/spack/spack-packages/-/jobs/24411562).

Cause. gfortran accepts -fvisibility=hidden but ignores it for Fortran procedures, so GNU builds are unaffected. ifx honors it and, unlike GCC/Clang for C, also marks undefined references in its objects as STV_HIDDEN. The F90 module pnetcdf.f90 references every nfmpi_* wrapper, so when libpnetcdf.so is linked the linker applies the most restrictive visibility and demotes the C-defined wrappers in allf.o (which correctly carry visibility("default")) to hidden. All 28 symbols reported undefined in our log are referenced from Fortran-compiled objects; the ld behavior is easy to reproduce with a two-file C example using a hidden extern declaration.

Suggested fix. Drop -fvisibility=hidden for Fortran entirely: remove the Fortran AX_CHECK_COMPILE_FLAG block in configure.ac and the @F77_VISIBILITY_FLAGS@/@F90_VISIBILITY_FLAGS@ uses in the three Makefile.am files. The Fortran sources contain nothing but the public API (nfmpi_strerror, nfmpi_strerrno, nfmpi_inq_libvers and the nf90mpi module), so there is nothing to hide, and hiding internal symbols is already handled by the C/C++ flags.

The --disable-shared workaround in README.CRAY.md is not an option for Spack (or other package managers), which build shared libraries by default. In Spack we are working around it by passing ax_cv_check_fcflags___fvisibility_hidden=no to configure for 1.15+, which restores exported nfmpi_* symbols without touching the C/C++ visibility settings.

Activity

  1. xylar commented on Sep 22, 2026

    @xylar
    Author
  2. wkliao commented on Sep 22, 2026

    @wkliao
    Member

    Thanks for the suggestions. I will give them a try.
    However, I wonder if this should be considered as a problem
    that Intel compiler developers need to resolve, or I am just using
    those flags incorrectly.

  3. xylar commented on Sep 23, 2026

    @xylar
    Author

    @wkliao, that's a good question. I'd say it's a bit of both, and it's worth taking care of the PnetCDF of the issue.

    Intel's compiler does behave differently from GNU in this situation. Even if Intel changed it, though, hiding still isn't right for the Fortran sources. Some of the public API — nfmpi_strerror, nfmpi_strerrno, nfmpi_inq_libvers, and the whole nf90mpi module — is written in Fortran, and Fortran gives you no way to mark those as "export anyway", the way the C code does. So on any compiler that honors the flag, they vanish from the shared library.

    And dropping the flag for Fortran shouldn't have any negative consequences. gfortran ignores it for Fortran procedures, so it has never actually hidden anything — it only looked harmless because the compiler you tested with quietly did nothing with it.

  4. wkliao commented on Sep 23, 2026

    @wkliao
    Member

    Thanks. Your suggested fix solved a problem puzzling me for 3 months, and
    your explanation of the Fortran part makes sense to me.
    I will create a PR with the suggested fix.

    One question. I used the Intel oneAPI based MPI compilers to build PnetCDF 1.15.0
    on Aurora at ALCF back in June, but did not encounter a problem (see doc/ALCF.md).
    However, I now seeing those Fortran errors today. The version of Intel oneAPI compier
    remains the same. Do you know what else can also trigger that Fortran linking error?

    Here is the version of Intel oneAPI compilers.

      % mpicc --version
      Intel(R) oneAPI DPC++/C++ Compiler 2025.3.2 (2025.3.2.20260112)
      Target: x86_64-unknown-linux-gnu
    
  5. xylar commented on Sep 23, 2026

    @xylar
    Author

    @wkliao, honestly, no, I don't. I encountered the error in spack's CI, not in my own local testing. I can see if I can find anything out myself on Aurora. I'll follow up.

  6. xylar commented on Sep 23, 2026

    @xylar
    Author

    @wkliao, short answer: I don't think anything else is involved. The compiler is the same, but I believe the PnetCDF source you built on Aurora in June was older than the change that causes the error.

    What I tried on Aurora

    Today I built the 1.15.0 release tarball on an Aurora login node with the compiler you listed (ifx 2025.3.2 20260112) and the configure command from doc/ALCF.md. make fails in benchmarks/FLASH-IO with the same nfmpi_* undefined references. When I turn off only the Fortran flag (ax_cv_check_fcflags___fvisibility_hidden=no), everything builds. So the Fortran -fvisibility=hidden flag is the only trigger I could find. Building with --disable-shared, --disable-fortran or gfortran also avoids the error, in case one of those was different in your June build.

    When the flag was added

    The Fortran check was added on June 18 in 632f437, a commit titled "pnetcdf_version - add compiler vendor info", so it's easy to miss. On June 21, 2a357e9 moved it into F77_VISIBILITY_FLAGS and F90_VISIBILITY_FLAGS. You were already building with oneAPI earlier in June (your libtool fix in 992fad8 is from June 8). Your June 10 Perlmutter note mentions only the MPL_trfree problem, so make was still working with the Intel compilers then. My guess is that the Aurora build you remember was done before June 18, even though ALCF.md was written on June 24.

    If you still have that June installation, you can check this. nm -D libpnetcdf.so | grep -c ncmpio_ prints a number above zero if the library predates all of the visibility changes, because the internal ncmpio_* functions were still exported then.

    How much the flag hides

    With ifx, the flag hides more than the benchmarks need. Here are the two builds of libpnetcdf.so side by side:

    Exported from libpnetcdf.so Fortran flag on Fortran flag off
    nfmpi_* functions 122 437
    nf90mpi module procedures 0 1109

    Internal C functions such as ncmpio_create stay hidden in both builds, so dropping the Fortran flag keeps the C/C++ visibility work intact.

    Written by Claude (Anthropic's AI assistant) on behalf of @xylar.

  7. added a commit that references this issue on Sep 27, 2026
  8. wkliao commented on Sep 27, 2026

    @wkliao
    Member

    Hi @xylar
    PR #244 has been created based on your suggestions and merged into the master branch.
    Many thanks !

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions