Subject: bug#10972: Some troubles with gfortran 4.6 and libtool

From: Roger Ferrer Ibáñez <[email-masked]>
Date: Thu, 8 Mar 2012 23:41:26 +0100

Hi,

maybe this has been discussed earlier, if so I apologize in advance.

While looking into some link failures using libtool + gfortran 4.6 I
discovered that as of 4.6, "gfortran -v" emits its own libraries with
a blank between '-l' and the name of the library. As I understood
after skimming libtool source, in most places a form "-lname" is
assumed and no "-l name" is handled (at least in the places relevant
to my problem).

When using autoconf, libtool.m4-injected code, tries to discover
hidden libraries that might be used by the current compiler. There is
a moment where this command is executed

eval '$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "\-L"'

that expanded to the Fortran compiler (in my case gfortran 4.6) looks like

gfortran -shared -g -O2 -v conftest.o | /bin/grep '\-L'

If we manually check the output of gfortran 4.6 we see many lines but
the one I care is the first one

# This is gfortran 4.6
$ gfortran -shared -g -O2 -v conftest.o
Driving: gfortran -shared -g -O2 -v conftest.o -l gfortran -l m -shared-libgcc
... lots of lines follow ...

Note the blanks in "-l gfortran" and "-l m". Despite that blank, this
line is harmless since it is filtered by "$GREP "\-L"

[Note: In gfortran 4.5 this line appears like this

# This is gfortran 4.5
$ gfortran -shared -v -g -O2 conftest.o
Driving: gfortran -shared -v -g -O2 conftest.o -lgfortran -lm -shared-libgcc

Note too that neither gcc nor g++ output such "Driving:" line, this
seems to be a gfortran thing]

So far this is not a problem as that $GREP "\-L" saved us.

Things get messy, though, when using mpif90 (or another similar tool).
mpif90 is the driver/wrapper for easier compilation of MPI Fortran 90
applications. Such wrapper is usually provided by MPI implementations
(like MPICH or OpenMPI). If we tell mpif90 to use gfortran we see that
the above invocation is much more involved

# Tell OpenMPI's mpif90 to use gfortran 4.6
$ export OMPI_FC=gfortran
# Let's assume here we are running configure with FC=mpif90, at some
point the following command is run
$ mpif90 -shared -g -O2 -v conftest.o 2>&1 | grep $GREP "\-L"
Driving: gfortran -shared -g -O2 -v conftest.o -I/path_of_mpi/include
-I/path_of_mpi/lib -L/path_of_mpi/lib -lmpi_f90 -lmpi_f77 -lmpi -ldl
-Wl,--export-dynamic -lnsl -lutil -l gfortran -lm -ldl -l gfortran -l
m -shared-libgcc
... lots of lines follow ...

Note that the wrapper is adding an -Lflag, thus this line (with the
troublesome "-l gfortran" and "-l m") is not filtered by that $GREP
above.

When libtool code analizes "gfortran -v" output it assumes that the
form of a -l option is always "-lname". So it ends assuming it needs a
library named "" (the empty string). This causes that the "postdeps"
variable in the configure-generated libtool ends containing an empty
"-l" (among other legitimate "-lname" libraries). When linking the
application such "-l" flag is added by libtool and link fails.

I came up with several ideas to solve this issue but none seems
totally satisfying to me.

We could ask gfortran guys to revert to pre-4.6 behaviour of emitting
-lname instead of "-l name". Since "gfortran" understands "-l name"
this does not sound too realistic to me :)

Another approach is reducing the "-l name" problem to "-lname".
Replace every occurrence of the variable 'output_verbose_link_cmd' as
follows

 -      output_verbose_link_cmd='$CC -shared $CFLAGS -v
conftest.$objext 2>&1 | $GREP "\-L"'
+      output_verbose_link_cmd='$CC -shared $CFLAGS -v
conftest.$objext 2>&1 | $GREP "\-L" | $SED -e
"s/-l\s\+\(@<:@^-@:>@\S*\)/-l\1/g"'

This seems to work in my Linux machine (GNU sed powered).

I'm not expert in sed so maybe this is too naive, kludgy or plain
wrong. I assume that "-l" alone does not mean anything and must be
followed by a name. Concerning portability, I think that \s (for
whitespace) and \S (for non-whitespace) are GNU extensions. Although
not entirely equivalent they could be replaced by [ ] and [^ ].

Finally, another simpler approach would be filtering that line

+      output_verbose_link_cmd='$CC -shared $CFLAGS -v
conftest.$objext 2>&1 | $GREP -v "Driving:" | $GREP "\-L"

Kind regards,

P.S.: This problem is not a blocker since one can always fix the
configure-generated libtool, for instance using sed.

--
Roger Ferrer Ibáñez