Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
a02dc3b
CHANGES: remove a stray conflict marker
hzhou-muse Nov 9, 2026
a8c9c10
mpix.h: define MPIX constants for MPI ABI builds
hzhou-muse Nov 9, 2026
4795ef5
mpix.h: remove declarations of removed MPI functions
hzhou-muse Nov 9, 2026
3a85ce6
abi: make MPIX_Stream and MPIX_Grequest_class MPI ABI handles
hzhou-muse Nov 9, 2026
f824d09
abi: add MPIX functions to libmpi_abi
hzhou-muse Nov 9, 2026
1025956
binding/fortran: use MPIX callbacks on the MPI ABI
hzhou-muse Nov 9, 2026
718b452
romio: Remove dependency on legacy MPI APIS
dalcinl Sep 2, 2026
d26b6ac
binding/abi: do not export removed MPI functions from libmpi_abi
hzhou-muse Nov 9, 2026
84cbd9e
romio: allow building pvfs2 without MPI_LB and MPI_UB
hzhou-muse Nov 9, 2026
2ead529
mpi_legacy.h: map removed APIs to their replacements in the MPI ABI
hzhou-muse Nov 9, 2026
3d3fd5f
test: skip the MPI_LB and MPI_UB tests when mpi.h lacks them
hzhou-muse Nov 9, 2026
6a66a3d
mpicc: accept -mpix as an alias of -mpi-mpix
hzhou-muse Nov 9, 2026
ebf7199
errhan: do not export MPIR_Err_* functions
hzhou-muse Nov 9, 2026
9551dfa
binding/cxx: use MPIX keyval callbacks for attribute proxies
hzhou-muse Nov 9, 2026
3664420
mpicxx: link the C++ binding library
hzhou-muse Nov 9, 2026
822f981
errhan: return the result of get_file_errhand in the MPI ABI build
hzhou-muse Nov 9, 2026
8054f41
binding/abi: count threads in the communicator size of a threadcomm
hzhou-muse Nov 10, 2026
724876d
test: run the impls/mpich tests on the MPICH MPI ABI
hzhou-muse Nov 10, 2026
29d4b0c
include: include mpi_proto.h with quotes
hzhou-muse Nov 11, 2026
e0a0bde
doc: add a design page for mpi.h and describe the removed APIs
hzhou-muse Nov 9, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion CHANGES
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
===============================================================================
Changes in 5.1
===============================================================================
<<<<<<< HEAD
# Removed MPID collective interfaces. Binding layer call MPIR_Xxx_impl instead of
MPIR_Xxx. Use a single json config file. Generate json parsing from
coll_algorithms.txt. MPIR_Xxx_impl functions call MPIR_Coll_auto for CSEL
Expand All @@ -16,6 +15,11 @@
from the MPI C library. mpifort now explicitly links -lmpi (or -lmpi_abi).

# Split mpix.h from mpi.h. MPIX constants are available with ABI conversion support.
libmpi_abi provides the MPIX functions (mpicc -mpi-mpix, or its alias -mpix).

# libmpi_abi no longer exports the APIs removed from the MPI standard. With
mpicc -mpi-legacy, mpi_legacy.h maps them to their replacements; MPI_LB and
MPI_UB are not available in the MPI ABI.

# Added circulant graph (circ_graph) algorithms for Bcast, Reduce, Allgather, and
nonblocking IBcast.
Expand Down
2 changes: 1 addition & 1 deletion configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -2955,7 +2955,7 @@ fi
AC_SUBST(LPMPILIBNAME)
AC_SUBST(LPMPIABILIBNAME)

if test "enable_cxx" = "yes" ; then
if test "$enable_cxx" = "yes" ; then
LMPICXXLIBNAME="-l${MPICXXLIBNAME}"
else
LMPICXXLIBNAME=
Expand Down
1 change: 1 addition & 0 deletions doc/wiki/design/Design_Documentation_Index.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
- [Overriding Collective Functions](Overriding_Collective_Functions.md)

