[J3] [EXTERNAL] [BULK] [SC22WG5.6552] bind(C) external linkage issues on MacOS

Clune, Thomas L. (GSFC-6101) thomas.l.clune at nasa.gov
Mon Mar 18 12:17:39 UTC 2024


I may have encountered something related to this last week.    Namely, I found that in some of my unit-tests modules I saw “S” for some MPI symbols and not in others when using gfortran-13 + openmpi 5 on M2 mac.       By trial and error, the distinction was whether I put USE MPI at the module level or instead inside individual procedures.

Caveat:  I was not actually using OpenMPI in this case, but rather a lightweight MPI mock that only included the interfaces needed for my tests and a handful of integer constants (e.g., MPI_STATUS_SIZE).

Since this was just test code, I merely moved the USE statements and moved on …


  *   Tom

From: J3 <j3-bounces at mailman.j3-fortran.org> on behalf of j3 <j3 at mailman.j3-fortran.org>
Reply-To: j3 <j3 at mailman.j3-fortran.org>
Date: Friday, March 15, 2024 at 1:29 PM
To: WG5 <sc22wg5 at open-std.org>
Cc: Jeff Hammond <jehammond at nvidia.com>
Subject: [EXTERNAL] [BULK] [J3] [SC22WG5.6552] bind(C) external linkage issues on MacOS

CAUTION: This email originated from outside of NASA.  Please take care when clicking links or opening attachments.  Use the "Report Message" button to report suspicious messages to the NASA SOC.


This is both an FYI for those of you who use MacOS but also a possible identification of a problem in how we specify 19.5.1.5 Linkage association.

Apple has removed “-commons use_dylibs” in recent versions of MacOS.  This flag sets a non-default behavior of COMMON symbols (which include linkage associated bind(C) symbols that are not using obsolescent features) to be “U” (undefined) instead of “S” (uninitialized, small) https://linux.die.net/man/1/nm.

This flag is required to get a bind(C) module variable that points to a C global variable to work properly, as is potentially required by MPI.  There are many reports of failures online with both GCC and Intel compilers (I can only verify the former).

It has been noted that our definition of linkage association may not be adequate to interact with C shared libraries.  I don’t understand this topic well enough to have an opinion either way.

Has anybody else run into this or thought about it enough to know if there is a way to enhance our definition of linkage association so as to not require Fortran-specific linker options and behave more like C extern in shared libraries?

Thanks,

Jeff

jhammond at Jeff-M2 fortran % gcc -fPIC -shared extern2.c -o libxxx.so && gfortran -c extern.F90 && ld extern.o libxxx.so -L/opt/homebrew/Cellar/gcc/13.2.0/lib/gcc/current/  -lgfortran -commons use_dylibs -o extern && ./extern ; nm extern | grep MPI
MPIR_F08_MPI_IN_PLACE=0 &MPIR_F08_MPI_IN_PLACE=0x1003a4000 &MPIR_F08_MPI_IN_PLACE=4298784768
LOC(MPI_IN_PLACE)=           4298784768
LOC(buf)=           6168523360
sendbuf=0x1003a4000, sendbuf=4298784768
sendbuf is MPI_IN_PLACE? yes
recvbuf=0x16fac3260, recvbuf=6168523360
*count=1, *datatype=2, *op=3, *comm=4
         911
                 U _MPIR_F08_MPI_IN_PLACE
                 U _MPI_Allreduce


jhammond at Jeff-M2 fortran % gcc -fPIC -shared extern2.c -o libxxx.so && gfortran -c extern.F90 && ld extern.o libxxx.so -L/opt/homebrew/Cellar/gcc/13.2.0/lib/gcc/current/  -lgfortran  -o extern && ./extern ; nm extern | grep MPI
MPIR_F08_MPI_IN_PLACE=0 &MPIR_F08_MPI_IN_PLACE=0x102b1c000 &MPIR_F08_MPI_IN_PLACE=4340170752
LOC(MPI_IN_PLACE)=           4339777664
LOC(buf)=           6127137376
sendbuf=0x102abc080, sendbuf=4339777664
sendbuf is MPI_IN_PLACE? no
recvbuf=0x16d34b260, recvbuf=6127137376
*count=1, *datatype=2, *op=3, *comm=4
         911
0000000100008080 S _MPIR_F08_MPI_IN_PLACE
                 U _MPI_Allreduce


==> extern2.c <==
#include <stdio.h>
#include <stdint.h>

int MPIR_F08_MPI_IN_PLACE;

void p(void)
{
    printf("MPIR_F08_MPI_IN_PLACE=%d &MPIR_F08_MPI_IN_PLACE=%p &MPIR_F08_MPI_IN_PLACE=%zu\n",
            MPIR_F08_MPI_IN_PLACE,   &MPIR_F08_MPI_IN_PLACE,   (intptr_t)&MPIR_F08_MPI_IN_PLACE);
}

void MPI_Allreduce(void ** sendbuf, void ** recvbuf,
                   int * count, int * datatype,
                   int * op, int * comm, int * ierror)
{
    printf("sendbuf=%p, sendbuf=%zu\n", sendbuf, (intptr_t)sendbuf);
    printf("sendbuf is MPI_IN_PLACE? %s\n",
           (intptr_t)sendbuf==(intptr_t)&MPIR_F08_MPI_IN_PLACE ? "yes" : "no");
    printf("recvbuf=%p, recvbuf=%zu\n", recvbuf, (intptr_t)recvbuf);
    printf("*count=%d, *datatype=%d, *op=%d, *comm=%d\n",
            *count, *datatype, *op, *comm);
    *ierror = 911;
}

==> extern.F90 <==
module mpi
    use iso_c_binding
    !type(c_ptr), bind(C,name="MPI_F_IN_PLACE") :: MPI_IN_PLACE
    integer(c_int), bind(C, name="MPIR_F08_MPI_IN_PLACE"), target :: MPI_IN_PLACE
    interface
        subroutine p() bind(C,name="p")
        end subroutine
    end interface
    interface
        SUBROUTINE MPI_ALLREDUCE(SENDBUF, RECVBUF, COUNT, DATATYPE, OP, COMM, IERROR) &
                   bind(C,name="MPI_Allreduce")
            use iso_c_binding
            import :: MPI_IN_PLACE
            !DEC$ ATTRIBUTES NO_ARG_CHECK :: sendbuf,recvbuf
            !GCC$ ATTRIBUTES NO_ARG_CHECK :: sendbuf,recvbuf
            !$PRAGMA IGNORE_TKR sendbuf,recvbuf
            !DIR$ IGNORE_TKR sendbuf,recvbuf
            !IBM* IGNORE_TKR sendbuf,recvbuf
            INTEGER(kind=c_int) :: SENDBUF(*), RECVBUF(*)
            INTEGER(kind=c_int) :: COUNT, DATATYPE, OP, COMM, IERROR
        END SUBROUTINE MPI_ALLREDUCE
    end interface
end module mpi

program main
    use mpi
    implicit none
    real :: buf(100)
    integer :: ierror
    call p
    buf = 17
    print*,'LOC(MPI_IN_PLACE)=',LOC(MPI_IN_PLACE)
    print*,'LOC(buf)=',LOC(buf)
    call MPI_ALLREDUCE(MPI_IN_PLACE,buf,1,2,3,4,ierror)
    print*,ierror
end program main
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mailman.j3-fortran.org/pipermail/j3/attachments/20240318/b45a738c/attachment.htm>


More information about the J3 mailing list