AX_CHECK_VSCRIPT improves on the current detection method by adding a new check for false positives. On OSX, the current check fails, but only by accident: configure:14730: checking if library symbol versioning is available configure:14734: gcc -c -g -O2 conftest.c >&5 configure:14737: $? = 0 configure:14741: gcc -dynamiclib ${wl}-undefined ${wl}dynamic_lookup -o conftest.o -install_name /conftest -Wl,--version-script -Wl,conftest.map clang: error: no such file or directory: '${wl}-undefined' clang: error: no such file or directory: '${wl}dynamic_lookup' configure:14744: $? = 1 configure:14749: gcc -dynamiclib ${wl}-undefined ${wl}dynamic_lookup -o conftest.o -install_name /conftest -Wl,-M -Wl,conftest.map clang: error: no such file or directory: '${wl}-undefined' clang: error: no such file or directory: '${wl}dynamic_lookup' configure:14752: $? = 1 configure:14759: result: no Passing -Wl,-M,conftest.map on OSX may or may not actually cause a build failure: $ gcc conftest.c -o conftest -Wl,-M,conftest.map ; echo $? ld: warning: ignoring file conftest.map, file was built for unsupported file format ( 0x56 0x31 0x20 0x7B 0x20 0x67 0x6C 0x6F 0x62 0x61 0x6C 0x3A 0x20 0x24 0x32 0x3B ) which is not the architecture being linked (x86_64): conftest.map 0 $ gcc conftest.c -o conftest -Wl,-M,conftest-short.map ; echo $? ld: file too small (length=2) file 'conftest-short.map' for architecture x86_64 clang: error: linker command failed with exit code 1 (use -v to see invocation) 1 After getting a successful result from the above -M check, AX_CHECK_VSCRIPT will try another version script containing syntax errors. It will report a failure (unsupported) if the linker still accepts the malformed script. Signed-off-by: Kevin Cernekee <cernekee at gmail.com> --- Makefile.am | 4 +- configure.ac | 30 +---------- m4/ax_check_vscript.m4 | 142 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 145 insertions(+), 31 deletions(-) create mode 100644 m4/ax_check_vscript.m4 diff --git a/Makefile.am b/Makefile.am index d817afb..0a38785 100644 --- a/Makefile.am +++ b/Makefile.am @@ -75,8 +75,8 @@ endif libopenconnect_la_LDFLAGS = $(LT_VER_ARG) @APIMAJOR@:@APIMINOR@ -no-undefined noinst_HEADERS = openconnect-internal.h openconnect.h gnutls.h include_HEADERS = openconnect.h -if HAVE_SYMBOL_VERSIONING -libopenconnect_la_LDFLAGS += -Wl, at VERSION_SCRIPT_ARG@,libopenconnect.map +if HAVE_VSCRIPT +libopenconnect_la_LDFLAGS += @VSCRIPT_LDFLAGS@,libopenconnect.map libopenconnect_la_DEPENDENCIES = libopenconnect.map endif diff --git a/configure.ac b/configure.ac index d55b743..047b1c3 100644 --- a/configure.ac +++ b/configure.ac @@ -520,35 +520,7 @@ if test "$use_openbsd_libtool" = "true" && test -x /usr/bin/libtool; then fi AM_CONDITIONAL(OPENBSD_LIBTOOL, [ test "$use_openbsd_libtool" = "true" ]) -# Ick. This seems like it's likely to be very fragile, but I can't see a better -# way. I shall console myself with the observation that the failure mode isn't -# particularly horrible ? you just don't get symbol versioning if it fails. - -AC_ARG_ENABLE([symvers], - AS_HELP_STRING([--disable-symvers], - [disable library symbol versioning [default=auto]]), - [want_symvers=$enableval], - [want_symvers=yes]) - -symvers=no -if test "$enable_shared" = "yes" -a "$want_symvers" != "no" ; then - AC_MSG_CHECKING([if library symbol versioning is available]); - echo 'FOO { global: foo; local: *; };' > conftest.map - echo 'int foo = 0;' > conftest.$ac_ext - if AC_TRY_EVAL(ac_compile); then - soname=conftest - libobjs=conftest.$ac_objext - if AC_TRY_EVAL(archive_cmds ${wl}--version-script ${wl}conftest.map); then - AC_SUBST(VERSION_SCRIPT_ARG, [--version-script]) - symvers="yes (with --version-script)" - elif AC_TRY_EVAL(archive_cmds ${wl}-M ${wl}conftest.map); then - AC_SUBST(VERSION_SCRIPT_ARG, [-M]) - symvers="yes (with -M)" - fi - fi - AC_MSG_RESULT(${symvers}) -fi -AM_CONDITIONAL(HAVE_SYMBOL_VERSIONING, [test "${symvers}" != "no"]) +AX_CHECK_VSCRIPT PKG_CHECK_MODULES(LIBXML2, libxml-2.0) diff --git a/m4/ax_check_vscript.m4 b/m4/ax_check_vscript.m4 new file mode 100644 index 0000000..030da18 --- /dev/null +++ b/m4/ax_check_vscript.m4 @@ -0,0 +1,142 @@ +# =========================================================================== +# http://www.gnu.org/software/autoconf-archive/ax_check_vscript.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_CHECK_VSCRIPT +# +# DESCRIPTION +# +# Check whether the linker supports version scripts. Version scripts are +# used when building shared libraries to bind symbols to version nodes +# (helping to detect incompatibilities) or to limit the visibility of +# non-public symbols. +# +# Output: +# +# If version scripts are supported, VSCRIPT_LDFLAGS will contain the +# appropriate flag to pass to the linker. On GNU systems this would +# typically be "-Wl,--version-script", and on Solaris it would +# typically be "-Wl,-M". +# +# Two Automake conditionals are also set: +# +# HAVE_VSCRIPT is true if the linker supports version scripts with +# entries that use simple wildcards, like "local: *". +# +# HAVE_VSCRIPT_COMPLEX is true if the linker supports version scripts with +# pattern matching wildcards, like "global: Java_*". +# +# On systems that do not support symbol versioning, such as Mac OS X, both +# conditionals will be false. They will also be false if the user passes +# "--disable-symvers" on the configure command line. +# +# Example: +# +# configure.ac: +# +# AX_CHECK_VSCRIPT +# +# Makefile.am: +# +# if HAVE_VSCRIPT +# libfoo_la_LDFLAGS += $(VSCRIPT_LDFLAGS), at srcdir@/libfoo.map +# endif +# +# if HAVE_VSCRIPT_COMPLEX +# libbar_la_LDFLAGS += $(VSCRIPT_LDFLAGS), at srcdir@/libbar.map +# endif +# +# LICENSE +# +# Copyright (c) 2014 Kevin Cernekee <cernekee at gmail.com> +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 1 + +# _AX_CHECK_VSCRIPT(flag, global-sym, action-if-link-succeeds, [junk-file=no]) +AC_DEFUN([_AX_CHECK_VSCRIPT], [ + AC_LANG_PUSH([C]) + ax_check_vscript_save_flags="$LDFLAGS" + echo "V1 { global: $2; local: *; };" > conftest.map + AS_IF([test x$4 = xyes], [ + echo "{" >> conftest.map + ]) + LDFLAGS="$LDFLAGS -Wl,$1,conftest.map" + AC_LINK_IFELSE([AC_LANG_PROGRAM([[int show, hide;]], [])], [$3]) + LDFLAGS="$ax_check_vscript_save_flags" + rm -f conftest.map + AC_LANG_POP([C]) +]) dnl _AX_CHECK_VSCRIPT + +AC_DEFUN([AX_CHECK_VSCRIPT], [ + + AC_ARG_ENABLE([symvers], + AS_HELP_STRING([--disable-symvers], + [disable library symbol versioning [default=auto]]), + [want_symvers=$enableval], + [want_symvers=yes] + ) + + AS_IF([test x$want_symvers = xyes], [ + + dnl First test --version-script and -M with a simple wildcard. + + AC_CACHE_CHECK([linker version script flag], ax_cv_check_vscript_flag, [ + ax_cv_check_vscript_flag=unsupported + _AX_CHECK_VSCRIPT([--version-script], [show], [ + ax_cv_check_vscript_flag=--version-script + ]) + AS_IF([test x$ax_cv_check_vscript_flag = xunsupported], [ + _AX_CHECK_VSCRIPT([-M], [show], [ax_cv_check_vscript_flag=-M]) + ]) + + dnl The linker may interpret -M (no argument) as "produce a load map." + dnl If "-M conftest.map" doesn't fail when conftest.map contains + dnl obvious syntax errors, assume this is the case. + + AS_IF([test x$ax_cv_check_vscript_flag != xunsupported], [ + _AX_CHECK_VSCRIPT([$ax_cv_check_vscript_flag], [show], + [ax_cv_check_vscript_flag=unsupported], [yes]) + ]) + ]) + + dnl If the simple wildcard worked, retest with a complex wildcard. + + AS_IF([test x$ax_cv_check_vscript_flag != xunsupported], [ + ax_check_vscript_flag=$ax_cv_check_vscript_flag + AC_CACHE_CHECK([if version scripts can use complex wildcards], + ax_cv_check_vscript_complex_wildcards, [ + ax_cv_check_vscript_complex_wildcards=no + _AX_CHECK_VSCRIPT([$ax_cv_check_vscript_flag], [sh*], [ + ax_cv_check_vscript_complex_wildcards=yes]) + ]) + ax_check_vscript_complex_wildcards="$ax_cv_check_vscript_complex_wildcards" + ], [ + ax_check_vscript_flag= + ax_check_vscript_complex_wildcards=no + ]) + ], [ + AC_MSG_CHECKING([linker version script flag]) + AC_MSG_RESULT([disabled]) + + ax_check_vscript_flag= + ax_check_vscript_complex_wildcards=no + ]) + + AS_IF([test x$ax_check_vscript_flag != x], [ + VSCRIPT_LDFLAGS="-Wl,$ax_check_vscript_flag" + AC_SUBST([VSCRIPT_LDFLAGS]) + ]) + + AM_CONDITIONAL([HAVE_VSCRIPT], + [test x$ax_check_vscript_flag != x]) + AM_CONDITIONAL([HAVE_VSCRIPT_COMPLEX], + [test x$ax_check_vscript_complex_wildcards = xyes]) + +]) dnl AX_CHECK_VSCRIPT -- 2.1.1