Skip to content

Commit a083686

Browse files
committed
ompi_setup_fc.m4: use -Wl,-ld_classic if supported
Per #12427, on MacOS, add -Wl,-ld_classic to the Fortran wrapper compiler if that flag is needed. Specifically, Open MPI has used -Wl,-commons,use_dylibs for decades to support common symbols (e.g., MPI_BOTTOM) in the Fortran bindings. There is a window of Xcode versions where this switch was effectively disabled; it effectively required the additional -Wl,-ld_classic switch to force the use of the "old" Apple linker (that still supported -Wl,-commons,use_dylibs). Update the configury to test whether we need -Wl,-ld_classic or not. Signed-off-by: Jeff Squyres <[email protected]>
1 parent 8b7e577 commit a083686

File tree

1 file changed

+157
-14
lines changed

1 file changed

+157
-14
lines changed

config/ompi_setup_fc.m4

Lines changed: 157 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,163 @@ AC_DEFUN_ONCE([_OMPI_SETUP_FC_COMPILER],[
5050

5151
#############################################################################
5252

53+
dnl On macOS with Xcode, test whether -Wl,-commons,use_dylibs works
54+
dnl by itself or whether it also needs -Wl,-ld_classic.
55+
dnl
56+
dnl * It seems to always work (by itself) when building shared
57+
dnl libraries.
58+
dnl * It seems to fail (by itself) when building shared libraries for
59+
dnl certain versions of Xcode. In these failure scenarios, we add
60+
dnl -Wl,-ld_classic to make it work.
61+
dnl
62+
dnl Note: the -ld_classic flag works with both static and shared
63+
dnl libraries, so it is safe to always do this test -- even if
64+
dnl we are only building static libraries.
65+
dnl
66+
dnl The history is that for a long time (decades),
67+
dnl -Wl,-commons,use_dylibs worked by itself. But then Apple decided
68+
dnl to remove support for it, and cause link-time errors with MPI
69+
dnl Fortran sentinel values (e.g., MPI_BOTTOM) because they are
70+
dnl implemented with Fortran common symbols. Later, Xcode v16
71+
dnl (re)added support for -Wl,commons,use_dylibs again. Hence, there
72+
dnl is a window of a few versions of Xcode that need the additional
73+
dnl -Wl,ld_classic flag to link/work properly.
74+
dnl
75+
dnl We have to use a slightly complex test code that will actually
76+
dnl fail if the version of Xcode being used requires -Wl,-ld_classic
77+
dnl with -Wl,-commons,use_dylibs.
78+
dnl
79+
dnl 1. Build a shared library (with C source code) with a common
80+
dnl symbol.
81+
dnl 2. Compile a Fortran program that calls a function in the shared
82+
dnl library, and link it against the shared library.
83+
AC_DEFUN([_OMPI_SETUP_FC_XCODE_COMMONS_LDFLAGS],[
84+
OPAL_VAR_SCOPE_PUSH([xcode_flags])
85+
86+
# This variable is used by the invoking macro to display the
87+
# results via AC RESULT (just to keep the symmetry of
88+
# MSG_CHECKING / RESULT in the same upper-level macro).
89+
OMPI_FORTRAN_WRAPPER_FLAGS=
90+
91+
xcode_flags="-Wl,-commons,use_dylibs"
92+
_OMPI_SETUP_FC_XCODE_COMMONS_LDFLAGS_BACKEND(
93+
[$xcode_flags],
94+
[OMPI_FORTRAN_WRAPPER_FLAGS=$xcode_flags], [])
95+
AS_IF([test -z "$OMPI_FORTRAN_WRAPPER_FLAGS"],
96+
[xcode_flags="-Wl,-commons,use_dylibs -Wl,-ld_classic"
97+
_OMPI_SETUP_FC_XCODE_COMMONS_LDFLAGS_BACKEND(
98+
[$xcode_flags],
99+
[OMPI_FORTRAN_WRAPPER_FLAGS=$xcode_flags], [])])
100+
AS_IF([test -z "$OMPI_FORTRAN_WRAPPER_FLAGS"],
101+
[OMPI_FORTRAN_WRAPPER_FLAGS="none"])
102+
103+
OPAL_VAR_SCOPE_POP
104+
])
105+
106+
dnl Companion to _OMPI SETUP_FC_XCODE_COMMONS_LDFLAGS;
107+
dnl see that macro for an explanation of this macro.
108+
dnl
109+
dnl $1: LDFLAGS to test
110+
dnl $2: action to perform upon success
111+
dnl $3: action to perform upon failure
112+
AC_DEFUN([_OMPI_SETUP_FC_XCODE_COMMONS_LDFLAGS_BACKEND],[
113+
OPAL_VAR_SCOPE_PUSH([xcode_happy xcode_dir LDFLAGS_save_xcode LIBS_save_xcode])
114+
115+
xcode_dir=conftest.$$
116+
rm -rf $xcode_dir
117+
mkdir -p $xcode_dir
118+
cd $xcode_dir
119+
120+
LIBS_save_xcode=$LIBS
121+
LDFLAGS_save_xcode=$LDFLAGS
122+
LDFLAGS="$LDFLAGS -L. $1"
123+
124+
# Note: we use COMPILE_IFELSE and LANG_SOURCE below, which assume
125+
# that confdefs.h exists. This is being invoked extremely early
126+
# in the configure sequence, so we haven't AC DEFINE'ed anything
127+
# yet, and therefore confdefs.h won't be automatically created
128+
# yet. So we'll make an empty confdefs.h to avoid some error
129+
# messages (it'll be removed with the whole tempdir, later).
130+
touch confdefs.h
131+
132+
# Step 1: make a C library with some public symbols
133+
xcode_happy=0
134+
AC_LANG_PUSH([C])
135+
AC_COMPILE_IFELSE([AC_LANG_SOURCE([[
136+
/* Must end the symbol in _ (remember: we are targeting the MacOS
137+
compilation environment, otherwise the Fortran linker will not find
138+
it, and will just create a new Fortran symbol for it */
139+
int ompi_mpi_bottom_ = 42;
140+
141+
void ompi_init_f(int *bogus);
142+
143+
/* Empty / useless function that ensures that this compilation
144+
unit will not be optimized out */
145+
void ompi_init_f(int *bogus)
146+
{
147+
/* Have a non-optimizable function body
148+
(but is otherwise worthless) */
149+
*bogus = ompi_mpi_bottom_;
150+
}
151+
]])],
152+
[ # If the above compiled successfully, Then use
153+
# conftest.OBJEXT to make the library. Note that
154+
# conftest.OBJEXT will automatically be deleted upon exit of
155+
# COMPILE_IFELSE.
156+
OPAL_LOG_COMMAND([$CC -dynamiclib -Wl,-undefined -Wl,dynamic_lookup $LDFLAGS conftest.$OBJEXT -o libconftest.dylib],
157+
[xcode_happy=1])])
158+
AC_LANG_POP
159+
160+
# Now compile and link a Fortran program against this shared
161+
# library
162+
AC_LANG_PUSH([Fortran])
163+
AS_IF([test $xcode_happy -eq 1],
164+
[LIBS="$LIBS -lconftest"
165+
AC_LINK_IFELSE([AC_LANG_SOURCE([
166+
program test
167+
integer :: mpi_bottom
168+
common/ompi_mpi_bottom/mpi_bottom
169+
170+
interface
171+
subroutine ompi_init(bogus) BIND(C, name="ompi_init_f")
172+
implicit none
173+
integer bogus
174+
end subroutine ompi_init
175+
end interface
176+
177+
integer bogus
178+
call ompi_init(bogus)
179+
end program
180+
])],
181+
182+
[],
183+
[xcode_happy=0])])
184+
AC_LANG_POP
185+
186+
# Exit the temp dir
187+
cd ..
188+
rm -rf $xcode_dir
189+
190+
# LIBS was set specifically for the artificial conditions of this
191+
# test, so reset it
192+
LIBS=$LIBS_save_xcode
193+
194+
AS_IF([test $xcode_happy -eq 1],
195+
[$2],
196+
[ # If we failed the test, reset LDFLAGS (if we passed the
197+
# test, leave LDFLAGS modified with the new flags so that
198+
# we use them to build Open MPI).
199+
LDFLAGS=$LDFLAGS_xcode_save
200+
$3])
201+
202+
OPAL_VAR_SCOPE_POP
203+
])
204+
205+
#############################################################################
206+
53207
# General Fortran compiler setup
54208
AC_DEFUN([OMPI_SETUP_FC],[
55-
OPAL_VAR_SCOPE_PUSH([ompi_fc_happy LDFLAGS_save fc_version])
209+
OPAL_VAR_SCOPE_PUSH([ompi_fc_happy LDFLAGS_save fc_version OMPI_FORTRAN_WRAPPER_FLAGS])
56210

57211
# Force the intro banner to be displayed first
58212
AC_REQUIRE([_OMPI_SETUP_FC_BANNER])
@@ -226,23 +380,12 @@ I = 3]])],
226380
])
227381
])
228382