- Language Bindings
- [The `mpi.h` Header](MPI_Header.md)
- [Fortran Bindings](Fortran_Binding.md)
- [Stand-Alone Fortran Binding](Standalone_Fortran_Binding.md)

Expand Down
125 changes: 125 additions & 0 deletions doc/wiki/design/MPI_Header.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
# The `mpi.h` Header

This page describes how `src/include/mpi.h.in` is organized. One installed
`mpi.h` serves two ABIs, the MPICH ABI and the MPI ABI of MPI-5.0, and it is
also the header the MPI ABI library itself is compiled with. For the
user-facing side (configure options, `mpicc` flags, installed files), see
[MPI ABI Build Interface](../how_to/MPI_ABI_Build_Interface.md).

## The Three Modes

`mpi.h` is consumed in three modes, selected by two macros:

| Mode | Consumer | `MPI_ABI` | `MPICH_BUILD_MPI_ABI` | Set by |
|---|---|---|---|---|
| 1. MPI ABI header | user code built for `libmpi_abi` | defined | – | `mpicc` for the MPI ABI (`src/env/mpicc.def`) |
| 2. MPICH ABI header | user code built for `libmpi`, and the `libmpi` build itself | – | – | default |
| 3. MPI ABI library build | the MPICH sources compiled into `libmpi_abi` | – | defined | `abi_cppflags` in `Makefile.am` |

`MPI_ABI` is an input switch: it picks the branch of `mpi.h`, but it is not
what code should test afterwards. To tell which ABI a header provides, test
the macros the header defines:

- `MPICH` is defined in every mode, so code can tell that the header comes
from MPICH whichever ABI it is.
- `MPI_ABI_VERSION` is defined only by the MPI ABI header (`mpi_abi.h`), as
the MPI standard requires. MPICH's own headers, such as `mpix.h`, use it
to branch between the two ABIs.

## Layout of mpi.h.in

```
#define MPICH always
#ifdef MPI_ABI -- mode 1
#include "mpi_abi.h"
#include "mpix.h" if MPI_MPIX
#include "mpi_legacy.h" if MPI_LEGACY
#include "mpi_fortran.h" if MPI_FORTRAN
#else -- modes 2 and 3
#define MPI_MPIX MPIX is always on
#ifdef MPICH_BUILD_MPI_ABI -- mode 3 only
#include "mpi_abi_internal.h"
#endif
... MPICH native types and constants ...
#ifndef MPICH_BUILD_MPI_ABI -- mode 2 only
#include "mpix.h"
#include "mpi_proto.h"
#include "mpicxx.h" if C++
#include "mpi_fortran.h" if MPI_FORTRAN
#endif
#endif
```

### Mode 1: MPI ABI header

`mpi.h` is only a switch: everything comes from `mpi_abi.h`, the standard
ABI header kept in sync with the MPI Forum's `mpi-abi-stubs`
(`src/binding/abi/mpi_abi.h`). The MPICH-specific parts are opt-in, because
code that uses them is no longer portable across MPI ABI implementations:

| Macro | `mpicc` flag | Header | Provides |
|---|---|---|---|
| `MPI_MPIX` | `-mpi-mpix` (alias `-mpix`) | `mpix.h` | MPIX extensions |
| `MPI_LEGACY` | `-mpi-legacy` | `mpi_legacy.h` | APIs removed from the MPI standard, mapped to their replacements (no `MPI_LB`/`MPI_UB`) |
| `MPI_FORTRAN` | `-mpi-fortran` | `mpi_fortran.h` | Fortran interop (`MPI_Fint`, f2c/c2f), see [Stand-Alone Fortran Binding](Standalone_Fortran_Binding.md) |

### Mode 2: MPICH ABI header

This is the traditional MPICH `mpi.h`. Handles are `int`s with MPICH's own
encoding. `MPI_MPIX` is always defined, so `mpix.h` is always included.
Prototypes come from the generated `mpi_proto.h`, which also declares the
APIs removed from the standard; `mpi_legacy.h` is not used in this mode.
`mpix.h` comes before `mpi_proto.h` because `mpi_proto.h` declares the MPIX
functions too, and their types (`MPIX_Stream`, `MPIX_Iov`, ...) are defined
in `mpix.h`. `mpicxx.h` is included if the C++ binding is configured.

