From a60b03b7f9641c1898cbfbab7a05c42b74c1475c Mon Sep 17 00:00:00 2001 From: Jeff Squyres Date: Mon, 5 May 2025 07:56:48 -0400 Subject: [PATCH 1/2] Convert more Perl build scripts to Python Continue the slow trend of removing Perl from our build process, and move to a more sustainable (at least by number of developers who know the language) language: Python. Use generative AI to convert 3 Perl scripts to Python: mpif-values.pl, gen-mpi-mangling.pl, and gen-mpi-sizeof.pl. Validate the results by code review+inspection and diff'ing the results of the Python-generated files with the original Perl-generated files. Signed-off-by: Jeff Squyres --- autogen.pl | 4 +- ompi/communicator/comm_init.c | 3 +- ompi/datatype/ompi_datatype_module.c | 3 +- ompi/include/Makefile.am | 17 +- ompi/include/mpi.h.in | 15 +- ompi/include/mpif-sentinels.h | 3 +- ompi/include/mpif-values.pl | 571 ------------------ ompi/include/mpif-values.py | 567 +++++++++++++++++ ompi/mpi/fortran/base/Makefile.am | 5 +- ompi/mpi/fortran/base/gen-mpi-mangling.pl | 206 ------- ompi/mpi/fortran/base/gen-mpi-mangling.py | 204 +++++++ ompi/mpi/fortran/base/gen-mpi-sizeof.pl | 283 --------- ompi/mpi/fortran/base/gen-mpi-sizeof.py | 328 ++++++++++ ompi/mpi/fortran/mpif-h/Makefile.am | 7 +- ompi/mpi/fortran/mpif-h/profile/Makefile.am | 7 +- ompi/mpi/fortran/use-mpi-f08/Makefile.am | 15 +- .../fortran/use-mpi-ignore-tkr/Makefile.am | 11 +- 17 files changed, 1149 insertions(+), 1100 deletions(-) delete mode 100755 ompi/include/mpif-values.pl create mode 100755 ompi/include/mpif-values.py delete mode 100755 ompi/mpi/fortran/base/gen-mpi-mangling.pl create mode 100755 ompi/mpi/fortran/base/gen-mpi-mangling.py delete mode 100755 ompi/mpi/fortran/base/gen-mpi-sizeof.pl create mode 100755 ompi/mpi/fortran/base/gen-mpi-sizeof.py diff --git a/autogen.pl b/autogen.pl index ecc726b54eb..167f8c1c6bc 100755 --- a/autogen.pl +++ b/autogen.pl @@ -10,8 +10,8 @@ # Copyright (c) 2015-2022 IBM Corporation. All rights reserved. # Copyright (c) 2020 Amazon.com, Inc. or its affiliates. # All Rights reserved. -# # Copyright (c) 2025 Nanook Consulting All rights reserved. +# Copyright (c) 2025 Jeffrey M. Squyres. All rights reserved. # $COPYRIGHT$ # # Additional copyrights may follow @@ -1609,7 +1609,7 @@ sub replace_config_sub_guess { # sync). my @scripts; -push(@scripts, "ompi/include/mpif-values.pl"); +push(@scripts, "ompi/include/mpif-values.py"); foreach my $s (@scripts) { verbose "=== $s\n"; diff --git a/ompi/communicator/comm_init.c b/ompi/communicator/comm_init.c index 86e260c536d..46148901f52 100644 --- a/ompi/communicator/comm_init.c +++ b/ompi/communicator/comm_init.c @@ -27,6 +27,7 @@ * reserved. * Copyright (c) 2023-2024 Advanced Micro Devices, Inc. All rights reserved. * Copyright (c) 2023 NVIDIA Corporation. All rights reserved. + * Copyright (c) 2025 Jeffrey M. Squyres. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -453,7 +454,7 @@ static void ompi_comm_construct(ompi_communicator_t* comm) comm->c_index_vec = NULL; /* - * magic numerology - see TOPDIR/ompi/include/mpif-values.pl + * magic numerology - see TOPDIR/ompi/include/mpif-values.py */ idx = (comm == (ompi_communicator_t*)ompi_mpi_comm_world_addr) ? 0 : (comm == (ompi_communicator_t*)ompi_mpi_comm_self_addr) ? 1 : diff --git a/ompi/datatype/ompi_datatype_module.c b/ompi/datatype/ompi_datatype_module.c index 77747100d90..1a2fed2e88a 100644 --- a/ompi/datatype/ompi_datatype_module.c +++ b/ompi/datatype/ompi_datatype_module.c @@ -20,6 +20,7 @@ * Copyright (c) 2016-2018 FUJITSU LIMITED. All rights reserved. * Copyright (c) 2018-2021 Triad National Security, LLC. All rights * reserved. + * Copyright (c) 2025 Jeffrey M. Squyres. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -566,7 +567,7 @@ int32_t ompi_datatype_init( void ) } while(0) /* - * This MUST match the order of ompi/include/mpif-values.pl + * This MUST match the order of ompi/include/mpif-values.py * Any change will break binary compatibility of Fortran programs. */ MOOG(datatype_null, 0); diff --git a/ompi/include/Makefile.am b/ompi/include/Makefile.am index 9b052b94920..d8a55e38c59 100644 --- a/ompi/include/Makefile.am +++ b/ompi/include/Makefile.am @@ -15,6 +15,7 @@ # and Technology (RIST). All rights reserved. # Copyright (c) 2018 FUJITSU LIMITED. All rights reserved. # Copyright (c) 2022 IBM Corporation. All rights reserved. +# Copyright (c) 2025 Jeffrey M. Squyres. All rights reserved. # $COPYRIGHT$ # # Additional copyrights may follow @@ -66,7 +67,7 @@ endif include ompi/Makefile.am -# This is complicated, but mpif-values.pl generates several +# This is complicated, but mpif-values.py generates several # mpif-*.h files in this directory (during autogen.pl). # Hence, if any of those files change, it's safer to just force the # user to re-autogen. @@ -75,17 +76,17 @@ include ompi/Makefile.am # @ echo "ERROR: you must re-run autogen.pl (sorry!)" # @ exit 1 -EXTRA_DIST = $(headers) mpif-values.pl +EXTRA_DIST = $(headers) mpif-values.py # # mpif-sizeof.h is generated based on some results from configure tests. # -sizeof_pl=$(top_srcdir)/ompi/mpi/fortran/base/gen-mpi-sizeof.pl +sizeof_py=$(top_srcdir)/ompi/mpi/fortran/base/gen-mpi-sizeof.py mpif-sizeof.h: $(top_builddir)/config.status -mpif-sizeof.h: $(sizeof_pl) +mpif-sizeof.h: $(sizeof_py) mpif-sizeof.h: - $(OMPI_V_GEN) $(sizeof_pl) \ + $(OMPI_V_GEN) $(python) $(sizeof_py) \ --header=$@ --ierror=mandatory \ --maxrank=$(OMPI_FORTRAN_MAX_ARRAY_RANK) \ --generate=$(OMPI_FORTRAN_BUILD_SIZEOF) \ @@ -102,11 +103,11 @@ mpif-sizeof.h: # results from configure tests. # -mpif_mangling_pl=$(top_srcdir)/ompi/mpi/fortran/base/gen-mpi-mangling.pl +mpif_mangling_py=$(top_srcdir)/ompi/mpi/fortran/base/gen-mpi-mangling.py mpif-c-constants-decl.h: $(top_builddir)/config.status -mpif-c-constants-decl.h: $(mpif_mangling_pl) +mpif-c-constants-decl.h: $(mpif_mangling_py) mpif-c-constants-decl.h: - $(OMPI_V_GEN) $(mpif_mangling_pl) \ + $(OMPI_V_GEN) $(python) $(mpif_mangling_py) \ --caps $(OMPI_FORTRAN_CAPS) \ --plain $(OMPI_FORTRAN_PLAIN) \ --single $(OMPI_FORTRAN_SINGLE_UNDERSCORE) \ diff --git a/ompi/include/mpi.h.in b/ompi/include/mpi.h.in index 4886868c37c..e838fe66061 100644 --- a/ompi/include/mpi.h.in +++ b/ompi/include/mpi.h.in @@ -28,6 +28,7 @@ * Copyright (c) 2018-2022 Triad National Security, LLC. All rights * reserved. * Copyright (c) 2025 Advanced Micro Devices, Inc. All rights reserved + * Copyright (c) 2025 Jeffrey M. Squyres. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -538,9 +539,9 @@ typedef MPI_Win_errhandler_function MPI_Win_errhandler_fn * Miscellaneous constants * * NOTE: Many of the integer constants below *also* appear in - * ompi/include/mpif-values.pl. If you change any of these integer + * ompi/include/mpif-values.py. If you change any of these integer * values below, make sure to also change the corresponding values in - * mpif-values.pl. + * mpif-values.py. */ #define MPI_ANY_SOURCE -1 /* match any source rank */ #define MPI_PROC_NULL -2 /* rank of null process */ @@ -583,7 +584,7 @@ typedef MPI_Win_errhandler_function MPI_Win_errhandler_fn * Constants for C code to access elements in Fortran MPI status array. * * NOTE: The MPI_F_SOURCE, MPI_F_TAG, MPI_F_ERROR are intentionally 1 - * smaller than their Fortran equivalents in mpif-values.pl (because C + * smaller than their Fortran equivalents in mpif-values.py (because C * is 0-indexed and Fortran is 1-indexed). */ #define MPI_F_STATUS_SIZE OMPI_FORTRAN_STATUS_SIZE /* Size of Fortran MPI status array */ @@ -761,7 +762,7 @@ enum { * Comparison results. Don't change the order of these, the group * comparison functions rely on it. * Do not change the order of these without also modifying - * mpif-values.pl. + * mpif-values.py. */ enum { MPI_IDENT, @@ -773,7 +774,7 @@ enum { /* * MPI_Init_thread constants * Do not change the order of these without also modifying - * mpif-values.pl. + * mpif-values.py. */ enum { MPI_THREAD_SINGLE, @@ -785,7 +786,7 @@ enum { /* * Datatype combiners. * Do not change the order of these without also modifying - * mpif-values.pl. + * mpif-values.py. */ enum { MPI_COMBINER_NAMED, @@ -837,7 +838,7 @@ enum { /* * Communicator split type constants. * Do not change the order of these without also modifying - * mpif-values.pl. + * mpif-values.py. */ enum { MPI_COMM_TYPE_SHARED, diff --git a/ompi/include/mpif-sentinels.h b/ompi/include/mpif-sentinels.h index 99384d072eb..8411ae77219 100644 --- a/ompi/include/mpif-sentinels.h +++ b/ompi/include/mpif-sentinels.h @@ -12,6 +12,7 @@ ! All rights reserved. ! Copyright (c) 2006-2012 Cisco Systems, Inc. All rights reserved. ! Copyright (c) 2009 Oak Ridge National Labs. All rights reserved. +! Copyright (c) 2025 Jeffrey M. Squyres. All rights reserved. ! $COPYRIGHT$ ! ! Additional copyrights may follow @@ -26,7 +27,7 @@ ! ! - the "mpi" module bindings ! - the "mpi_f08" module bindings -! - ompi/mpi/fortran/base/gen-mpi-mangling.pl +! - ompi/mpi/fortran/base/gen-mpi-mangling.py ! ! MPI_BOTTOM is only used where choice buffers can be used (meaning diff --git a/ompi/include/mpif-values.pl b/ompi/include/mpif-values.pl deleted file mode 100755 index 21f69530cde..00000000000 --- a/ompi/include/mpif-values.pl +++ /dev/null @@ -1,571 +0,0 @@ -#!/usr/bin/env perl -# -# Copyright (c) 2011-2014 Cisco Systems, Inc. All rights reserved. -# Copyright (c) 2016-2019 Research Organization for Information Science -# and Technology (RIST). All rights reserved. -# Copyright (c) 2016-2018 FUJITSU LIMITED. All rights reserved. -# Copyright (c) 2020 The University of Tennessee and The University -# of Tennessee Research Foundation. All rights -# reserved. -# Copyright (c) 2022 IBM Corporation. All rights reserved. -# $COPYRIGHT$ -# -# Additional copyrights may follow -# -# $HEADER$ -# - -# This script creates header files to be compiled with the various -# Fortran bindings. In some cases, we need Fortran PARAMETER values; -# in other cases, we need #define preprocessor macros. -# -# This script generates both cases, and ensures that the values are -# the same between both (e.g., that MPI_COMM_WORLD is both a fortran -# INTEGER PARAMETER of value 0 and is #define'd to be 0). -# -# Additionally, since Open MPI provides the configure ability to -# compile out the entire MPI IO interface, all the IO -# handles/constants are generated in separate .h files in the -# non-preprocessor case, and included in relevant #if's in the -# preprocessor case. -# -# Files are generated in the following directories: -# -# ompi/include -# ompi/mpi/fortran/use-mpi-f08 -# - -use strict; - -#---------------------------------------------------------------------------- - -# Write an output file only if a) the output file does not already -# exist, or b) it exists, but its contents are different than $str. - -sub write_file { - my ($filename_out, $str) = @_; - - my $need_write = 0; - if (! -f $filename_out) { - $need_write = 1; - } else { - open(FILE_IN, $filename_out) || die "Couldn't open $filename_out"; - my $tmp; - $tmp .= $_ - while (); - close(FILE_IN); - if ($str ne $tmp) { - $need_write = 1; - } - } - - if ($need_write) { - open(FILE_OUT, ">$filename_out") || die "Couldn't open $filename_out"; - print FILE_OUT $str; - close(FILE_OUT); - print "created $filename_out\n"; - } else { - print "$filename_out unchanged; not written\n"; - } -} - -#---------------------------------------------------------------------------- - -# Read a value for a specified key from the file specified. - -sub read_value_from_file { - my ($filename, $key) = @_; - my $value; - - open(FILE_IN, $filename) || die "Couldn't open $filename"; - while(my $line = ) { - if( $line =~ /^$key=(.+)/ ) { - $value = $1; - last; - } - } - close(FILE_IN); - - if(!defined($value)) { - die "Did not find the string \"$key\" in the file $filename" - } - - return $value; -} - -#---------------------------------------------------------------------------- - -print "creating Fortran header files (with common constants)...\n"; - -# Find the OMPI topdir. It is likely the pwd. -my $topdir; -if (-r "ompi/include/mpi.h.in") { - $topdir = "."; -} elsif (-r "include/mpi.h.in") { - $topdir = ".."; -} elsif (-r "mpi.h.in") { - $topdir = "../.."; -} else { - print "Please run this script from the Open MPI topdir or topdir/include/mpi\n"; - print "Aborting.\n"; - exit(1); -} - -#---------------------------------------------------------------------------- - -my $handles; -my $lhandles; - -$handles->{MPI_COMM_WORLD} = 0; -$handles->{MPI_COMM_SELF} = 1; -$handles->{MPI_GROUP_EMPTY} = 1; -$handles->{MPI_ERRORS_ARE_FATAL} = 1; -$handles->{MPI_ERRORS_RETURN} = 2; -$handles->{MPI_ERRORS_ABORT} = 3; - -$handles->{MPI_MAX} = 1; -$handles->{MPI_MIN} = 2; -$handles->{MPI_SUM} = 3; -$handles->{MPI_PROD} = 4; -$handles->{MPI_LAND} = 5; -$handles->{MPI_BAND} = 6; -$handles->{MPI_LOR} = 7; -$handles->{MPI_BOR} = 8; -$handles->{MPI_LXOR} = 9; -$handles->{MPI_BXOR} = 10; -$handles->{MPI_MAXLOC} = 11; -$handles->{MPI_MINLOC} = 12; -$handles->{MPI_REPLACE} = 13; -$handles->{MPI_NO_OP} = 14; - -$handles->{MPI_COMM_NULL} = 2; -$handles->{MPI_DATATYPE_NULL} = 0; -$handles->{MPI_ERRHANDLER_NULL} = 0; -$handles->{MPI_GROUP_NULL} = 0; -$handles->{MPI_INFO_NULL} = 0; -$handles->{MPI_MESSAGE_NULL} = 0; -$handles->{MPI_OP_NULL} = 0; -$handles->{MPI_REQUEST_NULL} = 0; -$handles->{MPI_WIN_NULL} = 0; -$handles->{MPI_MESSAGE_NULL} = 0; -$handles->{MPI_SESSION_NULL} = 0; - -$handles->{MPI_BYTE} = 1; -$handles->{MPI_PACKED} = 2; -$handles->{MPI_UB} = 3; -$handles->{MPI_LB} = 4; -$handles->{MPI_CHARACTER} = 5; -$handles->{MPI_LOGICAL} = 6; -$handles->{MPI_INTEGER} = 7; -$handles->{MPI_INTEGER1} = 8; -$handles->{MPI_INTEGER2} = 9; -$handles->{MPI_INTEGER4} = 10; -$handles->{MPI_INTEGER8} = 11; -$handles->{MPI_INTEGER16} = 12; -$handles->{MPI_REAL} = 13; -$handles->{MPI_REAL4} = 14; -$handles->{MPI_REAL8} = 15; -$handles->{MPI_REAL16} = 16; -$handles->{MPI_DOUBLE_PRECISION} = 17; -$handles->{MPI_COMPLEX} = 18; -$handles->{MPI_COMPLEX8} = 19; -$handles->{MPI_COMPLEX16} = 20; -$handles->{MPI_COMPLEX32} = 21; -$handles->{MPI_DOUBLE_COMPLEX} = 22; -$handles->{MPI_2REAL} = 23; -$handles->{MPI_2DOUBLE_PRECISION} = 24; -$handles->{MPI_2INTEGER} = 25; -$handles->{MPI_2COMPLEX} = 26; -$handles->{MPI_2DOUBLE_COMPLEX} = 27; -$handles->{MPI_REAL2} = 28; -$handles->{MPI_LOGICAL1} = 29; -$handles->{MPI_LOGICAL2} = 30; -$handles->{MPI_LOGICAL4} = 31; -$handles->{MPI_LOGICAL8} = 32; -$handles->{MPI_WCHAR} = 33; -$handles->{MPI_CHAR} = 34; -$handles->{MPI_UNSIGNED_CHAR} = 35; -$handles->{MPI_SIGNED_CHAR} = 36; -$handles->{MPI_SHORT} = 37; -$handles->{MPI_UNSIGNED_SHORT} = 38; -$handles->{MPI_INT} = 39; -$handles->{MPI_UNSIGNED} = 40; -$handles->{MPI_LONG} = 41; -$handles->{MPI_UNSIGNED_LONG} = 42; -$handles->{MPI_LONG_LONG_INT} = 43; -$handles->{MPI_LONG_LONG} = $handles->{MPI_LONG_LONG_INT}; -$handles->{MPI_UNSIGNED_LONG_LONG} = 44; -$handles->{MPI_FLOAT} = 45; -$handles->{MPI_DOUBLE} = 46; -$handles->{MPI_LONG_DOUBLE} = 47; -$handles->{MPI_FLOAT_INT} = 48; -$handles->{MPI_DOUBLE_INT} = 49; -$handles->{MPI_LONG_DOUBLE_INT} = 50; -$handles->{MPI_LONG_INT} = 51; -$handles->{MPI_2INT} = 52; -$handles->{MPI_SHORT_INT} = 53; -$handles->{MPI_CXX_BOOL} = 54; -$handles->{MPI_CXX_FLOAT_COMPLEX} = 55; -$handles->{MPI_CXX_COMPLEX} = $handles->{MPI_CXX_FLOAT_COMPLEX}; -$handles->{MPI_CXX_DOUBLE_COMPLEX} = 56; -$handles->{MPI_CXX_LONG_DOUBLE_COMPLEX} = 57; -$handles->{MPI_INT8_T} = 58; -$handles->{MPI_UINT8_T} = 59; -$handles->{MPI_INT16_T} = 60; -$handles->{MPI_UINT16_T} = 61; -$handles->{MPI_INT32_T} = 62; -$handles->{MPI_UINT32_T} = 63; -$handles->{MPI_INT64_T} = 64; -$handles->{MPI_UINT64_T} = 65; -$handles->{MPI_AINT} = 66; -$handles->{MPI_OFFSET} = 67; -$handles->{MPI_C_BOOL} = 68; -$handles->{MPI_C_COMPLEX} = 69; -$handles->{MPI_C_FLOAT_COMPLEX} = $handles->{MPI_C_COMPLEX}; -$handles->{MPI_C_DOUBLE_COMPLEX} = 70; -$handles->{MPI_C_LONG_DOUBLE_COMPLEX} = 71; -$handles->{MPI_COUNT} = 72; -$handles->{MPI_COMPLEX4} = 73; - -$handles->{MPI_MESSAGE_NO_PROC} = 1; - -$handles->{MPI_INFO_ENV} = 1; - -#---------------------------------------------------------------------------- - -my $io_handles; - -$io_handles->{MPI_FILE_NULL} = 0; - -#---------------------------------------------------------------------------- - -my $constants; - -$constants->{MPI_VERSION} = read_value_from_file("$topdir/VERSION", "mpi_standard_version"); -$constants->{MPI_SUBVERSION} = read_value_from_file("$topdir/VERSION", "mpi_standard_subversion"); - -$constants->{MPI_ANY_SOURCE} = -1; -$constants->{MPI_ANY_TAG} = -1; -$constants->{MPI_PROC_NULL} = -2; -$constants->{MPI_ROOT} = -4; -$constants->{MPI_UNDEFINED} = -32766; -$constants->{MPI_CART} = 1; -$constants->{MPI_GRAPH} = 2; -$constants->{MPI_DIST_GRAPH} = 3; -$constants->{MPI_KEYVAL_INVALID} = -1; -$constants->{MPI_SOURCE} = 1; -$constants->{MPI_TAG} = 2; -$constants->{MPI_ERROR} = 3; -$constants->{MPI_TAG_UB} = 0; -$constants->{MPI_HOST} = 1; -$constants->{MPI_IO} = 2; -$constants->{MPI_WTIME_IS_GLOBAL} = 3; -$constants->{MPI_APPNUM} = 4; -$constants->{MPI_LASTUSEDCODE} = 5; -$constants->{MPI_UNIVERSE_SIZE} = 6; -$constants->{MPI_WIN_BASE} = 7; -$constants->{MPI_WIN_SIZE} = 8; -$constants->{MPI_WIN_DISP_UNIT} = 9; -$constants->{MPI_WIN_CREATE_FLAVOR} = 10; -$constants->{MPI_WIN_MODEL} = 11; -$constants->{MPI_FT} = 12; -$constants->{MPI_WIN_FLAVOR_CREATE} = 1; -$constants->{MPI_WIN_FLAVOR_ALLOCATE} = 2; -$constants->{MPI_WIN_FLAVOR_DYNAMIC} = 3; -$constants->{MPI_WIN_FLAVOR_SHARED} = 4; -$constants->{MPI_WIN_UNIFIED} = 0; -$constants->{MPI_WIN_SEPARATE} = 1; - -$constants->{MPI_BSEND_OVERHEAD} = 128; -$constants->{MPI_ORDER_C} = 0; -$constants->{MPI_ORDER_FORTRAN} = 1; -$constants->{MPI_DISTRIBUTE_BLOCK} = 0; -$constants->{MPI_DISTRIBUTE_CYCLIC} = 1; -$constants->{MPI_DISTRIBUTE_NONE} = 2; -$constants->{MPI_DISTRIBUTE_DFLT_DARG} = -1; -$constants->{MPI_TYPECLASS_INTEGER} = 1; -$constants->{MPI_TYPECLASS_REAL} = 2; -$constants->{MPI_TYPECLASS_COMPLEX} = 3; -$constants->{MPI_MODE_NOCHECK} = 1; -$constants->{MPI_MODE_NOPRECEDE} = 2; -$constants->{MPI_MODE_NOPUT} = 4; -$constants->{MPI_MODE_NOSTORE} = 8; -$constants->{MPI_MODE_NOSUCCEED} = 16; -$constants->{MPI_LOCK_EXCLUSIVE} = 1; -$constants->{MPI_LOCK_SHARED} = 2; - -$constants->{MPI_THREAD_SINGLE} = 0; -$constants->{MPI_THREAD_FUNNELED} = 1; -$constants->{MPI_THREAD_SERIALIZED} = 2; -$constants->{MPI_THREAD_MULTIPLE} = 3; - -$constants->{MPI_SUCCESS} = 0; -$constants->{MPI_ERR_BUFFER} = 1; -$constants->{MPI_ERR_COUNT} = 2; -$constants->{MPI_ERR_TYPE} = 3; -$constants->{MPI_ERR_TAG} = 4; -$constants->{MPI_ERR_COMM} = 5; -$constants->{MPI_ERR_RANK} = 6; -$constants->{MPI_ERR_REQUEST} = 7; -$constants->{MPI_ERR_ROOT} = 8; -$constants->{MPI_ERR_GROUP} = 9; -$constants->{MPI_ERR_OP} = 10; -$constants->{MPI_ERR_TOPOLOGY} = 11; -$constants->{MPI_ERR_DIMS} = 12; -$constants->{MPI_ERR_ARG} = 13; -$constants->{MPI_ERR_UNKNOWN} = 14; -$constants->{MPI_ERR_TRUNCATE} = 15; -$constants->{MPI_ERR_OTHER} = 16; -$constants->{MPI_ERR_INTERN} = 17; -$constants->{MPI_ERR_IN_STATUS} = 18; -$constants->{MPI_ERR_PENDING} = 19; -$constants->{MPI_ERR_ACCESS} = 20; -$constants->{MPI_ERR_AMODE} = 21; -$constants->{MPI_ERR_ASSERT} = 22; -$constants->{MPI_ERR_BAD_FILE} = 23; -$constants->{MPI_ERR_BASE} = 24; -$constants->{MPI_ERR_CONVERSION} = 25; -$constants->{MPI_ERR_DISP} = 26; -$constants->{MPI_ERR_DUP_DATAREP} = 27; -$constants->{MPI_ERR_FILE_EXISTS} = 28; -$constants->{MPI_ERR_FILE_IN_USE} = 29; -$constants->{MPI_ERR_FILE} = 30; -$constants->{MPI_ERR_INFO_KEY} = 31; -$constants->{MPI_ERR_INFO_NOKEY} = 32; -$constants->{MPI_ERR_INFO_VALUE} = 33; -$constants->{MPI_ERR_INFO} = 34; -$constants->{MPI_ERR_IO} = 35; -$constants->{MPI_ERR_KEYVAL} = 36; -$constants->{MPI_ERR_LOCKTYPE} = 37; -$constants->{MPI_ERR_NAME} = 38; -$constants->{MPI_ERR_NO_MEM} = 39; -$constants->{MPI_ERR_NOT_SAME} = 40; -$constants->{MPI_ERR_NO_SPACE} = 41; -$constants->{MPI_ERR_NO_SUCH_FILE} = 42; -$constants->{MPI_ERR_PORT} = 43; -$constants->{MPI_ERR_PROC_ABORTED} = 74; -$constants->{MPI_ERR_QUOTA} = 44; -$constants->{MPI_ERR_READ_ONLY} = 45; -$constants->{MPI_ERR_RMA_CONFLICT} = 46; -$constants->{MPI_ERR_RMA_SYNC} = 47; -$constants->{MPI_ERR_SERVICE} = 48; -$constants->{MPI_ERR_SIZE} = 49; -$constants->{MPI_ERR_SPAWN} = 50; -$constants->{MPI_ERR_UNSUPPORTED_DATAREP} = 51; -$constants->{MPI_ERR_UNSUPPORTED_OPERATION} = 52; -$constants->{MPI_ERR_WIN} = 53; -# these errors are MPI, but we keep it with high values -# until standardized so as to avoid changing the ABI -$constants->{MPI_ERR_PROC_FAILED} = 75; -$constants->{MPI_ERR_PROC_FAILED_PENDING} = 76; -$constants->{MPI_ERR_REVOKED} = 77; -# these error codes will never be returned by a fortran function -# since there are no fortran bindings for MPI_T -$constants->{MPI_T_ERR_MEMORY} = 54; -$constants->{MPI_T_ERR_NOT_INITIALIZED} = 55; -$constants->{MPI_T_ERR_CANNOT_INIT} = 56; -$constants->{MPI_T_ERR_INVALID_INDEX} = 57; -$constants->{MPI_T_ERR_INVALID_ITEM} = 58; -$constants->{MPI_T_ERR_INVALID_HANDLE} = 59; -$constants->{MPI_T_ERR_OUT_OF_HANDLES} = 60; -$constants->{MPI_T_ERR_OUT_OF_SESSIONS} = 61; -$constants->{MPI_T_ERR_INVALID_SESSION} = 62; -$constants->{MPI_T_ERR_CVAR_SET_NOT_NOW} = 63; -$constants->{MPI_T_ERR_CVAR_SET_NEVER} = 64; -$constants->{MPI_T_ERR_PVAR_NO_STARTSTOP} = 65; -$constants->{MPI_T_ERR_PVAR_NO_WRITE} = 66; -$constants->{MPI_T_ERR_PVAR_NO_ATOMIC} = 67; -$constants->{MPI_ERR_RMA_RANGE} = 68; -$constants->{MPI_ERR_RMA_ATTACH} = 69; -$constants->{MPI_ERR_RMA_FLAVOR} = 70; -$constants->{MPI_ERR_RMA_SHARED} = 71; -$constants->{MPI_T_ERR_INVALID} = 72; -$constants->{MPI_ERR_SESSION} = 78; -$constants->{MPI_ERR_VALUE_TOO_LARGE} = 79; -$constants->{MPI_ERR_LASTCODE} = 92; - -$constants->{MPI_IDENT} = 0; -$constants->{MPI_CONGRUENT} = 1; -$constants->{MPI_SIMILAR} = 2; -$constants->{MPI_UNEQUAL} = 3; - -$constants->{MPI_COMBINER_NAMED} = 0; -$constants->{MPI_COMBINER_DUP} = 1; -$constants->{MPI_COMBINER_CONTIGUOUS} = 2; -$constants->{MPI_COMBINER_VECTOR} = 3; -$constants->{MPI_COMBINER_HVECTOR_INTEGER} = 4; -$constants->{MPI_COMBINER_HVECTOR} = 5; -$constants->{MPI_COMBINER_INDEXED} = 6; -$constants->{MPI_COMBINER_HINDEXED_INTEGER} = 7; -$constants->{MPI_COMBINER_HINDEXED} = 8; -$constants->{MPI_COMBINER_INDEXED_BLOCK} = 9; -$constants->{MPI_COMBINER_STRUCT_INTEGER} = 10; -$constants->{MPI_COMBINER_STRUCT} = 11; -$constants->{MPI_COMBINER_SUBARRAY} = 12; -$constants->{MPI_COMBINER_DARRAY} = 13; -$constants->{MPI_COMBINER_F90_REAL} = 14; -$constants->{MPI_COMBINER_F90_COMPLEX} = 15; -$constants->{MPI_COMBINER_F90_INTEGER} = 16; -$constants->{MPI_COMBINER_RESIZED} = 17; -$constants->{MPI_COMBINER_HINDEXED_BLOCK} = 18; - -$constants->{MPI_COMM_TYPE_SHARED} = 0; -$constants->{OMPI_COMM_TYPE_HWTHREAD} = 1; -$constants->{OMPI_COMM_TYPE_CORE} = 2; -$constants->{OMPI_COMM_TYPE_L1CACHE} = 3; -$constants->{OMPI_COMM_TYPE_L2CACHE} = 4; -$constants->{OMPI_COMM_TYPE_L3CACHE} = 5; -$constants->{OMPI_COMM_TYPE_SOCKET} = 6; -$constants->{OMPI_COMM_TYPE_NUMA} = 7; -$constants->{OMPI_COMM_TYPE_NODE} = 0; -$constants->{OMPI_COMM_TYPE_BOARD} = 8; -$constants->{OMPI_COMM_TYPE_HOST} = 9; -$constants->{OMPI_COMM_TYPE_CU} = 10; -$constants->{OMPI_COMM_TYPE_CLUSTER} = 11; -$constants->{MPI_COMM_TYPE_HW_UNGUIDED} = 12; -$constants->{MPI_COMM_TYPE_HW_GUIDED} = 13; - -#---------------------------------------------------------------------------- - -my $io_constants; - -$io_constants->{MPI_SEEK_SET} = 600; -$io_constants->{MPI_SEEK_CUR} = 602; -$io_constants->{MPI_SEEK_END} = 604; -$io_constants->{MPI_MODE_CREATE} = 1; -$io_constants->{MPI_MODE_RDONLY} = 2; -$io_constants->{MPI_MODE_WRONLY} = 4; -$io_constants->{MPI_MODE_RDWR} = 8; -$io_constants->{MPI_MODE_DELETE_ON_CLOSE} = 16; -$io_constants->{MPI_MODE_UNIQUE_OPEN} = 32; -$io_constants->{MPI_MODE_EXCL} = 64; -$io_constants->{MPI_MODE_APPEND} = 128; -$io_constants->{MPI_MODE_SEQUENTIAL} = 256; - -my $lio_constants; -$lio_constants->{MPI_DISPLACEMENT_CURRENT} = -54278278; - -#---------------------------------------------------------------------------- - -# Fortran handles file - -my $header = '! -*- fortran -*- -! WARNING! THIS IS A GENERATED FILE!! -! ANY EDITS YOU PUT HERE WILL BE LOST! -! ==> Instead, edit topdir/ompi/include/mpif-values.pl. - -! Copyright (c) 2004-2006 The Trustees of Indiana University and Indiana -! University Research and Technology -! Corporation. All rights reserved. -! Copyright (c) 2004-2016 The University of Tennessee and The University -! of Tennessee Research Foundation. All rights -! reserved. -! Copyright (c) 2004-2007 High Performance Computing Center Stuttgart, -! University of Stuttgart. All rights reserved. -! Copyright (c) 2004-2005 The Regents of the University of California. -! All rights reserved. -! Copyright (c) 2006-2012 Cisco Systems, Inc. All rights reserved. -! Copyright (c) 2009-2012 Oak Ridge National Labs. All rights reserved. -! Copyright (c) 2016 Research Organization for Information Science -! and Technology (RIST). All rights reserved. -! $COPYRIGHT$ -! -! Additional copyrights may follow -! -! $HEADER$ -! - -'; - -sub write_fortran_file { - my ($header, $vals, $lvals, $file) = @_; - - foreach my $key (sort(keys(%{$vals}))) { - $header .= " integer $key\n"; - } - foreach my $key (sort(keys(%{$lvals}))) { - $header .= " integer(KIND=MPI_OFFSET_KIND) $key\n"; - } - $header .= "\n"; - foreach my $key (sort(keys(%{$vals}))) { - $header .= " parameter ($key=$vals->{$key})\n"; - } - foreach my $key (sort(keys(%{$lvals}))) { - $header .= " parameter ($key=$lvals->{$key})\n"; - } - - write_file($file, $header); -} - -write_fortran_file($header, $handles, {}, - "$topdir/ompi/include/mpif-handles.h"); -write_fortran_file($header, $constants, {}, - "$topdir/ompi/include/mpif-constants.h"); -write_fortran_file($header, $io_handles, {}, - "$topdir/ompi/include/mpif-io-handles.h"); -write_fortran_file($header, $io_constants, $lio_constants, - "$topdir/ompi/include/mpif-io-constants.h"); - -#---------------------------------------------------------------------------- - -# Create preprocessor files - -my $output = '! WARNING! THIS IS A GENERATED FILE!! -! ANY EDITS YOU PUT HERE WILL BE LOST! -! Instead, edit topdir/ompi/include/mpif-values.pl -! - -! -! Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana -! University Research and Technology -! Corporation. All rights reserved. -! Copyright (c) 2004-2016 The University of Tennessee and The University -! of Tennessee Research Foundation. All rights -! reserved. -! Copyright (c) 2004-2007 High Performance Computing Center Stuttgart, -! University of Stuttgart. All rights reserved. -! Copyright (c) 2004-2005 The Regents of the University of California. -! All rights reserved. -! Copyright (c) 2007-2009 Cisco Systems, Inc. All rights reserved. -! Copyright (c) 2008-2009 Sun Microsystems, Inc. All rights reserved. -! Copyright (c) 2009-2012 Oak Ridge National Labs. All rights reserved. -! Copyright (c) 2009-2012 Los Alamos National Security, LLC. -! All rights reserved. -! Copyright (c) 2016-2019 Research Organization for Information Science -! and Technology (RIST). All rights reserved. -! $COPYRIGHT$ -! -! Additional copyrights may follow -! -! $HEADER$ -! - -#ifndef USE_MPI_F08_CONSTANTS_H -#define USE_MPI_F08_CONSTANTS_H - -'; - -foreach my $key (sort(keys(%{$constants}))) { - $output .= "#define OMPI_$key $constants->{$key}\n"; -} -$output .= "\n"; -foreach my $key (sort(keys(%{$handles}))) { - $output .= "#define OMPI_$key $handles->{$key}\n"; -} - -foreach my $key (sort(keys(%{$io_constants}))) { - $output .= "#define OMPI_$key $io_constants->{$key}\n"; -} -foreach my $key (sort(keys(%{$lio_constants}))) { - $output .= "#define OMPI_$key $lio_constants->{$key}\n"; -} -$output .= "\n"; -foreach my $key (sort(keys(%{$io_handles}))) { - $output .= "#define OMPI_$key $io_handles->{$key}\n"; -} -$output .= "\n"; -$output .= "#endif\n"; - -write_file("$topdir/ompi/mpi/fortran/use-mpi-f08/mod/mpi-f08-constants.h", $output); - -exit(0); diff --git a/ompi/include/mpif-values.py b/ompi/include/mpif-values.py new file mode 100755 index 00000000000..f4537762a79 --- /dev/null +++ b/ompi/include/mpif-values.py @@ -0,0 +1,567 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2011-2014 Cisco Systems, Inc. All rights reserved. +# Copyright (c) 2016-2019 Research Organization for Information Science +# and Technology (RIST). All rights reserved. +# Copyright (c) 2016-2018 FUJITSU LIMITED. All rights reserved. +# Copyright (c) 2020 The University of Tennessee and The University +# of Tennessee Research Foundation. All rights +# reserved. +# Copyright (c) 2022 IBM Corporation. All rights reserved. +# Copyright (c) 2025 Jeffrey M. Squyres. All rights reserved. +# $COPYRIGHT$ +# +# Additional copyrights may follow +# +# $HEADER$ +# + +# This script creates header files to be compiled with the various +# Fortran bindings. In some cases, we need Fortran PARAMETER values; +# in other cases, we need #define preprocessor macros. +# +# This script generates both cases, and ensures that the values are +# the same between both (e.g., that MPI_COMM_WORLD is both a fortran +# INTEGER PARAMETER of value 0 and is #define'd to be 0). +# +# Additionally, since Open MPI provides the configure ability to +# compile out the entire MPI IO interface, all the IO +# handles/constants are generated in separate .h files in the +# non-preprocessor case, and included in relevant #if's in the +# preprocessor case. +# +# Files are generated in the following directories: +# +# ompi/include +# ompi/mpi/fortran/use-mpi-f08 +# + +import os +import sys +import re +from pathlib import Path + +# --- Data Definitions --- + +# Standard Handles +handles = { + 'MPI_COMM_WORLD': 0, + 'MPI_COMM_SELF': 1, + 'MPI_GROUP_EMPTY': 1, + 'MPI_ERRORS_ARE_FATAL': 1, + 'MPI_ERRORS_RETURN': 2, + 'MPI_ERRORS_ABORT': 3, + 'MPI_MAX': 1, + 'MPI_MIN': 2, + 'MPI_SUM': 3, + 'MPI_PROD': 4, + 'MPI_LAND': 5, + 'MPI_BAND': 6, + 'MPI_LOR': 7, + 'MPI_BOR': 8, + 'MPI_LXOR': 9, + 'MPI_BXOR': 10, + 'MPI_MAXLOC': 11, + 'MPI_MINLOC': 12, + 'MPI_REPLACE': 13, + 'MPI_NO_OP': 14, + 'MPI_COMM_NULL': 2, + 'MPI_DATATYPE_NULL': 0, + 'MPI_ERRHANDLER_NULL': 0, + 'MPI_GROUP_NULL': 0, + 'MPI_INFO_NULL': 0, + 'MPI_MESSAGE_NULL': 0, + 'MPI_OP_NULL': 0, + 'MPI_REQUEST_NULL': 0, + 'MPI_WIN_NULL': 0, + 'MPI_SESSION_NULL': 0, + 'MPI_BYTE': 1, + 'MPI_PACKED': 2, + 'MPI_UB': 3, + 'MPI_LB': 4, + 'MPI_CHARACTER': 5, + 'MPI_LOGICAL': 6, + 'MPI_INTEGER': 7, + 'MPI_INTEGER1': 8, + 'MPI_INTEGER2': 9, + 'MPI_INTEGER4': 10, + 'MPI_INTEGER8': 11, + 'MPI_INTEGER16': 12, + 'MPI_REAL': 13, + 'MPI_REAL4': 14, + 'MPI_REAL8': 15, + 'MPI_REAL16': 16, + 'MPI_DOUBLE_PRECISION': 17, + 'MPI_COMPLEX': 18, + 'MPI_COMPLEX8': 19, + 'MPI_COMPLEX16': 20, + 'MPI_COMPLEX32': 21, + 'MPI_DOUBLE_COMPLEX': 22, + 'MPI_2REAL': 23, + 'MPI_2DOUBLE_PRECISION': 24, + 'MPI_2INTEGER': 25, + 'MPI_2COMPLEX': 26, + 'MPI_2DOUBLE_COMPLEX': 27, + 'MPI_REAL2': 28, + 'MPI_LOGICAL1': 29, + 'MPI_LOGICAL2': 30, + 'MPI_LOGICAL4': 31, + 'MPI_LOGICAL8': 32, + 'MPI_WCHAR': 33, + 'MPI_CHAR': 34, + 'MPI_UNSIGNED_CHAR': 35, + 'MPI_SIGNED_CHAR': 36, + 'MPI_SHORT': 37, + 'MPI_UNSIGNED_SHORT': 38, + 'MPI_INT': 39, + 'MPI_UNSIGNED': 40, + 'MPI_LONG': 41, + 'MPI_UNSIGNED_LONG': 42, + 'MPI_LONG_LONG_INT': 43, + 'MPI_UNSIGNED_LONG_LONG': 44, + 'MPI_FLOAT': 45, + 'MPI_DOUBLE': 46, + 'MPI_LONG_DOUBLE': 47, + 'MPI_FLOAT_INT': 48, + 'MPI_DOUBLE_INT': 49, + 'MPI_LONG_DOUBLE_INT': 50, + 'MPI_LONG_INT': 51, + 'MPI_2INT': 52, + 'MPI_SHORT_INT': 53, + 'MPI_CXX_BOOL': 54, + 'MPI_CXX_FLOAT_COMPLEX': 55, + 'MPI_CXX_DOUBLE_COMPLEX': 56, + 'MPI_CXX_LONG_DOUBLE_COMPLEX': 57, + 'MPI_INT8_T': 58, + 'MPI_UINT8_T': 59, + 'MPI_INT16_T': 60, + 'MPI_UINT16_T': 61, + 'MPI_INT32_T': 62, + 'MPI_UINT32_T': 63, + 'MPI_INT64_T': 64, + 'MPI_UINT64_T': 65, + 'MPI_AINT': 66, + 'MPI_OFFSET': 67, + 'MPI_C_BOOL': 68, + 'MPI_C_COMPLEX': 69, + 'MPI_C_DOUBLE_COMPLEX': 70, + 'MPI_C_LONG_DOUBLE_COMPLEX': 71, + 'MPI_COUNT': 72, + 'MPI_COMPLEX4': 73, + 'MPI_MESSAGE_NO_PROC': 1, + 'MPI_INFO_ENV': 1, +} + +# Handle aliases +handles['MPI_LONG_LONG'] = handles['MPI_LONG_LONG_INT'] +handles['MPI_CXX_COMPLEX'] = handles['MPI_CXX_FLOAT_COMPLEX'] +handles['MPI_C_FLOAT_COMPLEX'] = handles['MPI_C_COMPLEX'] + +# IO Handles +io_handles = { + 'MPI_FILE_NULL': 0, +} + +# Standard Constants (populated later with version info) +constants = { + 'MPI_ANY_SOURCE': -1, + 'MPI_ANY_TAG': -1, + 'MPI_PROC_NULL': -2, + 'MPI_ROOT': -4, + 'MPI_UNDEFINED': -32766, + 'MPI_CART': 1, + 'MPI_GRAPH': 2, + 'MPI_DIST_GRAPH': 3, + 'MPI_KEYVAL_INVALID': -1, + 'MPI_SOURCE': 1, + 'MPI_TAG': 2, + 'MPI_ERROR': 3, + 'MPI_TAG_UB': 0, + 'MPI_HOST': 1, + 'MPI_IO': 2, + 'MPI_WTIME_IS_GLOBAL': 3, + 'MPI_APPNUM': 4, + 'MPI_LASTUSEDCODE': 5, + 'MPI_UNIVERSE_SIZE': 6, + 'MPI_WIN_BASE': 7, + 'MPI_WIN_SIZE': 8, + 'MPI_WIN_DISP_UNIT': 9, + 'MPI_WIN_CREATE_FLAVOR': 10, + 'MPI_WIN_MODEL': 11, + 'MPI_FT': 12, + 'MPI_WIN_FLAVOR_CREATE': 1, + 'MPI_WIN_FLAVOR_ALLOCATE': 2, + 'MPI_WIN_FLAVOR_DYNAMIC': 3, + 'MPI_WIN_FLAVOR_SHARED': 4, + 'MPI_WIN_UNIFIED': 0, + 'MPI_WIN_SEPARATE': 1, + 'MPI_BSEND_OVERHEAD': 128, + 'MPI_ORDER_C': 0, + 'MPI_ORDER_FORTRAN': 1, + 'MPI_DISTRIBUTE_BLOCK': 0, + 'MPI_DISTRIBUTE_CYCLIC': 1, + 'MPI_DISTRIBUTE_NONE': 2, + 'MPI_DISTRIBUTE_DFLT_DARG': -1, + 'MPI_TYPECLASS_INTEGER': 1, + 'MPI_TYPECLASS_REAL': 2, + 'MPI_TYPECLASS_COMPLEX': 3, + 'MPI_MODE_NOCHECK': 1, + 'MPI_MODE_NOPRECEDE': 2, + 'MPI_MODE_NOPUT': 4, + 'MPI_MODE_NOSTORE': 8, + 'MPI_MODE_NOSUCCEED': 16, + 'MPI_LOCK_EXCLUSIVE': 1, + 'MPI_LOCK_SHARED': 2, + 'MPI_THREAD_SINGLE': 0, + 'MPI_THREAD_FUNNELED': 1, + 'MPI_THREAD_SERIALIZED': 2, + 'MPI_THREAD_MULTIPLE': 3, + 'MPI_SUCCESS': 0, + 'MPI_ERR_BUFFER': 1, + 'MPI_ERR_COUNT': 2, + 'MPI_ERR_TYPE': 3, + 'MPI_ERR_TAG': 4, + 'MPI_ERR_COMM': 5, + 'MPI_ERR_RANK': 6, + 'MPI_ERR_REQUEST': 7, + 'MPI_ERR_ROOT': 8, + 'MPI_ERR_GROUP': 9, + 'MPI_ERR_OP': 10, + 'MPI_ERR_TOPOLOGY': 11, + 'MPI_ERR_DIMS': 12, + 'MPI_ERR_ARG': 13, + 'MPI_ERR_UNKNOWN': 14, + 'MPI_ERR_TRUNCATE': 15, + 'MPI_ERR_OTHER': 16, + 'MPI_ERR_INTERN': 17, + 'MPI_ERR_IN_STATUS': 18, + 'MPI_ERR_PENDING': 19, + 'MPI_ERR_ACCESS': 20, + 'MPI_ERR_AMODE': 21, + 'MPI_ERR_ASSERT': 22, + 'MPI_ERR_BAD_FILE': 23, + 'MPI_ERR_BASE': 24, + 'MPI_ERR_CONVERSION': 25, + 'MPI_ERR_DISP': 26, + 'MPI_ERR_DUP_DATAREP': 27, + 'MPI_ERR_FILE_EXISTS': 28, + 'MPI_ERR_FILE_IN_USE': 29, + 'MPI_ERR_FILE': 30, + 'MPI_ERR_INFO_KEY': 31, + 'MPI_ERR_INFO_NOKEY': 32, + 'MPI_ERR_INFO_VALUE': 33, + 'MPI_ERR_INFO': 34, + 'MPI_ERR_IO': 35, + 'MPI_ERR_KEYVAL': 36, + 'MPI_ERR_LOCKTYPE': 37, + 'MPI_ERR_NAME': 38, + 'MPI_ERR_NO_MEM': 39, + 'MPI_ERR_NOT_SAME': 40, + 'MPI_ERR_NO_SPACE': 41, + 'MPI_ERR_NO_SUCH_FILE': 42, + 'MPI_ERR_PORT': 43, + 'MPI_ERR_PROC_ABORTED': 74, + 'MPI_ERR_QUOTA': 44, + 'MPI_ERR_READ_ONLY': 45, + 'MPI_ERR_RMA_CONFLICT': 46, + 'MPI_ERR_RMA_SYNC': 47, + 'MPI_ERR_SERVICE': 48, + 'MPI_ERR_SIZE': 49, + 'MPI_ERR_SPAWN': 50, + 'MPI_ERR_UNSUPPORTED_DATAREP': 51, + 'MPI_ERR_UNSUPPORTED_OPERATION': 52, + 'MPI_ERR_WIN': 53, + 'MPI_ERR_PROC_FAILED': 75, + 'MPI_ERR_PROC_FAILED_PENDING': 76, + 'MPI_ERR_REVOKED': 77, + 'MPI_T_ERR_MEMORY': 54, + 'MPI_T_ERR_NOT_INITIALIZED': 55, + 'MPI_T_ERR_CANNOT_INIT': 56, + 'MPI_T_ERR_INVALID_INDEX': 57, + 'MPI_T_ERR_INVALID_ITEM': 58, + 'MPI_T_ERR_INVALID_HANDLE': 59, + 'MPI_T_ERR_OUT_OF_HANDLES': 60, + 'MPI_T_ERR_OUT_OF_SESSIONS': 61, + 'MPI_T_ERR_INVALID_SESSION': 62, + 'MPI_T_ERR_CVAR_SET_NOT_NOW': 63, + 'MPI_T_ERR_CVAR_SET_NEVER': 64, + 'MPI_T_ERR_PVAR_NO_STARTSTOP': 65, + 'MPI_T_ERR_PVAR_NO_WRITE': 66, + 'MPI_T_ERR_PVAR_NO_ATOMIC': 67, + 'MPI_ERR_RMA_RANGE': 68, + 'MPI_ERR_RMA_ATTACH': 69, + 'MPI_ERR_RMA_FLAVOR': 70, + 'MPI_ERR_RMA_SHARED': 71, + 'MPI_T_ERR_INVALID': 72, + 'MPI_ERR_SESSION': 78, + 'MPI_ERR_VALUE_TOO_LARGE': 79, + 'MPI_ERR_LASTCODE': 92, + 'MPI_IDENT': 0, + 'MPI_CONGRUENT': 1, + 'MPI_SIMILAR': 2, + 'MPI_UNEQUAL': 3, + 'MPI_COMBINER_NAMED': 0, + 'MPI_COMBINER_DUP': 1, + 'MPI_COMBINER_CONTIGUOUS': 2, + 'MPI_COMBINER_VECTOR': 3, + 'MPI_COMBINER_HVECTOR_INTEGER': 4, + 'MPI_COMBINER_HVECTOR': 5, + 'MPI_COMBINER_INDEXED': 6, + 'MPI_COMBINER_HINDEXED_INTEGER': 7, + 'MPI_COMBINER_HINDEXED': 8, + 'MPI_COMBINER_INDEXED_BLOCK': 9, + 'MPI_COMBINER_STRUCT_INTEGER': 10, + 'MPI_COMBINER_STRUCT': 11, + 'MPI_COMBINER_SUBARRAY': 12, + 'MPI_COMBINER_DARRAY': 13, + 'MPI_COMBINER_F90_REAL': 14, + 'MPI_COMBINER_F90_COMPLEX': 15, + 'MPI_COMBINER_F90_INTEGER': 16, + 'MPI_COMBINER_RESIZED': 17, + 'MPI_COMBINER_HINDEXED_BLOCK': 18, + 'MPI_COMM_TYPE_SHARED': 0, + 'OMPI_COMM_TYPE_HWTHREAD': 1, + 'OMPI_COMM_TYPE_CORE': 2, + 'OMPI_COMM_TYPE_L1CACHE': 3, + 'OMPI_COMM_TYPE_L2CACHE': 4, + 'OMPI_COMM_TYPE_L3CACHE': 5, + 'OMPI_COMM_TYPE_SOCKET': 6, + 'OMPI_COMM_TYPE_NUMA': 7, + 'OMPI_COMM_TYPE_NODE': 0, + 'OMPI_COMM_TYPE_BOARD': 8, + 'OMPI_COMM_TYPE_HOST': 9, + 'OMPI_COMM_TYPE_CU': 10, + 'OMPI_COMM_TYPE_CLUSTER': 11, + 'MPI_COMM_TYPE_HW_UNGUIDED': 12, + 'MPI_COMM_TYPE_HW_GUIDED': 13, +} + +# IO Constants +io_constants = { + 'MPI_SEEK_SET': 600, + 'MPI_SEEK_CUR': 602, + 'MPI_SEEK_END': 604, + 'MPI_MODE_CREATE': 1, + 'MPI_MODE_RDONLY': 2, + 'MPI_MODE_WRONLY': 4, + 'MPI_MODE_RDWR': 8, + 'MPI_MODE_DELETE_ON_CLOSE': 16, + 'MPI_MODE_UNIQUE_OPEN': 32, + 'MPI_MODE_EXCL': 64, + 'MPI_MODE_APPEND': 128, + 'MPI_MODE_SEQUENTIAL': 256, +} + +# Large IO Constants (using MPI_OFFSET_KIND) +lio_constants = { + 'MPI_DISPLACEMENT_CURRENT': -54278278, +} + +# --- File Writing Logic --- + +def write_file_if_changed(filename, content): + # Writes content to filename only if file doesn't exist or content differs + filepath = Path(filename) + needs_write = True + if filepath.is_file(): + try: + existing_content = filepath.read_text() + if content == existing_content: + needs_write = False + except IOError as e: + print(f"Warning: Could not read existing file {filename}: {e}", file=sys.stderr) + # Proceed to write + + if needs_write: + try: + # Ensure directory exists + filepath.parent.mkdir(parents=True, exist_ok=True) + filepath.write_text(content) + print(f"created {filename}") + except IOError as e: + print(f"Error: Could not write to file {filename}: {e}", file=sys.stderr) + sys.exit(1) # Mimic Perl's die + else: + print(f"{filename} unchanged; not written") + +# --- Value Reading Logic --- + +def read_value_from_file(filename, key): + # Reads a value for a specific key=value line from a file + value = None + filepath = Path(filename) + try: + with open(filepath, 'r') as f: + for line in f: + match = re.match(rf"^{re.escape(key)}=(.*)", line) + if match: + value = match.group(1).strip() + break + except IOError as e: + print(f"Error: Couldn't open {filename}: {e}", file=sys.stderr) + sys.exit(1) # Mimic Perl's die + + if value is None: + print(f"Error: Did not find the string \"{key}\" in the file {filename}", file=sys.stderr) + sys.exit(1) # Mimic Perl's die + + # Attempt to convert to int if possible, otherwise keep as string + try: + return int(value) + except ValueError: + return value + +# --- Fortran File Generation --- + +fortran_header_template = """! -*- fortran -*- +! WARNING! THIS IS A GENERATED FILE!! +! ANY EDITS YOU PUT HERE WILL BE LOST! +! ==> Instead, edit topdir/ompi/include/mpif-values.py. + +! Copyright (c) 2004-2006 The Trustees of Indiana University and Indiana +! University Research and Technology +! Corporation. All rights reserved. +! Copyright (c) 2004-2016 The University of Tennessee and The University +! of Tennessee Research Foundation. All rights +! reserved. +! Copyright (c) 2004-2007 High Performance Computing Center Stuttgart, +! University of Stuttgart. All rights reserved. +! Copyright (c) 2004-2005 The Regents of the University of California. +! All rights reserved. +! Copyright (c) 2006-2012 Cisco Systems, Inc. All rights reserved. +! Copyright (c) 2009-2012 Oak Ridge National Labs. All rights reserved. +! Copyright (c) 2016 Research Organization for Information Science +! and Technology (RIST). All rights reserved. +! Copyright (c) 2022 IBM Corporation. All rights reserved. +! $COPYRIGHT$ +! +! Additional copyrights may follow +! +! $HEADER$ +! + +""" + +def generate_fortran_file(header, vals, lvals, filename): + # Generates a Fortran include file with PARAMETER statements + content = header + # Declarations + for key in sorted(vals.keys()): + content += f" integer {key}\n" + for key in sorted(lvals.keys()): + content += f" integer(KIND=MPI_OFFSET_KIND) {key}\n" + content += "\n" + # Parameters + for key in sorted(vals.keys()): + content += f" parameter ({key}={vals[key]})\n" + for key in sorted(lvals.keys()): + content += f" parameter ({key}={lvals[key]})\n" + + write_file_if_changed(filename, content) + +# --- C Preprocessor File Generation --- + +c_header_template = """! WARNING! THIS IS A GENERATED FILE!! +! ANY EDITS YOU PUT HERE WILL BE LOST! +! Instead, edit topdir/ompi/include/mpif-values.py. +! + +! +! Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana +! University Research and Technology +! Corporation. All rights reserved. +! Copyright (c) 2004-2016 The University of Tennessee and The University +! of Tennessee Research Foundation. All rights +! reserved. +! Copyright (c) 2004-2007 High Performance Computing Center Stuttgart, +! University of Stuttgart. All rights reserved. +! Copyright (c) 2004-2005 The Regents of the University of California. +! All rights reserved. +! Copyright (c) 2007-2009 Cisco Systems, Inc. All rights reserved. +! Copyright (c) 2008-2009 Sun Microsystems, Inc. All rights reserved. +! Copyright (c) 2009-2012 Oak Ridge National Labs. All rights reserved. +! Copyright (c) 2009-2012 Los Alamos National Security, LLC. +! All rights reserved. +! Copyright (c) 2016-2019 Research Organization for Information Science +! and Technology (RIST). All rights reserved. +! Copyright (c) 2022 IBM Corporation. All rights reserved. +! $COPYRIGHT$ +! +! Additional copyrights may follow +! +! $HEADER$ +! + +#ifndef USE_MPI_F08_CONSTANTS_H +#define USE_MPI_F08_CONSTANTS_H + +""" + +def generate_c_header_file(filename): + # Generates the mpi-f08-constants.h C preprocessor file + content = c_header_template + + for key in sorted(constants.keys()): + content += f"#define OMPI_{key} {constants[key]}\n" + content += "\n" + for key in sorted(handles.keys()): + content += f"#define OMPI_{key} {handles[key]}\n" + content += "\n" # Explicitly add newline like Perl script + + for key in sorted(io_constants.keys()): + content += f"#define OMPI_{key} {io_constants[key]}\n" + for key in sorted(lio_constants.keys()): + content += f"#define OMPI_{key} {lio_constants[key]}\n" + content += "\n" + for key in sorted(io_handles.keys()): + content += f"#define OMPI_{key} {io_handles[key]}\n" + content += "\n" + content += "#endif /* USE_MPI_F08_CONSTANTS_H */\n" + + write_file_if_changed(filename, content) + + +# --- Main Script Logic --- + +def main(): + print("creating Fortran header files (with common constants)...") + + # Find the OMPI topdir + topdir = None + if Path("ompi/include/mpi.h.in").is_file(): + topdir = Path(".") + elif Path("../ompi/include/mpi.h.in").is_file(): + topdir = Path("..") + elif Path("../../ompi/include/mpi.h.in").is_file(): + topdir = Path("../..") + else: + print("Please run this script from the Open MPI topdir or topdir/include/mpi", file=sys.stderr) + print("Aborting.", file=sys.stderr) + sys.exit(1) + + # Read version info and update constants dict + version_file = topdir / "VERSION" + constants['MPI_VERSION'] = read_value_from_file(version_file, 'mpi_standard_version') + constants['MPI_SUBVERSION'] = read_value_from_file(version_file, 'mpi_standard_subversion') + + + # --- Generate Fortran Files --- + ompi_include_dir = topdir / "ompi/include" + generate_fortran_file(fortran_header_template, handles, {}, + ompi_include_dir / "mpif-handles.h") + generate_fortran_file(fortran_header_template, constants, {}, + ompi_include_dir / "mpif-constants.h") + generate_fortran_file(fortran_header_template, io_handles, {}, + ompi_include_dir / "mpif-io-handles.h") + generate_fortran_file(fortran_header_template, io_constants, lio_constants, + ompi_include_dir / "mpif-io-constants.h") + + # --- Generate C Preprocessor File --- + mpi_f08_mod_dir = topdir / "ompi/mpi/fortran/use-mpi-f08/mod" + generate_c_header_file(mpi_f08_mod_dir / "mpi-f08-constants.h") + + print("Done.") + sys.exit(0) + +if __name__ == "__main__": + main() diff --git a/ompi/mpi/fortran/base/Makefile.am b/ompi/mpi/fortran/base/Makefile.am index 7109e453c47..100fba8991c 100644 --- a/ompi/mpi/fortran/base/Makefile.am +++ b/ompi/mpi/fortran/base/Makefile.am @@ -12,6 +12,7 @@ # Copyright (c) 2006-2015 Cisco Systems, Inc. All rights reserved. # Copyright (c) 2015-2017 Research Organization for Information Science # and Technology (RIST). All rights reserved. +# Copyright (c) 2025 Jeffrey M. Squyres. All rights reserved. # $COPYRIGHT$ # # Additional copyrights may follow @@ -24,8 +25,8 @@ noinst_LTLIBRARIES = EXTRA_DIST = \ attr-fn-int-callback-interfaces.h \ conversion-fn-null-int-interface.h \ - gen-mpi-sizeof.pl \ - gen-mpi-mangling.pl + gen-mpi-sizeof.py \ + gen-mpi-mangling.py #----------------------------------------------------------------------------- diff --git a/ompi/mpi/fortran/base/gen-mpi-mangling.pl b/ompi/mpi/fortran/base/gen-mpi-mangling.pl deleted file mode 100755 index a049c625228..00000000000 --- a/ompi/mpi/fortran/base/gen-mpi-mangling.pl +++ /dev/null @@ -1,206 +0,0 @@ -#!/usr/bin/env perl -# -# Copyright (c) 2015 Research Organization for Information Science -# and Technology (RIST). All rights reserved. -# Copyright (c) 2015-2020 Cisco Systems, Inc. All rights reserved. -# $COPYRIGHT$ -# -# Subroutine to generate a bunch of Fortran declarations and symbols -# - -use strict; - -use Getopt::Long; - -my $caps_arg; -my $plain_arg; -my $single_underscore_arg; -my $double_underscore_arg; -my $help_arg = 0; - -&Getopt::Long::Configure("bundling"); -my $ok = Getopt::Long::GetOptions("caps=i" => \$caps_arg, - "plain=i" => \$plain_arg, - "single=i" => \$single_underscore_arg, - "double=i" => \$double_underscore_arg, - "help|h" => \$help_arg); - -if ($help_arg || !$ok) { - print "Usage: $0 [--caps|--plain|--single|--double] [--help]\n"; - exit(1 - $ok); -} - -my $file_c_constants_decl = "mpif-c-constants-decl.h"; -my $file_c_constants = "mpif-c-constants.h"; -my $file_f08_types = "mpif-f08-types.h"; - -# If we are not building fortran, then just make empty files -if ($caps_arg + $plain_arg + $single_underscore_arg + - $double_underscore_arg == 0) { - system("touch $file_c_constants_decl"); - system("touch $file_c_constants"); - system("touch $file_f08_types"); - exit(0); -} - -############################################################### - -# Declare a hash of all the Fortran sentinel values - -my $fortran; - -$fortran->{bottom} = { - c_type => "int", - c_name => "mpi_fortran_bottom", - f_type => "integer", - f_name => "MPI_BOTTOM", -}; -$fortran->{in_place} = { - c_type => "int", - c_name => "mpi_fortran_in_place", - f_type => "integer", - f_name => "MPI_IN_PLACE", -}; -$fortran->{unweighted} = { - c_type => "int", - c_name => "mpi_fortran_unweighted", - f_type => "integer, dimension(1)", - f_name => "MPI_UNWEIGHTED", -}; -$fortran->{weights_empty} = { - c_type => "int", - c_name => "mpi_fortran_weights_empty", - f_type => "integer, dimension(1)", - f_name => "MPI_WEIGHTS_EMPTY", -}; - -$fortran->{argv_null} = { - c_type => "char", - c_name => "mpi_fortran_argv_null", - f_type => "character, dimension(1)", - f_name => "MPI_ARGV_NULL", -}; -$fortran->{argvs_null} = { - c_type => "char", - c_name => "mpi_fortran_argvs_null", - f_type => "character, dimension(1, 1)", - f_name => "MPI_ARGVS_NULL", -}; - -$fortran->{errcodes_ignore} = { - c_type => "int", - c_name => "mpi_fortran_errcodes_ignore", - f_type => "integer, dimension(1)", - f_name => "MPI_ERRCODES_IGNORE", -}; -$fortran->{status_ignore} = { - c_type => "int *", - c_name => "mpi_fortran_status_ignore", - f_type => "type(MPI_STATUS)", - f_name => "MPI_STATUS_IGNORE", -}; -$fortran->{statuses_ignore} = { - c_type => "int *", - c_name => "mpi_fortran_statuses_ignore", - f_type => "type(MPI_STATUS)", - f_name => "MPI_STATUSES_IGNORE(1)", -}; - -############################################################### - -sub mangle { - my $name = shift; - - if ($plain_arg) { - return $name; - } elsif ($caps_arg) { - return uc($name); - } elsif ($single_underscore_arg) { - return $name . "_"; - } elsif ($double_underscore_arg) { - return $name . "__"; - } else { - die "Unknown name mangling type"; - } -} - -sub gen_c_constants_decl { - open(OUT, ">$file_c_constants_decl") || - die "Can't write to $file_c_constants_decl"; - - print OUT "/* WARNING: This is a generated file! Edits will be lost! */ -/* - * Copyright (c) 2015 Research Organization for Information Science - * and Technology (RIST). All rights reserved. - * Copyright (c) 2015 Cisco Systems, Inc. All rights reserved. - * \$COPYRIGHT\$ - * - * This file was generated by gen-mpi-mangling.pl - */ - -/* Note that the rationale for the types of each of these variables is - discussed in ompi/include/mpif-common.h. Do not change the types - without also changing ompi/runtime/ompi_mpi_init.c and - ompi/include/mpif-common.h. */\n\n"; - - foreach my $key (sort(keys(%{$fortran}))) { - my $f = $fortran->{$key}; - my $m = mangle($f->{c_name}); - print OUT "extern $f->{c_type} $m; -#define OMPI_IS_FORTRAN_" . uc($key) . "(addr) \\ - (addr == (void*) &$m)\n\n"; - } - - close(OUT); -} - -sub gen_c_constants { - open(OUT, ">$file_c_constants") || - die "Can't write to $file_c_constants"; - - print OUT "/* WARNING: This is a generated file! Edits will be lost! */ -/* - * Copyright (c) 2015 Research Organization for Information Science - * and Technology (RIST). All rights reserved. - * Copyright (c) 2015 Cisco Systems, Inc. All rights reserved. - * \$COPYRIGHT\$ - * - * This file was generated by gen-mpi-mangling.pl - */\n\n"; - - foreach my $key (sort(keys(%{$fortran}))) { - my $f = $fortran->{$key}; - my $m = mangle($f->{c_name}); - print OUT "$f->{c_type} $m;\n"; - } - - close (OUT); -} - -sub gen_f08_types { - open(OUT, ">$file_f08_types") || - die "Can't write to $file_f08_types"; - - print OUT "! WARNING: This is a generated file! Edits will be lost! */ -! -! Copyright (c) 2015 Research Organization for Information Science -! and Technology (RIST). All rights reserved. -! Copyright (c) 2015 Cisco Systems, Inc. All rights reserved. -! \$COPYRIGHT\$ -! -! This file was generated by gen-mpi-mangling.pl -!\n\n"; - - foreach my $key (sort(keys(%{$fortran}))) { - my $f = $fortran->{$key}; - print OUT "$f->{f_type}, bind(C, name=\"".mangle($f->{c_name})."\") :: $f->{f_name}\n"; - } - - close (OUT); -} - -gen_c_constants_decl(); -gen_c_constants(); -gen_f08_types(); - -exit(0); diff --git a/ompi/mpi/fortran/base/gen-mpi-mangling.py b/ompi/mpi/fortran/base/gen-mpi-mangling.py new file mode 100755 index 00000000000..4b090561ec1 --- /dev/null +++ b/ompi/mpi/fortran/base/gen-mpi-mangling.py @@ -0,0 +1,204 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2015 Research Organization for Information Science +# and Technology (RIST). All rights reserved. +# Copyright (c) 2015-2020 Cisco Systems, Inc. All rights reserved. +# Copyright (c) 2025 Jeffrey M. Squyres. All rights reserved. +# $COPYRIGHT$ +# +# Subroutine to generate a bunch of Fortran declarations and symbols +# + +import argparse +import os +import sys + +from pathlib import Path + +# File names +file_c_constants_decl = "mpif-c-constants-decl.h" +file_c_constants = "mpif-c-constants.h" +file_f08_types = "mpif-f08-types.h" + +# Header comment block +header_comment = """/* + * Copyright (c) 2015 Research Organization for Information Science + * and Technology (RIST). All rights reserved. + * Copyright (c) 2015-2020 Cisco Systems, Inc. All rights reserved. + * $COPYRIGHT$ + * + * This file was generated by gen-mpi-mangling.py. + */ +""" + +fortran_header_comment = """! +! Copyright (c) 2015 Research Organization for Information Science +! and Technology (RIST). All rights reserved. +! Copyright (c) 2015-2020 Cisco Systems, Inc. All rights reserved. +! $COPYRIGHT$ +! +! This file was generated by gen-mpi-mangling.py. +!""" + +def get_fortran_constants(args): + return { + 'bottom': { + 'c_type': "int", + 'c_name': "mpi_fortran_bottom", + 'f_type': "integer", + 'f_name': "MPI_BOTTOM", + }, + 'in_place': { + 'c_type': "int", + 'c_name': "mpi_fortran_in_place", + 'f_type': "integer", + 'f_name': "MPI_IN_PLACE", + }, + 'unweighted': { + 'c_type': "int", + 'c_name': "mpi_fortran_unweighted", + 'f_type': "integer, dimension(1)", + 'f_name': "MPI_UNWEIGHTED", + }, + 'weights_empty': { + 'c_type': "int", + 'c_name': "mpi_fortran_weights_empty", + 'f_type': "integer, dimension(1)", + 'f_name': "MPI_WEIGHTS_EMPTY", + }, + 'argv_null': { + 'c_type': "char", + 'c_name': "mpi_fortran_argv_null", + 'f_type': "character, dimension(1)", + 'f_name': "MPI_ARGV_NULL", + }, + 'argvs_null': { + 'c_type': "char", + 'c_name': "mpi_fortran_argvs_null", + 'f_type': "character, dimension(1, 1)", + 'f_name': "MPI_ARGVS_NULL", + }, + 'errcodes_ignore': { + 'c_type': "int", + 'c_name': "mpi_fortran_errcodes_ignore", + 'f_type': "integer, dimension(1)", + 'f_name': "MPI_ERRCODES_IGNORE", + }, + 'status_ignore': { + 'c_type': "int", + 'c_name': "mpi_fortran_status_ignore", + 'f_type': "type(MPI_STATUS)", + 'f_name': "MPI_STATUS_IGNORE", + }, + 'statuses_ignore': { + 'c_type': "int", + 'c_name': "mpi_fortran_statuses_ignore", + 'f_type': "type(MPI_STATUS)", + 'f_name': "MPI_STATUSES_IGNORE(1)", + }, + } + +def mangle(name, mangling_type): + # Mangles a C name based on the chosen Fortran mangling scheme + if mangling_type == 'plain': + return name + elif mangling_type == 'caps': + return name.upper() + elif mangling_type == 'single': + return name + "_" + elif mangling_type == 'double': + return name + "__" + else: + raise ValueError("Unknown name mangling type") + +def gen_c_constants_decl(mangling_type, fortran_constants): + # Generates the mpif-c-constants-decl.h file + with open(file_c_constants_decl, "w") as f: + f.write("/* WARNING: This is a generated file! Edits will be lost! */\n") + f.write(header_comment) + f.write("\n/* Note that the rationale for the types of each of these variables is\n") + f.write(" discussed in ompi/include/mpif-common.h. Do not change the types\n") + f.write(" without also changing ompi/runtime/ompi_mpi_init.c and\n") + f.write(" ompi/include/mpif-common.h. */\n\n") + + for key in sorted(fortran_constants.keys()): + const = fortran_constants[key] + mangled_name = mangle(const['c_name'], mangling_type) + f.write(f"extern {const['c_type']} {mangled_name};\n") + f.write(f"#define OMPI_IS_FORTRAN_{key.upper()}(addr) \\\n") + f.write(f" (addr == (void*) &{mangled_name})\n\n") + +def gen_c_constants(mangling_type, fortran_constants): + # Generates the mpif-c-constants.h file + with open(file_c_constants, "w") as f: + f.write("/* WARNING: This is a generated file! Edits will be lost! */\n") + f.write(header_comment) + f.write("\n") + + for key in sorted(fortran_constants.keys()): + const = fortran_constants[key] + mangled_name = mangle(const['c_name'], mangling_type) + f.write(f"{const['c_type']} {mangled_name};\n") + +def gen_f08_types(mangling_type, fortran_constants): + # Generates the mpif-f08-types.h file + with open(file_f08_types, "w") as f: + f.write("! WARNING: This is a generated file! Edits will be lost! */\n") + f.write(fortran_header_comment) + f.write("\n\n") + + for key in sorted(fortran_constants.keys()): + const = fortran_constants[key] + mangled_name = mangle(const['c_name'], mangling_type) + f.write(f"{const['f_type']}, bind(C, name=\"{mangled_name}\") :: {const['f_name']}\n") + + +def main(): + parser = argparse.ArgumentParser(description="Generate Fortran MPI mangling header files.") + parser.add_argument('--caps', type=int, default=0, + help='Use uppercase mangling') + parser.add_argument('--plain', type=int, default=0, + help='Use plain mangling (no change)') + parser.add_argument('--single', type=int, default=0, + help='Use single underscore suffix mangling') + parser.add_argument('--double', type=int, default=0, + help='Use double underscore suffix mangling') + + args = parser.parse_args() + + if args.caps + args.plain + args.single + args.double > 1: + print("Cannot enable more than one mangling style") + exit(1) + + mangling_type = None + if args.caps: + mangling_type = 'caps' + elif args.plain: + mangling_type = 'plain' + elif args.single: + mangling_type = 'single' + elif args.double: + mangling_type = 'double' + + # If no mangling type is selected, create empty files + if mangling_type is None: + print("No Fortran mangling scheme specified. Creating empty files.") + Path(file_c_constants_decl).touch() + Path(file_c_constants).touch() + Path(file_f08_types).touch() + sys.exit(0) + + # Generate the files based on the selected mangling type + try: + fortran_constants = get_fortran_constants() + gen_c_constants_decl(mangling_type, fortran_constants) + gen_c_constants(mangling_type, fortran_constants) + gen_f08_types(mangling_type, fortran_constants) + print(f"Generated files with '{mangling_type}' mangling.") + sys.exit(0) + except Exception as e: + print(f"Error generating files: {e}", file=sys.stderr) + sys.exit(1) + +if __name__ == "__main__": + main() diff --git a/ompi/mpi/fortran/base/gen-mpi-sizeof.pl b/ompi/mpi/fortran/base/gen-mpi-sizeof.pl deleted file mode 100755 index 17c37f272c5..00000000000 --- a/ompi/mpi/fortran/base/gen-mpi-sizeof.pl +++ /dev/null @@ -1,283 +0,0 @@ -#!/usr/bin/env perl -# -# Copyright (c) 2014-2015 Cisco Systems, Inc. All rights reserved. -# Copyright (c) 2015-2021 Research Organization for Information Science -# and Technology (RIST). All rights reserved. -# Copyright (c) 2022 IBM Corporation. All rights reserved. -# $COPYRIGHT$ -# -# Script to generate the overloaded MPI_SIZEOF interfaces and -# subroutine bodies for both the mpi and mpi_f08 modules. -# -# This script won't really be necessary (i.e., be a whole lot simpler) -# when Fortran compilers uniformly supprort TS 29113 -- i.e., they -# support dimension(..). Using dimension(..), you can have just *one* -# procedure for every type, and dimension(..) will resolve to both -# scalars and all possible ranks. -# -# But for the meantime, we generate for all ranks so that we support -# as many compilers as possible. :-\ (we don't check the compiler and -# see if it supports dimension(..) and do a different generation based -# on that, because we already have a zillion different options in the -# Fortran support -- let's just do MPI_Sizeof this one way in the name -# of simplicity...). -# - -use strict; - -use Getopt::Long; - -my $header_arg; -my $impl_arg; -my $ierror_arg; -my $maxrank_arg; -my $generate_arg; -my $mpi_arg; -my $mpi_real2; -my $mpi_iso_real16; -my $mpi_real16; -my $mpi_complex4; -my $mpi_complex32; -my $pmpi_arg; -my $help_arg = 0; -my $request_deprecate = 0; -my $mpi_version = 0; - -&Getopt::Long::Configure("bundling"); -my $ok = Getopt::Long::GetOptions("complex32=i" => \$mpi_complex32, - "complex4=i" => \$mpi_complex4, - "header=s" => \$header_arg, - "impl=s" => \$impl_arg, - "ierror=s" => \$ierror_arg, - "maxrank=s" => \$maxrank_arg, - "generate=i" => \$generate_arg, - "mpi" => \$mpi_arg, - "pmpi" => \$pmpi_arg, - "real16=i" => \$mpi_real16, - "real2=i" => \$mpi_real2, - "iso_real16=i" => \$mpi_iso_real16, - "request_deprecate=i" => \$request_deprecate, - "mpi_version=i" => \$mpi_version, - "help|h" => \$help_arg); - -die "Must specify header and/or impl filenames to output" - if (!defined($header_arg) && !defined($impl_arg)); -die "ierror handling must be optional or mandatory" - if (defined($generate_arg) && $generate_arg && - (lc($ierror_arg) ne "optional" && lc($ierror_arg) ne "mandatory")); -die "max array rank must be >= 4 and <=15" - if (defined($generate_arg) && $generate_arg && - (!defined($maxrank_arg) || $maxrank_arg < 4 || $maxrank_arg > 15)); -die "Must specify --pmpi and/or --mpi if --impl is specified" - if (defined($generate_arg) && $generate_arg && - (defined($impl_arg) && !defined($mpi_arg) && !defined($pmpi_arg))); -die "Must specify real2, iso_real16, real16, complex4, and complex32" - if (!defined($mpi_real2) || !defined($mpi_iso_real16) || !defined($mpi_real16) || - !defined($mpi_complex4) || !defined($mpi_complex32)); - -############################################################################# - -my $optional_ierror_param; -my $optional_ierror_statement; -if (lc($ierror_arg) eq "optional") { - $optional_ierror_param = ", OPTIONAL"; - $optional_ierror_statement = "IF (present(ierror)) "; -} - -my $indent = " "; - -############################################################################# - -my $subs; - -sub queue_sub { - my ($f_type, $suffix, $import_type) = @_; - - # Leave off the MPI/PMI prefix; we'll add that when outputting - my $sub_name = "Sizeof_$suffix"; - - # Make a hash for this subroutine - my $subr; - $subr->{name} = $sub_name; - my $start = "${indent}SUBROUTINE ^PREFIX^$sub_name^RANK^(x, size, ierror)\n"; - $start .= "${indent} USE, INTRINSIC :: iso_fortran_env, ONLY: " . uc($import_type) . "\n" - if (defined($import_type)); - # For long type names and large ranks, this first line gets very - # long and only narrowly squeezed in before 72 columns. Use no - # whitespace. - $start .= $indent . uc($f_type) . "^DIMENSION^::x -${indent} INTEGER, INTENT(OUT) :: size -${indent} INTEGER$optional_ierror_param, INTENT(OUT) :: ierror"; - $subr->{start} = $start; - $subr->{middle} = "${indent} size = storage_size(x) / 8 -${indent} ${optional_ierror_statement}ierror = 0"; - if (($mpi_version >= 4) && ($request_deprecate == 1)) { - $subr->{end} = "!GCC\$ ATTRIBUTES DEPRECATED :: ^PREFIX^$sub_name^RANK^\n"; - } - else { - $subr->{end} = ""; - } - $subr->{end} .= "${indent}END SUBROUTINE ^PREFIX^$sub_name^RANK^"; - - # Save it in the overall hash - $subs->{$sub_name} = $subr; -} - -sub generate { - my ($prefix, $sub_name, $rank, $want_body) = @_; - - my $subr; - # Deep copy - %{$subr} = %{$subs->{$sub_name}}; - - # Make the initial version - my $str = $subr->{start} . "\n"; - $str .= "\n" . $subr->{middle} . "\n" - if ($want_body); - $str .= $subr->{end} . "\n"; - - # Substitute in the relevant parameters - $str =~ s/\^PREFIX\^/$prefix/g; - - # If rank is 0, generate a scalar version. Otherwise, generate an - # array version. - if (0 == $rank) { - $str =~ s/\^RANK\^/_scalar/g; - $str =~ s/\^DIMENSION\^//; - } else { - $str =~ s/\^RANK\^/_r$rank/g; - my $dim; - my $d = $rank; - while ($d > 1) { - $dim .= "1,"; - --$d; - } - $str =~ s/\^DIMENSION\^/, DIMENSION($dim*)/; - } - - # All done - return $str; -} - -############################################################################# -# Main -############################################################################# - -for my $size (qw/8 16 32 64/) { - queue_sub("integer(int${size})", "int${size}", "int${size}"); -} -for my $size (qw/16 32 64 128/) { - if (!($size == 16 && $mpi_real2 == 0 && $mpi_iso_real16 == 0) && - !($size == 128 && $mpi_real16 == 0)) { - queue_sub("real(real${size})", "real${size}", "real${size}"); - } - if (!($size == 16 && $mpi_complex4 == 0 && $mpi_iso_real16 == 0) && - !($size == 128 && $mpi_complex32 == 0)) { - queue_sub("complex(real${size})", "complex${size}", "real${size}"); - } -} -if ($mpi_real2 == 1 && $mpi_iso_real16 == 0) { - queue_sub("real*2", "real16"); - queue_sub("complex*4", "complex16"); -} -queue_sub("character", "character"); -queue_sub("logical", "logical"); - -####################################################### - -sub output_content { - my ($prefix, $want_bodies) = @_; - - print OUT "${indent}INTERFACE ${prefix}Sizeof\n\n" - if (!$want_bodies); - - # Print all the module procedure lines - foreach my $sub_name (sort(keys(%{$subs}))) { - my $rank = 0; - while ($rank <= $maxrank_arg) { - my $str = generate($prefix, $sub_name, $rank, $want_bodies); - print OUT $str . "\n"; - ++$rank; - } - } - - print OUT "${indent}END INTERFACE ${prefix}Sizeof\n\n" - if (!$want_bodies); -} - -# Output each file -sub output_file { - my ($filename, $want_bodies) = @_; - - unlink($filename); - open(OUT, ">$filename") || die "Can't open $filename for writing"; - print OUT "! -*- f90 -*- -! WARNING: This is a generated file! Edits will be lost! -! -! Copyright (c) 2014 Cisco Systems, Inc. All rights reserved. -! \$COPYRIGHT\$ -! -! This file was generated by gen-mpi-sizeof.pl for all the MPI_SIZEOF -! interface possibilities for intrinsic types. Once TS 29113 is -! supported in all compilers, we can simply have *one* procedure for -! each type and use dimension(..) to indicate scalars+all array ranks. -! But until more compilers support this, we simply generate a -! procedure for scalars and all possible ranks in an attempt to -! support lots of Fortran compilers.\n\n"; - - # Only output if the generate arg is 0. Otherwise, output an - # empty .h file (that is still safe to include by mpif.h, but - # won't include the MPI_SIZEOF interface block). - if ($generate_arg) { - output_content("MPI_", $want_bodies) - if (!$want_bodies || - ($want_bodies && $mpi_arg)); - output_content("PMPI_", $want_bodies) - if (!$want_bodies || - ($want_bodies && $pmpi_arg)); - } else { - print OUT "! *** ATTENTION! -! -! Sad panda. -! -! This compiler does not support the Right Stuff to enable MPI_SIZEOF. -! Specifically: we need support for the INTERFACE keyword, -! ISO_FORTRAN_ENV, and the STORAGE_SIZE() intrinsic on all types. -! Apparently, this compiler does not support both of those things, so -! this file will be (effectively) blank (i.e., we didn't bother -! generating the necessary stuff for MPI_SIZEOF because the compiler -! doesn't support -! it). -! -! If you want support for MPI_SIZEOF, please use a different Fortran -! compiler to build Open MPI.\n\n"; - - if ($want_bodies) { - my $name = $pmpi_arg ? "pompi_sad_panda" : "ompi_sad_panda"; - print OUT "! -! Dummy subroutine, just so that there is *some* Fortran in this file -! (this is defensive programming: since the Fortran compiler doesn't -! support enough mojo, configure should set some AM_CONDITIONALs such -! that this file should not end up being compiled, but just in case -! that logic changes someday and this file *does* end up getting -! compiled, make sure that it's not entirely empty because some -! compilers are unhappy if there are no Fortran statements in this -! file). -subroutine $name() - implicit none - - print *, 'Open MPI is a sad panda because your Fortran compiler' - print *, 'does not support enough Fortran mojo for MPI_SIZEOF' -end subroutine $name\n\n"; - } - } - - close(OUT); -} - -output_file($header_arg, 0) - if (defined($header_arg)); -output_file($impl_arg, 1) - if (defined($impl_arg)); - -exit(0); diff --git a/ompi/mpi/fortran/base/gen-mpi-sizeof.py b/ompi/mpi/fortran/base/gen-mpi-sizeof.py new file mode 100755 index 00000000000..72597e0ed06 --- /dev/null +++ b/ompi/mpi/fortran/base/gen-mpi-sizeof.py @@ -0,0 +1,328 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2014-2015 Cisco Systems, Inc. All rights reserved. +# Copyright (c) 2015-2021 Research Organization for Information Science +# and Technology (RIST). All rights reserved. +# Copyright (c) 2022 IBM Corporation. All rights reserved. +# Copyright (c) 2025 Jeffrey M. Squyres. All rights reserved. +# $COPYRIGHT$ +# +# Script to generate the overloaded MPI_SIZEOF interfaces and +# subroutine bodies for both the mpi and mpi_f08 modules. +# +# This script won't really be necessary (i.e., be a whole lot simpler) +# when Fortran compilers uniformly supprort TS 29113 -- i.e., they +# support dimension(..). Using dimension(..), you can have just *one* +# procedure for every type, and dimension(..) will resolve to both +# scalars and all possible ranks. +# +# But for the meantime, we generate for all ranks so that we support +# as many compilers as possible. :-\ (we don't check the compiler and +# see if it supports dimension(..) and do a different generation based +# on that, because we already have a zillion different options in the +# Fortran support -- let's just do MPI_Sizeof this one way in the name +# of simplicity...). +# + +import argparse +import sys +import os +import copy + +from pathlib import Path + +# Global dictionary to store subroutine templates +subs = {} +indent = " " + +# --- Helper Functions --- + +def queue_sub(f_type, suffix, import_type=None, mpi_version=0, request_deprecate=False): + # Creates and stores a template for a Fortran subroutine + global subs + # Leave off the MPI/PMI prefix; we'll add that when outputting + sub_name = f"Sizeof_{suffix}" + + # Make a dictionary for this subroutine + subr = {} + subr['name'] = sub_name + start = f"{indent}SUBROUTINE ^PREFIX^{sub_name}^RANK^(x, size, ierror)\n" + if import_type: + start += f"{indent} USE, INTRINSIC :: iso_fortran_env, ONLY: {import_type.upper()}\n" + + # For long type names and large ranks, this first line gets very + # long and only narrowly squeezed in before 72 columns. Use no + # whitespace. + start += f"{indent}{f_type.upper()}^DIMENSION^::x\n" + start += f"{indent} INTEGER, INTENT(OUT) :: size\n" + start += f"{indent} INTEGER^IERROR_OPTIONAL^, INTENT(OUT) :: ierror" + subr['start'] = start + + subr['middle'] = f"{indent} size = storage_size(x) / 8\n" + subr['middle'] += f"{indent} ^IERROR_STATEMENT^ierror = 0" + + if mpi_version >= 4 and request_deprecate: + subr['end'] = f"!GCC$ ATTRIBUTES DEPRECATED :: ^PREFIX^{sub_name}^RANK^\n" + else: + subr['end'] = "" + subr['end'] += f"{indent}END SUBROUTINE ^PREFIX^{sub_name}^RANK^" + + # Save it in the overall dictionary + subs[sub_name] = subr + +def generate(prefix, sub_name, rank, want_body, optional_ierror_param, optional_ierror_statement): + # Generates the Fortran code for a specific subroutine + global subs + if sub_name not in subs: + # This can happen if a type was conditionally excluded + return "" + + # Deep copy the template + subr = copy.deepcopy(subs[sub_name]) + + # Make the initial version + str_out = subr['start'] + "\n" + if want_body: + str_out += "\n" + subr['middle'] + "\n" + str_out += subr['end'] + "\n" + + # Substitute in the relevant parameters + str_out = str_out.replace('^PREFIX^', prefix) + str_out = str_out.replace('^IERROR_OPTIONAL^', optional_ierror_param) + str_out = str_out.replace('^IERROR_STATEMENT^', optional_ierror_statement) + + + # If rank is 0, generate a scalar version. Otherwise, generate an + # array version. + if rank == 0: + str_out = str_out.replace('^RANK^', '_scalar') + str_out = str_out.replace('^DIMENSION^', '') + else: + str_out = str_out.replace('^RANK^', f'_r{rank}') + # Generate dimension string like "1,"*(rank-1) + "*" + dim = ",".join(['1'] * (rank - 1)) + if rank > 1: + dim += "," + dim += "*" # Add the final asterisk + str_out = str_out.replace('^DIMENSION^', f', DIMENSION({dim})') + + + # All done + return str_out + +def output_content(f, prefix, want_bodies, maxrank, optional_ierror_param, optional_ierror_statement): + # Writes the generated content (interfaces or bodies) to the file object + global subs + global indent + + if not want_bodies: + f.write(f"{indent}INTERFACE {prefix}Sizeof\n\n") + + # Print all the module procedure lines + for sub_name in sorted(subs.keys()): + rank = 0 + while rank <= maxrank: + str_generated = generate(prefix, sub_name, rank, want_bodies, + optional_ierror_param, optional_ierror_statement) + if str_generated: # Only write if generate didn't return empty + f.write(str_generated + "\n") + rank += 1 + + if not want_bodies: + f.write(f"{indent}END INTERFACE {prefix}Sizeof\n\n") + +def output_file(filename, want_bodies, args): + # Generates and writes the complete output file + global indent + + # Determine optional ierror parts + optional_ierror_param = "" + optional_ierror_statement = "" + if args.ierror and args.ierror.lower() == "optional": + optional_ierror_param = ", OPTIONAL" + optional_ierror_statement = "IF (present(ierror)) " + + + try: + # Delete existing file first, like Perl's unlink + if os.path.exists(filename): + os.unlink(filename) + + with open(filename, "w") as f: + f.write("""! -*- f90 -*- +! WARNING: This is a generated file! Edits will be lost! +! +! Copyright (c) 2014-2015 Cisco Systems, Inc. All rights reserved. +! Copyright (c) 2015-2021 Research Organization for Information Science +! and Technology (RIST). All rights reserved. +! Copyright (c) 2022 IBM Corporation. All rights reserved. +! $COPYRIGHT$ +! +! This file was generated by gen-mpi-sizeof.py for all the MPI_SIZEOF +! interface possibilities for intrinsic types. Once TS 29113 is +! supported in all compilers, we can simply have *one* procedure for +! each type and use dimension(..) to indicate scalars+all array ranks. +! But until more compilers support this, we simply generate a +! procedure for scalars and all possible ranks in an attempt to +! support lots of Fortran compilers. + +""") + + # Only output if the generate arg is True. Otherwise, output an + # empty .h file (that is still safe to include by mpif.h, but + # won't include the MPI_SIZEOF interface block). + if args.generate: + # Call queue_sub for all required types *before* outputting + for size in [8, 16, 32, 64]: + queue_sub(f"integer(int{size})", f"int{size}", f"int{size}", args.mpi_version, args.request_deprecate) + + for size in [16, 32, 64, 128]: + # Check conditions before queueing real types + queue_real = True + if size == 16 and not args.real2 and not args.iso_real16: + queue_real = False + if size == 128 and not args.real16: + queue_real = False + if queue_real: + queue_sub(f"real(real{size})", f"real{size}", f"real{size}", args.mpi_version, args.request_deprecate) + + # Check conditions before queueing complex types + queue_complex = True + if size == 16 and not args.complex4 and not args.iso_real16: + queue_complex = False + if size == 128 and not args.complex32: + queue_complex = False + if queue_complex: + queue_sub(f"complex(real{size})", f"complex{size}", f"real{size}", args.mpi_version, args.request_deprecate) + + # Handle special non-ISO types if needed + if args.real2 and not args.iso_real16: + queue_sub("real*2", "real16", mpi_version=args.mpi_version, request_deprecate=args.request_deprecate) # No import_type for non-standard + # Assume complex*4 goes with real*2 if iso_real16 is not used + if args.complex4 and not args.iso_real16: + queue_sub("complex*4", "complex16", mpi_version=args.mpi_version, request_deprecate=args.request_deprecate) # No import_type for non-standard + + queue_sub("character", "character", mpi_version=args.mpi_version, request_deprecate=args.request_deprecate) # No iso_fortran_env needed + queue_sub("logical", "logical", mpi_version=args.mpi_version, request_deprecate=args.request_deprecate) # No iso_fortran_env needed + + + # --- Generate Content --- + if not want_bodies or (want_bodies and args.mpi): + output_content(f, "MPI_", want_bodies, args.maxrank, + optional_ierror_param, optional_ierror_statement) + if not want_bodies or (want_bodies and args.pmpi): + output_content(f, "PMPI_", want_bodies, args.maxrank, + optional_ierror_param, optional_ierror_statement) + else: + # Sad panda message + f.write("""! *** ATTENTION! +! +! Sad panda. +! +! This compiler does not support the Right Stuff to enable MPI_SIZEOF. +! Specifically: we need support for the INTERFACE keyword, +! ISO_FORTRAN_ENV, and the STORAGE_SIZE() intrinsic on all types. +! Apparently, this compiler does not support both of those things, so +! this file will be (effectively) blank (i.e., we didn't bother +! generating the necessary stuff for MPI_SIZEOF because the compiler +! doesn't support +! it). +! +! If you want support for MPI_SIZEOF, please use a different Fortran +! compiler to build Open MPI. + +""") + if want_bodies: + name = "pompi_sad_panda" if args.pmpi else "ompi_sad_panda" + f.write(f"""! +! Dummy subroutine, just so that there is *some* Fortran in this file +! (this is defensive programming: since the Fortran compiler doesn't +! support enough mojo, configure should set some AM_CONDITIONALs such +! that this file should not end up being compiled, but just in case +! that logic changes someday and this file *does* end up getting +! compiled, make sure that it's not entirely empty because some +! compilers are unhappy if there are no Fortran statements in this +! file). +subroutine {name}() + implicit none + + print *, 'Open MPI is a sad panda because your Fortran compiler' + print *, 'does not support enough Fortran mojo for MPI_SIZEOF' +end subroutine {name} + +""") + except IOError as e: + print(f"Error writing to file {filename}: {e}", file=sys.stderr) + sys.exit(1) + +# --- Main Execution --- + +def main(): + parser = argparse.ArgumentParser(description="Generate Fortran MPI_SIZEOF interfaces and implementations.") + + # File outputs + parser.add_argument("--header", + help="Filename for the interface header output.") + parser.add_argument("--impl", + help="Filename for the implementation subroutine output.") + + # Control flags + parser.add_argument("--generate", type=int, default=0, + help="Actually generate MPI_SIZEOF (otherwise output 'sad panda').") + parser.add_argument("--ierror", choices=['optional', 'mandatory'], + help="How to handle the ierror parameter.") + parser.add_argument("--maxrank", type=int, default=7, + help="Maximum array rank to generate (default: 7, must be >=4, <=15).") + parser.add_argument("--mpi", action='store_true', + help="Generate MPI_ prefixed routines (for --impl).") + parser.add_argument("--pmpi", action='store_true', + help="Generate PMPI_ prefixed routines (for --impl).") + parser.add_argument("--request_deprecate", type=int, default=0, + help="Add GCC DEPRECATED attribute if MPI version >= 4") + parser.add_argument("--mpi_version", type=int, default=3, + help="MPI Standard version (e.g., 3 or 4)") + + # Type support flags + parser.add_argument("--complex32", type=int, default=0, + help="Enable Complex*32 support (real128).") + parser.add_argument("--complex4", type=int, default=0, + help="Enable Complex*4 support (real16).") + parser.add_argument("--real16", type=int, default=0, + help="Enable Real*16 support (real128).") + parser.add_argument("--real2", type=int, default=0, + help="Enable Real*2 support (real16).") + parser.add_argument("--iso_real16", type=int, default=0, + help="Use ISO_FORTRAN_ENV real16 (overrides real2/complex4 if both specified).") + + args = parser.parse_args() + + # --- Argument Validation --- + if not args.header and not args.impl: + parser.error("Must specify --header and/or --impl filenames to output.") + + if args.generate: + if not args.ierror: + parser.error("--ierror must be specified when --generate is used.") + if not (4 <= args.maxrank <= 15): + parser.error("--maxrank must be >= 4 and <= 15.") + if args.impl and not args.mpi and not args.pmpi: + parser.error("Must specify --pmpi and/or --mpi if --impl is specified.") + # Note: The Perl script checked for presence of all type flags, + # but argparse with action='store_true' defaults them to False if not given. + # The logic in output_file now handles the conditional generation based + # on these boolean flags. + + # --- File Generation --- + if args.header: + print(f"Generating header file: {args.header}") + output_file(args.header, want_bodies=False, args=args) + + if args.impl: + print(f"Generating implementation file: {args.impl}") + output_file(args.impl, want_bodies=True, args=args) + + print("Done.") + sys.exit(0) + +if __name__ == "__main__": + main() diff --git a/ompi/mpi/fortran/mpif-h/Makefile.am b/ompi/mpi/fortran/mpif-h/Makefile.am index ecbf93a9d43..d8a12a347ce 100644 --- a/ompi/mpi/fortran/mpif-h/Makefile.am +++ b/ompi/mpi/fortran/mpif-h/Makefile.am @@ -20,6 +20,7 @@ # Copyright (c) 2018 FUJITSU LIMITED. All rights reserved. # Copyright (c) 2021-2022 Triad National Security, LLC. All rights # reserved. +# Copyright (c) 2025 Jeffrey M. Squyres. All rights reserved. # # $COPYRIGHT$ # @@ -115,12 +116,12 @@ nodist_libmpi_mpifh_sizeof_la_SOURCES = sizeof_f.f90 lib@OMPI_LIBMPI_NAME@_mpifh_la_LIBADD += libmpi_mpifh_sizeof.la endif -sizeof_pl = $(top_srcdir)/ompi/mpi/fortran/base/gen-mpi-sizeof.pl +sizeof_py = $(top_srcdir)/ompi/mpi/fortran/base/gen-mpi-sizeof.py sizeof_f.f90: $(top_builddir)/config.status -sizeof_f.f90: $(sizeof_pl) +sizeof_f.f90: $(sizeof_py) sizeof_f.f90: - $(OMPI_V_GEN) $(sizeof_pl) \ + $(OMPI_V_GEN) $(python) $(sizeof_py) \ --impl=$@ --ierror=mandatory --mpi \ --maxrank=$(OMPI_FORTRAN_MAX_ARRAY_RANK) \ --generate=$(OMPI_FORTRAN_BUILD_SIZEOF) \ diff --git a/ompi/mpi/fortran/mpif-h/profile/Makefile.am b/ompi/mpi/fortran/mpif-h/profile/Makefile.am index 6957518a71c..4833aa99b32 100644 --- a/ompi/mpi/fortran/mpif-h/profile/Makefile.am +++ b/ompi/mpi/fortran/mpif-h/profile/Makefile.am @@ -20,6 +20,7 @@ # Copyright (c) 2018 FUJITSU LIMITED. All rights reserved. # Copyright (c) 2019-2022 Triad National Security, LLC. All rights # reserved. +# Copyright (c) 2025 Jeffrey M. Squyres. All rights reserved. # $COPYRIGHT$ # # Additional copyrights may follow @@ -486,12 +487,12 @@ nodist_libmpi_mpifh_psizeof_la_SOURCES = psizeof_f.f90 libmpi_mpifh_pmpi_la_LIBADD += libmpi_mpifh_psizeof.la endif -sizeof_pl=$(top_srcdir)/ompi/mpi/fortran/base/gen-mpi-sizeof.pl +sizeof_py=$(top_srcdir)/ompi/mpi/fortran/base/gen-mpi-sizeof.py psizeof_f.f90: $(top_builddir)/config.status -psizeof_f.f90: $(sizeof_pl) +psizeof_f.f90: $(sizeof_py) psizeof_f.f90: - $(OMPI_V_GEN) $(sizeof_pl) \ + $(OMPI_V_GEN) $(python) $(sizeof_py) \ --impl=$@ --ierror=mandatory --pmpi \ --maxrank=$(OMPI_FORTRAN_MAX_ARRAY_RANK) \ --generate=$(OMPI_FORTRAN_BUILD_SIZEOF) \ diff --git a/ompi/mpi/fortran/use-mpi-f08/Makefile.am b/ompi/mpi/fortran/use-mpi-f08/Makefile.am index 98e1826a1f4..45865f9fe7a 100644 --- a/ompi/mpi/fortran/use-mpi-f08/Makefile.am +++ b/ompi/mpi/fortran/use-mpi-f08/Makefile.am @@ -15,6 +15,7 @@ # reserved. # Copyright (c) 2020 Sandia National Laboratories. All rights reserved. # Copyright (c) 2022 IBM Corporation. All rights reserved. +# Copyright (c) 2025 Jeffrey M. Squyres. All rights reserved. # # $COPYRIGHT$ # @@ -79,12 +80,12 @@ mpi-f08.lo: sizeof_f08.h # configure tests. # -sizeof_pl=$(top_srcdir)/ompi/mpi/fortran/base/gen-mpi-sizeof.pl +sizeof_py=$(top_srcdir)/ompi/mpi/fortran/base/gen-mpi-sizeof.py sizeof_f08.h: $(top_builddir)/config.status -sizeof_f08.h: $(sizeof_pl) +sizeof_f08.h: $(sizeof_py) sizeof_f08.h: - $(OMPI_V_GEN) $(sizeof_pl) \ + $(OMPI_V_GEN) $(python) $(sizeof_py) \ --header=$@ --ierror=optional \ --maxrank=$(OMPI_FORTRAN_MAX_ARRAY_RANK) \ --generate=$(OMPI_FORTRAN_BUILD_SIZEOF) \ @@ -97,9 +98,9 @@ sizeof_f08.h: --request_deprecate=$(OMPI_FORTRAN_HAVE_ATTR_DEPRECATED) sizeof_f08.f90: $(top_builddir)/config.status -sizeof_f08.f90: $(sizeof_pl) +sizeof_f08.f90: $(sizeof_py) sizeof_f08.f90: - $(OMPI_V_GEN) $(sizeof_pl) \ + $(OMPI_V_GEN) $(python) $(sizeof_py) \ --impl=$@ --ierror=optional --mpi \ --maxrank=$(OMPI_FORTRAN_MAX_ARRAY_RANK) \ --generate=$(OMPI_FORTRAN_BUILD_SIZEOF) \ @@ -110,9 +111,9 @@ sizeof_f08.f90: --complex32=$(OMPI_HAVE_FORTRAN_COMPLEX32) psizeof_f08.f90: $(top_builddir)/config.status -psizeof_f08.f90: $(sizeof_pl) +psizeof_f08.f90: $(sizeof_py) psizeof_f08.f90: - $(OMPI_V_GEN) $(sizeof_pl) \ + $(OMPI_V_GEN) $(python) $(sizeof_py) \ --impl=$@ --ierror=optional --pmpi \ --maxrank=$(OMPI_FORTRAN_MAX_ARRAY_RANK) \ --generate=$(OMPI_FORTRAN_BUILD_SIZEOF) \ diff --git a/ompi/mpi/fortran/use-mpi-ignore-tkr/Makefile.am b/ompi/mpi/fortran/use-mpi-ignore-tkr/Makefile.am index ed23a0fdea7..4ee034df4e4 100644 --- a/ompi/mpi/fortran/use-mpi-ignore-tkr/Makefile.am +++ b/ompi/mpi/fortran/use-mpi-ignore-tkr/Makefile.am @@ -7,6 +7,7 @@ # # Copyright (c) 2018 FUJITSU LIMITED. All rights reserved. # Copyright (c) 2022 IBM Corporation. All rights reserved. +# Copyright (c) 2025 Jeffrey M. Squyres. All rights reserved. # $COPYRIGHT$ # # Additional copyrights may follow @@ -93,12 +94,12 @@ lib@OMPI_LIBMPI_NAME@_usempi_ignore_tkr_la_LDFLAGS = \ # configure tests. # -sizeof_pl=$(top_srcdir)/ompi/mpi/fortran/base/gen-mpi-sizeof.pl +sizeof_py=$(top_srcdir)/ompi/mpi/fortran/base/gen-mpi-sizeof.py mpi-ignore-tkr-sizeof.h: $(top_builddir)/config.status -mpi-ignore-tkr-sizeof.h: $(sizeof_pl) +mpi-ignore-tkr-sizeof.h: $(sizeof_py) mpi-ignore-tkr-sizeof.h: - $(OMPI_V_GEN) $(sizeof_pl) \ + $(OMPI_V_GEN) $(python) $(sizeof_py) \ --header=$@ --ierror=mandatory \ --maxrank=$(OMPI_FORTRAN_MAX_ARRAY_RANK) \ --generate=$(OMPI_FORTRAN_BUILD_SIZEOF) \ @@ -111,9 +112,9 @@ mpi-ignore-tkr-sizeof.h: --request_deprecate=$(OMPI_FORTRAN_HAVE_ATTR_DEPRECATED) mpi-ignore-tkr-sizeof.f90: $(top_builddir)/config.status -mpi-ignore-tkr-sizeof.f90: $(sizeof_pl) +mpi-ignore-tkr-sizeof.f90: $(sizeof_py) mpi-ignore-tkr-sizeof.f90: - $(OMPI_V_GEN) $(sizeof_pl) \ + $(OMPI_V_GEN) $(python) $(sizeof_py) \ --impl=$@ --ierror=mandatory --mpi --pmpi \ --maxrank=$(OMPI_FORTRAN_MAX_ARRAY_RANK) \ --generate=$(OMPI_FORTRAN_BUILD_SIZEOF) \ From ec2b164a513dc5550b58f2dffa8f91c002c539c3 Mon Sep 17 00:00:00 2001 From: Gilles Gouaillardet Date: Mon, 5 May 2025 08:26:57 -0400 Subject: [PATCH 2/2] fortran: fix common symbol sizes and alignments with mpif-h and usempi, MPI constants (e.g. MPI_COMM_WORLD) are all parts of a unique common block. Fortran compilers generally have alignment requirements for these (16 with gfortran, 32 with ifort or 64 with nvfortran to name a few), so pass these requirements to the actual symbols that are defined in the C code to make pick linkers (e.g. ubuntu) happy pandas. Such linkers also complain about the size of MPI_STATUS, so define these are arrays intead of pointer. Refs #13043 Thanks MJ Rutter for the report Signed-off-by: Gilles Gouaillardet --- config/ompi_fortran_get_alignment.m4 | 40 +++++++++++++++++++++ config/ompi_setup_mpi_fortran.m4 | 5 ++- ompi/include/Makefile.am | 7 ++-- ompi/mpi/fortran/base/gen-mpi-mangling.py | 43 ++++++++++++++--------- 4 files changed, 75 insertions(+), 20 deletions(-) diff --git a/config/ompi_fortran_get_alignment.m4 b/config/ompi_fortran_get_alignment.m4 index 824b6756f16..9ccca2a22fb 100644 --- a/config/ompi_fortran_get_alignment.m4 +++ b/config/ompi_fortran_get_alignment.m4 @@ -10,6 +10,8 @@ dnl Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, dnl University of Stuttgart. All rights reserved. dnl Copyright (c) 2004-2005 The Regents of the University of California. dnl All rights reserved. +dnl Copyright (c) 2025 Research Organization for Information Science +dnl and Technology (RIST). All rights reserved. dnl Copyright (c) 2010-2012 Cisco Systems, Inc. All rights reserved. dnl $COPYRIGHT$ dnl @@ -178,3 +180,41 @@ end program]])], AS_VAR_COPY([$2], [type_var]) AS_VAR_POPDEF([type_var])dnl ])dnl + +# OMPI_FORTRAN_GET_COMMON_ALIGNMENT(variable to set) +# ------------------------------------------ +AC_DEFUN([OMPI_FORTRAN_GET_COMMON_ALIGNMENT],[ + AS_IF([test $OMPI_TRY_FORTRAN_BINDINGS -gt $OMPI_FORTRAN_NO_BINDINGS], + [AC_CACHE_CHECK([alignment of Fortran common], ompi_cv_fortran_common_alignment, + [AC_LANG_PUSH([Fortran]) + AC_LINK_IFELSE([AC_LANG_SOURCE([[ program falignment + CHARACTER A,B + COMMON /AA/A + COMMON /BB/B + OPEN(UNIT=10, FILE="conftestval") + if (LOC(A) > LOC(B)) then + write (10,'(I5)') LOC(A)-LOC(B) + else + write (10,'(I5)') LOC(B)-LOC(A) + endif + CLOSE(10) + +end program]])], + [AS_IF([test "$cross_compiling" = "yes"], + [AC_MSG_ERROR([Can not determine common alignment when cross-compiling])], + [OPAL_LOG_COMMAND([./conftest], + [AS_VAR_SET(ompi_cv_fortran_common_alignment, [`cat conftestval`])], + [AC_MSG_ERROR([Could not determine common alignment])])])], + + [AC_MSG_WARN([Could not determine common alignment]) + AC_MSG_WARN([See config.log for details]) + AC_MSG_ERROR([Cannot continue])]) + rm -rf conftest* *.mod 2> /dev/null + AC_LANG_POP([Fortran])]) + + AS_VAR_COPY([$1], [ompi_cv_fortran_common_alignment])], + [AC_MSG_CHECKING([Fortran common alignment]) + $1=0 + AC_MSG_RESULT([skipped])]) + +])dnl diff --git a/config/ompi_setup_mpi_fortran.m4 b/config/ompi_setup_mpi_fortran.m4 index 758268b6f35..45a8db19317 100644 --- a/config/ompi_setup_mpi_fortran.m4 +++ b/config/ompi_setup_mpi_fortran.m4 @@ -15,7 +15,7 @@ dnl Copyright (c) 2006-2008 Sun Microsystems, Inc. All rights reserved. dnl Copyright (c) 2006-2007 Los Alamos National Security, LLC. All rights dnl reserved. dnl Copyright (c) 2009 Oak Ridge National Labs. All rights reserved. -dnl Copyright (c) 2014-2021 Research Organization for Information Science +dnl Copyright (c) 2014-2025 Research Organization for Information Science dnl and Technology (RIST). All rights reserved. dnl Copyright (c) 2016-2022 IBM Corporation. All rights reserved. dnl Copyright (c) 2018 FUJITSU LIMITED. All rights reserved. @@ -138,6 +138,9 @@ AC_DEFUN([OMPI_SETUP_MPI_FORTRAN],[ AC_DEFINE([ompi_fortran_bogus_type_t], [int], [A bogus type that allows us to have sentinel type values that are still valid]) + OMPI_FORTRAN_GET_COMMON_ALIGNMENT([OMPI_FORTRAN_COMMON_ALIGNMENT]) + AC_SUBST([OMPI_FORTRAN_COMMON_ALIGNMENT]) + # We want to set the #define's for all of these, so invoke the macros # regardless of whether we have F77 support or not. OMPI_FORTRAN_CHECK([CHARACTER], [yes], diff --git a/ompi/include/Makefile.am b/ompi/include/Makefile.am index d8a55e38c59..f0226d146d6 100644 --- a/ompi/include/Makefile.am +++ b/ompi/include/Makefile.am @@ -11,7 +11,7 @@ # All rights reserved. # Copyright (c) 2006-2015 Cisco Systems, Inc. All rights reserved. # Copyright (c) 2009-2011 Oak Ridge National Labs. All rights reserved. -# Copyright (c) 2014-2021 Research Organization for Information Science +# Copyright (c) 2014-2025 Research Organization for Information Science # and Technology (RIST). All rights reserved. # Copyright (c) 2018 FUJITSU LIMITED. All rights reserved. # Copyright (c) 2022 IBM Corporation. All rights reserved. @@ -111,7 +111,10 @@ mpif-c-constants-decl.h: --caps $(OMPI_FORTRAN_CAPS) \ --plain $(OMPI_FORTRAN_PLAIN) \ --single $(OMPI_FORTRAN_SINGLE_UNDERSCORE) \ - --double $(OMPI_FORTRAN_DOUBLE_UNDERSCORE) + --double $(OMPI_FORTRAN_DOUBLE_UNDERSCORE) \ + --status-size $(OMPI_FORTRAN_STATUS_SIZE) \ + --align $(OMPI_FORTRAN_COMMON_ALIGNMENT) + if WANT_INSTALL_HEADERS ompidir = $(ompiincludedir) diff --git a/ompi/mpi/fortran/base/gen-mpi-mangling.py b/ompi/mpi/fortran/base/gen-mpi-mangling.py index 4b090561ec1..49d38bfc565 100755 --- a/ompi/mpi/fortran/base/gen-mpi-mangling.py +++ b/ompi/mpi/fortran/base/gen-mpi-mangling.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (c) 2015 Research Organization for Information Science +# Copyright (c) 2015-2025 Research Organization for Information Science # and Technology (RIST). All rights reserved. # Copyright (c) 2015-2020 Cisco Systems, Inc. All rights reserved. # Copyright (c) 2025 Jeffrey M. Squyres. All rights reserved. @@ -22,7 +22,7 @@ # Header comment block header_comment = """/* - * Copyright (c) 2015 Research Organization for Information Science + * Copyright (c) 2015-2025 Research Organization for Information Science * and Technology (RIST). All rights reserved. * Copyright (c) 2015-2020 Cisco Systems, Inc. All rights reserved. * $COPYRIGHT$ @@ -32,7 +32,7 @@ """ fortran_header_comment = """! -! Copyright (c) 2015 Research Organization for Information Science +! Copyright (c) 2015-2025 Research Organization for Information Science ! and Technology (RIST). All rights reserved. ! Copyright (c) 2015-2020 Cisco Systems, Inc. All rights reserved. ! $COPYRIGHT$ @@ -43,25 +43,25 @@ def get_fortran_constants(args): return { 'bottom': { - 'c_type': "int", + 'c_type': "MPI_Fint", 'c_name': "mpi_fortran_bottom", 'f_type': "integer", 'f_name': "MPI_BOTTOM", }, 'in_place': { - 'c_type': "int", + 'c_type': "MPI_Fint", 'c_name': "mpi_fortran_in_place", 'f_type': "integer", 'f_name': "MPI_IN_PLACE", }, 'unweighted': { - 'c_type': "int", + 'c_type': "MPI_Fint", 'c_name': "mpi_fortran_unweighted", 'f_type': "integer, dimension(1)", 'f_name': "MPI_UNWEIGHTED", }, 'weights_empty': { - 'c_type': "int", + 'c_type': "MPI_Fint", 'c_name': "mpi_fortran_weights_empty", 'f_type': "integer, dimension(1)", 'f_name': "MPI_WEIGHTS_EMPTY", @@ -79,19 +79,21 @@ def get_fortran_constants(args): 'f_name': "MPI_ARGVS_NULL", }, 'errcodes_ignore': { - 'c_type': "int", + 'c_type': "MPI_Fint", 'c_name': "mpi_fortran_errcodes_ignore", 'f_type': "integer, dimension(1)", 'f_name': "MPI_ERRCODES_IGNORE", }, 'status_ignore': { - 'c_type': "int", + 'c_type': "MPI_Fint", + 'c_dim' : f"[{args.status_size}]", 'c_name': "mpi_fortran_status_ignore", 'f_type': "type(MPI_STATUS)", 'f_name': "MPI_STATUS_IGNORE", }, 'statuses_ignore': { - 'c_type': "int", + 'c_type': "MPI_Fint", + 'c_dim' : f"[{args.status_size}]", 'c_name': "mpi_fortran_statuses_ignore", 'f_type': "type(MPI_STATUS)", 'f_name': "MPI_STATUSES_IGNORE(1)", @@ -111,7 +113,7 @@ def mangle(name, mangling_type): else: raise ValueError("Unknown name mangling type") -def gen_c_constants_decl(mangling_type, fortran_constants): +def gen_c_constants_decl(mangling_type, fortran_constants, args): # Generates the mpif-c-constants-decl.h file with open(file_c_constants_decl, "w") as f: f.write("/* WARNING: This is a generated file! Edits will be lost! */\n") @@ -124,11 +126,12 @@ def gen_c_constants_decl(mangling_type, fortran_constants): for key in sorted(fortran_constants.keys()): const = fortran_constants[key] mangled_name = mangle(const['c_name'], mangling_type) - f.write(f"extern {const['c_type']} {mangled_name};\n") + dim = const.get('c_dim', '') + f.write(f"extern {const['c_type']} {mangled_name}{dim};\n") f.write(f"#define OMPI_IS_FORTRAN_{key.upper()}(addr) \\\n") f.write(f" (addr == (void*) &{mangled_name})\n\n") -def gen_c_constants(mangling_type, fortran_constants): +def gen_c_constants(mangling_type, fortran_constants, args): # Generates the mpif-c-constants.h file with open(file_c_constants, "w") as f: f.write("/* WARNING: This is a generated file! Edits will be lost! */\n") @@ -137,8 +140,10 @@ def gen_c_constants(mangling_type, fortran_constants): for key in sorted(fortran_constants.keys()): const = fortran_constants[key] + align = f" __opal_attribute_aligned__({args.align}) " if args.align else ' ' + dim = const.get('c_dim', '') mangled_name = mangle(const['c_name'], mangling_type) - f.write(f"{const['c_type']} {mangled_name};\n") + f.write(f"{const['c_type']}{align}{mangled_name}{dim};\n") def gen_f08_types(mangling_type, fortran_constants): # Generates the mpif-f08-types.h file @@ -163,6 +168,10 @@ def main(): help='Use single underscore suffix mangling') parser.add_argument('--double', type=int, default=0, help='Use double underscore suffix mangling') + parser.add_argument('--status-size', type=int, default=0, + help='Length of the Fortran MPI_Status array') + parser.add_argument('--align', type=int, default=0, + help='Alignment of Fortran intengers') args = parser.parse_args() @@ -190,9 +199,9 @@ def main(): # Generate the files based on the selected mangling type try: - fortran_constants = get_fortran_constants() - gen_c_constants_decl(mangling_type, fortran_constants) - gen_c_constants(mangling_type, fortran_constants) + fortran_constants = get_fortran_constants(args) + gen_c_constants_decl(mangling_type, fortran_constants, args) + gen_c_constants(mangling_type, fortran_constants, args) gen_f08_types(mangling_type, fortran_constants) print(f"Generated files with '{mangling_type}' mangling.") sys.exit(0)