229-
# Per #1982, on OS X, we may need some esoteric linker flags in the
383+
# Per Trac #1982, on OS X, we may need some esoteric linker flags in the
230384
# Fortran wrapper compiler.
231385
AC_MSG_CHECKING([to see if mpifort compiler needs additional linker flags])
232386
case "$host" in
233387
*apple-darwin*)
234-
# Test whether -Wl,-commons,use_dylibs works; if it does, use it.
235-
LDFLAGS_save=$LDFLAGS
236-
LDFLAGS="$LDFLAGS -Wl,-commons,use_dylibs"
237-
AC_LANG_PUSH([Fortran])
238-
AC_LINK_IFELSE([AC_LANG_SOURCE([[program test
239-
integer :: i
240-
end program]])],
241-
[OMPI_FORTRAN_WRAPPER_FLAGS="-Wl,-commons,use_dylibs"
242-
OPAL_WRAPPER_FLAGS_ADD([FCFLAGS], [$OMPI_FORTRAN_WRAPPER_FLAGS])],
243-
[OMPI_FORTRAN_WRAPPER_FLAGS=none])
244-
AC_LANG_POP([Fortran])
245-
LDFLAGS=$LDFLAGS_save
388+
_OMPI_SETUP_FC_XCODE_COMMONS_LDFLAGS
246389
AC_MSG_RESULT([$OMPI_FORTRAN_WRAPPER_FLAGS])
247390
;;
248391
*)

0 commit comments

Comments
 (0)