### Mode 3: MPI ABI library build

`libmpi_abi` is built from the same sources as `libmpi`, with
`-DMPICH_BUILD_MPI_ABI`. The internals keep using MPICH's native handles,
while the public functions take MPI ABI handles and convert them. To make
this work, `mpi.h` first includes `mpi_abi_internal.h`, which
`maint/gen_abi.py` generates from `mpi_abi.h` and `mpix.h`:

| From the MPI ABI headers | In `mpi_abi_internal.h` | Why |
|---|---|---|
| Handle types and constants, e.g. `MPI_Comm`, `MPI_COMM_WORLD` | renamed `ABI_Comm`, `ABI_COMM_WORLD` | the native `MPI_Comm` and `MPI_COMM_WORLD` follow in `mpi.h` and are what the internals use |
| Integer constants, e.g. `MPI_COMM_TYPE_SHARED` | kept, with the MPI ABI value (221) | the internals are compiled with the ABI values, so these need no conversion |
| `MPI_`/`MPIX_` prototypes | handle parameters use `ABI_` types, plus `MPICH_API_PUBLIC` | these are the functions `libmpi_abi` exports |

The rest of `mpi.h` then defines the native types and handle constants as in
mode 2. The native integer constants that the MPI ABI defines differently,
such as `MPI_COMM_TYPE_SHARED` (1 in the MPICH ABI), sit inside
`#ifndef MPICH_BUILD_MPI_ABI` blocks, so the ABI values from
`mpi_abi_internal.h` win. The tail of `mpi.h` (`mpix.h`, `mpi_proto.h`,
C++, `mpi_fortran.h`) is skipped; the MPIX declarations already come from
`mpi_abi_internal.h`.

The public functions are the generated wrappers in
`src/binding/abi/c_binding_abi.c`. They convert handle arguments with the
`ABI_<Type>_to_mpi` and `ABI_<Type>_from_mpi` functions in
`src/binding/abi/mpi_abi_util.h`, and pass everything else through. The
datatype and op conversion tables come from `mpi_abi_util.c`, also generated
by `maint/gen_abi.py`.

In a dual build (`--enable-mpi-abi=dual`) every source is compiled twice, once
in mode 2 for `libmpi` and once in mode 3 for `libmpi_abi`, so a constant can
have different values in the two libraries.

ROMIO does not go through `mpi.h` in this mode: its build includes the
generated `romio_abi_internal.h`, which keeps the MPI ABI types
(`src/mpi/romio/adio/include/adio.h`).

## Rules for Editing mpi.h.in

- A native integer constant that the MPI ABI also defines goes inside an
`#ifndef MPICH_BUILD_MPI_ABI` block, so mode 3 gets the ABI value.
- Native handle types and handle constants stay outside those blocks; mode 3
needs them for the internals.
- MPIX constants go in `mpix.h`. Those passed through `libmpi_abi`
unconverted and with no conflict in either ABI are defined once, for both
ABIs. Those that differ, such as handles, are defined in the
`#ifdef MPI_ABI_VERSION` branch of `mpix.h` for the MPI ABI and in
`mpi.h.in` for the MPICH ABI.
- After changing a header that `maint/gen_abi.py` reads, check the generated
`src/binding/abi/mpi_abi_internal.h` to see what mode 3 gets.
21 changes: 15 additions & 6 deletions doc/wiki/design/Standalone_Fortran_Binding.md
Original file line number Diff line number Diff line change
Expand Up @@ -202,8 +202,8 @@ else:
## Fallback Without MPIX

When building against an MPI implementation that does not provide these
MPIX extensions (or with `--disable-fortran-mpix`), the binding falls
back to standard MPI functions with degraded behavior:
MPIX extensions, the binding falls back to standard MPI functions with
degraded behavior:

| Feature | With MPIX | Fallback (without MPIX) |
|---------|-----------|------------------------|
Expand All @@ -212,6 +212,11 @@ back to standard MPI functions with degraded behavior:
| Error handler | Proxy converts handle to `MPI_Fint` | Fortran function called directly; handle argument is a C pointer, **unusable in Fortran** |
| Attr get/set | Uses `MPIX_*_as_fortran` with correct Fortran value semantics | Uses `MPI_*_get_attr` / `MPI_*_set_attr` with C pointer semantics (see notes below) |

The first three rows depend only on whether the C library provides the
MPIX callbacks (`HAS_MPIX_CALLBACKS`). The attribute get/set row depends on
whether the binding includes the MPIX routines (`--disable-fortran-mpix`,
and always off on the MPI ABI for now).

The fallback is functional for programs that do not inspect callback
arguments (e.g. error handlers that only print the error code, or ops
that ignore the datatype).
Expand All @@ -238,11 +243,15 @@ AC_CHECK_FUNCS([MPIX_Comm_create_keyval_x],
[has_mpix_callbacks=yes], [has_mpix_callbacks=no])
```

If not found, `HAS_MPIX_CALLBACKS` is not defined and the Python binding
generators receive `-skip-mpix` to omit MPIX function wrappers from the
generated Fortran bindings.
In-tree builds assume the callbacks on both ABIs. When they are available,
`HAS_MPIX_CALLBACKS` and `MPI_MPIX` (so that `mpi.h` declares them) are
defined and the proxies use them, independent of `--disable-fortran-mpix`.

Users can explicitly disable with `--disable-fortran-mpix`.
Separately, `enable_fortran_mpix` decides whether the generated bindings
include the MPIX routines; otherwise the Python binding generators receive
`-skip-mpix`. It defaults to whether the callbacks were found, can be
turned off with `--disable-fortran-mpix`, and is always off on the MPI ABI
for now.

## Fortran Initialization: `MPIX_Init_fortran`

Expand Down
26 changes: 20 additions & 6 deletions doc/wiki/how_to/MPI_ABI_Build_Interface.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,12 +124,16 @@ the optional parts (see `src/include/mpi.h.in`).

### `-mpi-mpix`

Defines `MPI_MPIX`, which causes `mpi.h` to include `mpix.h`. This
Defines `MPI_MPIX`, which causes `mpi.h` to include `mpix.h`. `-mpix` is
a shorter alias. This
provides access to MPIX extension functions (e.g. `MPIX_Query_cuda_support`).

The MPIX declarations are split into a separate header because
`mpi_abi.h` does not declare them. This flag makes them available
regardless of which ABI is in use.
regardless of which ABI is in use, and `libmpi_abi` provides the MPIX
functions, converting MPIX handles such as `MPIX_Stream` like the
standard ones. The Fortran binding does not use MPIX on the MPI ABI yet
(see below).

### `-mpi-fortran`

Expand All @@ -151,8 +155,16 @@ that loads both `libmpi_abi.so` and `libmpi.so` (see the warning above).
### `-mpi-legacy`

Defines `MPI_LEGACY`, which causes `mpi.h` to include `mpi_legacy.h`.
This provides deprecated or removed MPI symbols for backward
compatibility.
This provides the APIs removed from the MPI standard for source
compatibility with old codes. On the MPI ABI they are mapped to their
replacements with macros and static inline functions (e.g. `MPI_Address`
to `MPI_Get_address`), so `libmpi_abi` exports no removed symbol and the
program runs on any MPI ABI implementation. `MPI_LB` and `MPI_UB` are
not provided on the MPI ABI, because they only work if the library
interprets them; use `MPI_Type_create_resized` instead.

With the MPICH ABI the removed APIs are always available as real
functions in `libmpi`, and the flag has no effect.

## What Gets Built and Installed

Expand Down Expand Up @@ -188,7 +200,7 @@ from `main` installs `libmpi.so.0`; stable releases restore the
| `mpi_abi.h` | MPI ABI is built | The standard MPI ABI header (`MPI_ABI_VERSION` 1, `MPI_ABI_SUBVERSION` 0). |
| `mpi_proto.h` | MPICH ABI is built | MPICH ABI prototypes. |
| `mpix.h` | always | MPICH extensions (`MPIX_`), see `-mpi-mpix`. |
| `mpi_legacy.h` | always | Deprecated or removed MPI symbols, see `-mpi-legacy`. |
| `mpi_legacy.h` | always | APIs removed from the MPI standard, for the MPI ABI, see `-mpi-legacy`. |
| `mpi_fortran.h` | the Fortran binding is built | Fortran interoperability for C code, see `-mpi-fortran`. |

### Tools
Expand Down Expand Up @@ -227,7 +239,9 @@ mixed Fortran/C programs can still be linked with `mpifort`.

On the MPI ABI, the Fortran binding does not provide the `MPIX_` routines
(`--disable-fortran-mpix` is implied) and is compiled with
`FORTRAN_BUILD_MPI_ABI`.
`FORTRAN_BUILD_MPI_ABI`. It still uses the MPIX callbacks of the C library
(`HAS_MPIX_CALLBACKS`, e.g. `MPIX_Op_create_x`) for its user-function
proxies, whenever the library provides them.

### Fortran on the MPI ABI in a Dual Build

Expand Down
10 changes: 5 additions & 5 deletions maint/extracterrmsgs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ foreach my $k ("envvarparse", "cvar_val"){

# Check for special args
my $mpi_h = "src/include/mpi.h.in";
my $mpix_h = "src/include/mpix.h";
my $mpi_abi_h = "src/binding/abi/mpi_abi.h";
my $baseerrnames_txt = "src/mpi/errhan/baseerrnames.txt";
my @files = ();
Expand Down Expand Up @@ -119,10 +120,11 @@ if ($build_test_pgm && -d "test/mpi/errhan") {
print TESTFD "{\n int err;\n MPI_Init( 0, 0 );\n";
}

# Load mpi.h for error class constants
# Load mpi.h for error class constants, and mpix.h for the MPIX error classes
my %mpi_h_constants;
$mpi_h_constants{"MPI_SUCCESS"} = 0;
if (open In, $mpi_h) {
foreach my $h ($mpi_h, $mpix_h) {
open In, $h or die "Unable to read $h\n";
while (<In>) {
if (/^#define\s+((MPICH|MPI|MPI_T|MPIX)_ERR_\w+)\s+(.+)/) {
my ($key, $t) = ($1, $3);
Expand All @@ -134,8 +136,6 @@ if (open In, $mpi_h) {
}
}
close In;
} else {
die "Unable to read $mpi_h\n";
}

# Load mpi_abi.h for ABI error class constants
Expand All @@ -154,7 +154,7 @@ if (open In, $mpi_abi_h) {

my $max_err_class = $mpi_h_constants{MPICH_ERR_LAST_MPIX};
if (!$max_err_class) {
die "Failed to load MPICH_ERR_LAST_MPIX from $mpi_h\n";
die "Failed to load MPICH_ERR_LAST_MPIX from $mpix_h\n";
}

# Process the definitions
Expand Down
9 changes: 4 additions & 5 deletions maint/gen_abi.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ def search(pat, str, flags=0):
def main():
load_mpi_abi_h("src/binding/abi/mpi_abi.h")
load_mpi_abi_h("src/include/mpix.h")
load_mpi_abi_h("src/include/mpi_legacy.h")
dump_mpi_abi_internal_h("src/binding/abi/mpi_abi_internal.h")
dump_io_abi_internal_h("src/binding/abi/io_abi_internal.h")
dump_romio_abi_internal_h("src/mpi/romio/include/romio_abi_internal.h")
Expand All @@ -37,7 +36,7 @@ def load_mpi_abi_h(mpi_abi_h):
if RE.search(r'(MPI_ABI|MPIX)_H_INCLUDED', line):
# skip the include guard, harmless
pass
elif RE.match(r'^(int|double|MPI_\w+)\s+(P?MPI\w+)\((.*)', line):
elif RE.match(r'^(int|double|void \*|MPIX?_\w+)\s*(P?MPI\w+)\((.*)', line):
# handle multi-line function prototypes
lines = [line.strip()]
while not RE.match(r'(.*)\);', lines[-1]):
Expand All @@ -49,7 +48,7 @@ def load_mpi_abi_h(mpi_abi_h):
def dump_mpi_abi_internal_h(mpi_abi_internal_h):
define_constants = {}
def gen_mpi_abi_internal_h(out):
re_Handle = r'\bMPI_(Comm|Datatype|Errhandler|Group|Info|Message|Op|Request|Session|Win|File|KEYVAL_INVALID|TAG_UB|IO|HOST|WTIME_IS_GLOBAL|APPNUM|LASTUSEDCODE|UNIVERSE_SIZE|WIN_BASE|WIN_DISP_UNIT|WIN_SIZE|WIN_CREATE_FLAVOR|WIN_MODEL)\b'
re_Handle = r'\bMPIX?_(Comm|Datatype|Errhandler|Group|Info|Message|Op|Request|Session|Win|File|Stream|Grequest_class|KEYVAL_INVALID|TAG_UB|IO|HOST|WTIME_IS_GLOBAL|APPNUM|LASTUSEDCODE|UNIVERSE_SIZE|WIN_BASE|WIN_DISP_UNIT|WIN_SIZE|WIN_CREATE_FLAVOR|WIN_MODEL)\b'
for line in G.abi_h_lines:
if RE.match(r'\s*int MPI_(SOURCE|TAG|ERROR);', line):
# no need to rename status fields
Expand All @@ -61,7 +60,7 @@ def gen_mpi_abi_internal_h(out):
out.append(" %s count_lo;" % T)
out.append(" %s count_hi_and_cancelled;" % T)
out.append(" %s reserved[%d];" % (T, n - 2))
elif RE.match(r'#define\s+(MPIX?_\w+)\s+\(?\((MPI_\w+)\)\s*(0x\w+)\)?', line):
elif RE.match(r'#define\s+(MPIX?_\w+)\s+\(?\((MPIX?_\w+)\)\s*(0x\w+)\)?', line):
(name, T, val) = RE.m.group(1,2,3)
if T == "MPI_File":
# Both ROMIO and ABI use pointers, thus we can directly replace constants
Expand All @@ -82,7 +81,7 @@ def gen_mpi_abi_internal_h(out):
# rename to internal mpi_t struct type
T = RE.m.group(1)
out.append("typedef struct %s_s *%s;" % (re.sub(r'MPI_', 'MPIR_', T), T))
elif RE.match(r'^(int|double|MPI_\w+)\s+(P?MPI\w+)\((.*)\);', line):
elif RE.match(r'^(int|double|void \*|MPIX?_\w+)\s*(P?MPI\w+)\((.*)\);', line):
# prototypes, rename param prefix, add MPICH_API_PUBLIC
(T, name, param) = RE.m.group(1,2,3)
T=re.sub(re_Handle, r'ABI_\1', T)
Expand Down
13 changes: 2 additions & 11 deletions maint/gen_binding_c.py
Original file line number Diff line number Diff line change
Expand Up @@ -177,20 +177,11 @@ def dump_c_binding_abi():
G.out.append("")

for func in func_list:
if 'replace' in func and 'body' not in func:
if 'replace' in func:
# removed functions are header-only in the MPI ABI (mpi_legacy.h)
continue

if re.match(r'MPIX_', func['name']):
if re.match(r'MPIX_(Grequest_|Type_iov)', func['name']):
# needed by ROMIO
pass
else:
continue

dump_func_abi(func)
if '_replaces' in func:
for t_func in func['_replaces']:
dump_func_abi(t_func)

abi_file_path = G.abi_dir + "/c_binding_abi.c"
G.check_write_path(abi_file_path)
Expand Down
Loading