Skip to content

MPAS-Framework fails to build with Intel oneAPI (ifx): "number of arguments doesn't match" in mpas_dmpar.F #8573

Description

@xylar

Summary

Building MPAS standalone with the intel-cray target fails during preprocessing of components/mpas-framework/src/framework/mpas_dmpar.F when the Intel compiler is oneAPI (ifx) rather than classic ifort. On Perlmutter this started after PrgEnv-intel/8.6.0 began loading intel/2025.3, so the Cray ftn wrapper now invokes ifx (IFX) 2025.3.0 (classic ifort is gone).

Error

mpas_dmpar.F(7859): #error: number of arguments doesn't match.
mpas_dmpar.F(7896): #error: number of arguments doesn't match.
make[3]: *** [Makefile:130: mpas_dmpar.o] Error 2

Both lines are DMPAR_DEBUG_WRITE(...) calls (a debug-logging macro that is disabled by default).

Root cause

The framework uses a standard, portable cpp idiom to pass a comma-containing list as a single argument to a function-like macro:

#define COMMA ,
#define DMPAR_DEBUG_WRITE(M) !call mpas_log_write( M )
...
DMPAR_DEBUG_WRITE('    -- Starting recv: ' COMMA commListPtr % procID COMMA commListPtr % nList COMMA size(commListPtr % rbuffer) )

A conforming preprocessor collects function-like macro arguments by scanning for literal top-level commas before expanding object-like macros, so COMMA does not split the argument (it is one argument M, and COMMA expands to , afterward). ifx's built-in fpp expands COMMA too early, sees four arguments for a one-argument macro, and errors. The replacement text being a Fortran comment is irrelevant — the error fires at argument collection.

Minimal reproducer

cmatest.F:

#define COMMA ,
#define DBG(M) !call foo( M )
      subroutine bar()
      DBG('x: ' COMMA a COMMA b COMMA c )
      end subroutine
Preprocessor Result
ifx -E -fpp cmatest.F / fpp cmatest.F (oneAPI 2025.3) #error: number of arguments doesn't match
cpp -P -traditional (GNU) correct → one argument
gfortran -E -cpp correct → one argument
standard C cpp correct → one argument

Scope

The COMMA idiom is used across the framework (7 files; 24 DMPAR_DEBUG_WRITE calls in mpas_dmpar.F alone), so mpas_dmpar.F(7859/7896) are just the first sites the compiler reaches. The intel-mpi target is expected to hit the same failure on oneAPI systems.

Why it only affects the Intel targets now

src/framework/Makefile compiles .F either via $(CPP) = cpp -P -traditional when GEN_F90=true (GNU cpp, handles the idiom), or directly with $(FC) when GEN_F90=false (the compiler's built-in fpp). The intel-cray/intel-mpi targets use the default GEN_F90=false, so they rely on ifx's broken fpp. This was latent under classic ifort and surfaced when the platform switched to ifx.

Suggested fix

Build the Intel/oneAPI targets with GEN_F90=true so .F files are preprocessed by GNU cpp instead of the compiler's fpp. Verified: adding "GEN_F90 = true" to the intel-cray target's recursive $(MAKE) all invocation preprocesses mpas_dmpar.F cleanly and the generated .f90 compiles with ifx. (Longer-term, filing the fpp conformance regression with Intel and/or reworking the COMMA idiom would also address it.)

Environment

Perlmutter (NERSC), PrgEnv-intel/8.6.0, intel/2025.3, ftnifx (IFX) 2025.3.0 20251023, MPAS-Framework at ae81cdecf9.

Metadata

Metadata

Assignees

Labels

MPAS-Ocean standaloneIssues and features for standalone MPAS-Ocean code that dont impact E3SM.MPAS-frameworkConcerning the MPAS frameworkbug

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions