Discussion:
Autoconf protype breaks GCC builtin inlining
Ferenc Wágner
2018-01-24 21:36:36 UTC
Permalink
Hi,

Since ceil() can be inlined when optimization is enabled, I use

AC_SEARCH_LIBS([ceil], [m], , [AC_MSG_ERROR([ceil not found])])
AC_SUBST([m_LIBS], [$LIBS])

to link against libm only when necessary (that is, when ceil is not
inlined). However, it does not work because GCC says in config.log:

conftest.c:76:6: warning: conflicting types for built-in function 'ceil'
char ceil ();
~~~~

and inlining is disabled, thus ceil becomes an undefined reference
without -lm. However, in the actual code where math.h is #included, the
above warning does not happen, ceil is inlined and I unnecessarily link
with -lm. How could I overcome this?

Please Cc me, I'm not subscribed.
--
Thanks,
Feri
Paul Eggert
2018-01-24 23:11:41 UTC
Permalink
Post by Ferenc Wágner
in the actual code where math.h is #included, the
above warning does not happen, ceil is inlined and I unnecessarily link
with -lm. How could I overcome this?
I don't see an easy workaround at the autoconf level. The compiler makes
the decision whether to inline, and this decision can depend on a lot of
things. The compiler's decision for the Autoconf-generated snippet might
disagree with the compiler's decision in the rest of your code, so this
is not something that one can safely test for at 'configure'-time.

To some extent you've lucked out because for you 'configure' tells
'make' to use -lm, so the worst that can happen for you is linking a
library unnecessarily. If it made the opposite mistake, the program
wouldn't link at all.
Zack Weinberg
2018-01-24 23:55:38 UTC
Permalink
Post by Ferenc Wágner
Hi,
Since ceil() can be inlined when optimization is enabled, I use
AC_SEARCH_LIBS([ceil], [m], , [AC_MSG_ERROR([ceil not found])])
AC_SUBST([m_LIBS], [$LIBS])
to link against libm only when necessary (that is, when ceil is not
conftest.c:76:6: warning: conflicting types for built-in function 'ceil'
char ceil ();
~~~~
and inlining is disabled, thus ceil becomes an undefined reference
without -lm. However, in the actual code where math.h is #included, the
above warning does not happen, ceil is inlined and I unnecessarily link
with -lm. How could I overcome this?
You could try setting -Wl,--as-needed (which really should be the
default) in your makefiles.

zw
Zack Weinberg
2018-01-25 00:00:45 UTC
Permalink
Post by Zack Weinberg
Post by Ferenc Wágner
Hi,
Since ceil() can be inlined when optimization is enabled, I use
AC_SEARCH_LIBS([ceil], [m], , [AC_MSG_ERROR([ceil not found])])
AC_SUBST([m_LIBS], [$LIBS])
to link against libm only when necessary (that is, when ceil is not
conftest.c:76:6: warning: conflicting types for built-in function 'ceil'
char ceil ();
~~~~
and inlining is disabled, thus ceil becomes an undefined reference
without -lm. However, in the actual code where math.h is #included, the
above warning does not happen, ceil is inlined and I unnecessarily link
with -lm. How could I overcome this?
You could try setting -Wl,--as-needed (which really should be the
default) in your makefiles.
That was unnecessarily cryptic, sorry.

The GNU linker accepts an option --as-needed which will make it
actually check whether shared libraries (such as libm) satisfy any
undefined symbols before adding them to the executable's list of
needed shared libraries. (This is not the default only for silly
historical reasons which let's not get into here.) If you add that to
your link commands in your Makefiles, libm will get pulled in only if
it's actually necessary, which is better than trying to probe for
whether it will actually be necessary in the configure script, since
inlining is somewhat unpredictable.. The compiler driver doesn't know
about it, though, so you have to spell it -Wl,--as-needed on your
actual command lines.

If you are using Automake, I believe you can just say

AM_LDFLAGS = -Wl,--as-needed

and get this applied to all of your executables.

zw
Ferenc Wágner
2018-01-25 16:47:25 UTC
Permalink
Post by Zack Weinberg
Post by Zack Weinberg
Post by Ferenc Wágner
Since ceil() can be inlined when optimization is enabled, I use
AC_SEARCH_LIBS([ceil], [m], , [AC_MSG_ERROR([ceil not found])])
AC_SUBST([m_LIBS], [$LIBS])
to link against libm only when necessary (that is, when ceil is not
conftest.c:76:6: warning: conflicting types for built-in function 'ceil'
char ceil ();
~~~~
and inlining is disabled, thus ceil becomes an undefined reference
without -lm. However, in the actual code where math.h is #included, the
above warning does not happen, ceil is inlined and I unnecessarily link
with -lm. How could I overcome this?
You could try setting -Wl,--as-needed (which really should be the
default) in your makefiles.
That was unnecessarily cryptic, sorry.
Nevermind, it was fine, I met --as-needed before, but I was somewhat
wary about using it for no concrete reason (FUD).
Post by Zack Weinberg
The GNU linker accepts an option --as-needed
Which brings us to a followup question: how to check whether it's safe
to use --as-needed? Is AX_CHECK_LINK_FLAG sufficient, should I check
for the effect somehow or what else is the best practice here?
Post by Zack Weinberg
(This is not the default only for silly historical reasons which let's
not get into here.)
Just out of curiosity, have to got a good link to the topic?
--
Thanks,
Feri
Jeffrey Walton
2018-01-25 17:06:42 UTC
Permalink
Post by Ferenc Wágner
Post by Zack Weinberg
...
Post by Zack Weinberg
You could try setting -Wl,--as-needed (which really should be the
default) in your makefiles.
That was unnecessarily cryptic, sorry.
Nevermind, it was fine, I met --as-needed before, but I was somewhat
wary about using it for no concrete reason (FUD).
Post by Zack Weinberg
The GNU linker accepts an option --as-needed
Testing for -Wl,--as-needed is like testing for other linker options
like -Wl,--exclude-libs,ALL. The extra gyrations below are due to
problems on AIX, OS X and Solaris. The tools report "illegal option"
or similar but Autotools does not detect the failure.

if test "$IS_APPLE_OS" -eq "0"; then
if test "$IS_SUN_OS" -eq "0"; then
if test "$IS_AIX_OS" -eq "0"; then

SAVED_LDFLAGS="$LDFLAGS"
LDFLAGS="-Wl,--as-needed"

AC_MSG_CHECKING([if $LDNAME supports $LDFLAGS])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([])],
[AC_MSG_RESULT([yes]); AC_SUBST([tr_RESULT], [1])],
[AC_MSG_RESULT([no]); AC_SUBST([tr_RESULT], [0])]
)

if test "$tr_RESULT" -eq "1"; then
AM_LDFLAGS="$AM_LDFLAGS $LDFLAGS"
fi

LDFLAGS="$SAVED_LDFLAGS"
fi
fi
fi
Ferenc Wágner
2018-01-25 22:44:36 UTC
Permalink
Post by Jeffrey Walton
AC_MSG_CHECKING([if $LDNAME supports $LDFLAGS])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([])],
[AC_MSG_RESULT([yes]); AC_SUBST([tr_RESULT], [1])],
[AC_MSG_RESULT([no]); AC_SUBST([tr_RESULT], [0])]
)
Thanks for the example! Why is AC_COMPILE_IFELSE enough? Don't you
have to invoke the linker itself to see if it accepts the option passed
through? And is the "-Wl," part applicable to most/all compilers?

BTW my other generic linker option is --enable-new-dtags. I'd be
interested to hear opinions about its usage as well. I found no other
way to run build-time test for a shared library dlopening modules.
(I know libtool can provide better portability than dlopen.)
--
Thanks,
Feri
Nick Bowler
2018-01-25 23:30:32 UTC
Permalink
Post by Ferenc Wágner
Post by Jeffrey Walton
AC_MSG_CHECKING([if $LDNAME supports $LDFLAGS])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([])],
[AC_MSG_RESULT([yes]); AC_SUBST([tr_RESULT], [1])],
[AC_MSG_RESULT([no]); AC_SUBST([tr_RESULT], [0])]
)
Thanks for the example! Why is AC_COMPILE_IFELSE enough?
It isn't. You will definitely should use AC_LINK_IFELSE to test if the
linker accepts the option. By itself that won't tell you if the option
actually did anything useful but that likely won't matter for this test.
Post by Ferenc Wágner
Don't you have to invoke the linker itself to see if it accepts the
option passed through? And is the "-Wl," part applicable to most/all
compilers?
There may exist toolchains where this won't work. They probably don't
support as-needed anyway. I wouldn't worry about it at all, since normally
this feature is strictly optional and the consequence of a false negative
on the test is essentially zero (the as-needed flag won't be set, the build
will work fine anyway, and your users are happy). This is in line with the
Autoconf philosophy.

Cheers,
Nick

Loading...