| # static.at -- test flags for static/dynamic linking -*- Autotest -*- |
| # |
| # Copyright (C) 2006, 2007, 2008 Free Software Foundation, Inc. |
| # Written by Ralf Wildenhues, 2006 |
| # |
| # This file is part of GNU Libtool. |
| # |
| # GNU Libtool is free software; you can redistribute it and/or |
| # modify it under the terms of the GNU General Public License as |
| # published by the Free Software Foundation; either version 2 of |
| # the License, or (at your option) any later version. |
| # |
| # GNU Libtool is distributed in the hope that it will be useful, |
| # but WITHOUT ANY WARRANTY; without even the implied warranty of |
| # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| # GNU General Public License for more details. |
| # |
| # You should have received a copy of the GNU General Public License |
| # along with GNU Libtool; see the file COPYING. If not, a copy |
| # can be downloaded from http://www.gnu.org/licenses/gpl.html, |
| # or obtained by writing to the Free Software Foundation, Inc., |
| # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
| #### |
| |
| ##### NOTES ##### |
| # |
| # - How do we test whether a library was linked statically? |
| # We could |
| # - try $NM on the program to see whether it includes the symbol definitions. |
| # disadvantage: for uninstalled programs, we may need to find out the name |
| # of the _real_ linked-against-uninstalled executable |
| # (.libs/prog vs .libs/lt-prog etc). |
| # - simply remove the libraries before execution. If the program still works, |
| # then the library was linked statically. |
| # -Does this work on all systems? |
| # -No, it will fail on AIX with non-rtl-created libraries: plain `-static' |
| # will only cause the linker not to consider `*.so' libraries, but only |
| # `*.a'. The latter, however, may still be shared images. :-/ |
| # `-all-static' still works, however. |
| # |
| # It will not work with dlpreloading until we fix its related bug. |
| # |
| # Let's try the latter until we know better. |
| |
| # - Test -Bstatic/-Bdynamic. It should work with all of: |
| # - (un)installed libtool libraries |
| # - non-libtool libraries |
| # - direct or pulled-in libraries |
| # - libraries of which there are only one kind available (TODO) |
| # (in the static case, should having only the shared one provoke failure?) |
| |
| # - Check no extraneous run paths have been added. |
| |
| # - make sure -Bstatic/-Bdynamic cannot be mixed with -all-static (TODO) |
| |
| # - should -Bstatic/-Bdynamic be mixable with -static or -static-libtool-libs? |
| # Semantics could be as follows: |
| # - `-static'/`-static-libtool-libs' set the default which is the initial |
| # value, then `-Bstatic'/`-Bdynamic' override that |
| # - `-Bdefault' resets to the default value given by the other switches. |
| |
| # - TODO: test exposure for dlopened and dlpreopened modules, |
| # without and with diverse static flag combinations. |
| |
| # - TODO: test other tags: C++ etc. |
| # (most likely the Sun compiler suite will be the only problem child). |
| |
| AT_SETUP([static linking flags for programs]) |
| AT_KEYWORDS([libtool]) |
| |
| LDFLAGS="$LDFLAGS -no-undefined" |
| prefix=`pwd`/inst |
| bindir=$prefix/bin |
| prefix1=`pwd`/inst1 |
| prefix2=`pwd`/inst2 |
| prefix3=`pwd`/inst3 |
| libdir1=$prefix1/lib |
| libdir2=$prefix2/lib |
| libdir3=$prefix3/lib |
| srcdir_broken=`pwd`/broken-src |
| prefix_broken=`pwd`/broken |
| libdir_broken=$prefix_broken/lib |
| bindir_broken=$prefix_broken/bin |
| |
| have_static=false |
| have_shared=false |
| per_deplib=false |
| $LIBTOOL --features | grep 'enable static libraries' >/dev/null && have_static=: |
| $LIBTOOL --features | grep 'enable shared libraries' >/dev/null && have_shared=: |
| eval `$LIBTOOL --config | |
| $EGREP '^(per_deplib_(static|dynamic)_flag|shlibpath_var|link_static_flag)='` |
| if test -n "$per_deplib_static_flag" && test -n "$per_deplib_dynamic_flag"; then |
| per_deplib=: |
| fi |
| # On GNU/Linux with --disable-static, m-all-static fails to link. |
| # What we'd like to state here is: if the user actively passed |
| # --disable-static (as opposed to: the libtool.m4 macros set |
| # enable_static=no), then they cannot expect -all-static to work. |
| # So we punt, knowing that we mangle enable_static on AIX only. |
| can_link_all_static=-all-static |
| case $host_os,$have_static,$link_static_flag in |
| aix*) ;; |
| *,false,?*) can_link_all_static= ;; |
| esac |
| |
| # Create broken libraries. They will later be moved to those |
| # directories where the respective libraries should be linked |
| # statically from. This detects both failure to link statically |
| # and failure to omit extraneous run paths. |
| mkdir $srcdir_broken $prefix_broken $libdir_broken |
| ( |
| cd $srcdir_broken |
| echo 'int this_should_not_be_linked_against() { return 0; }' > a.c |
| $LIBTOOL --mode=compile $CC $CPPFLAGS $CFLAGS -c a.c |
| for i in 1 1dep 2 2dep 3 3dep; do |
| $LIBTOOL --mode=link $CC $CFLAGS $LDFLAGS -o liba$i.la a.lo -rpath $libdir_broken |
| $LIBTOOL --mode=install cp liba$i.la $libdir_broken/liba$i.la |
| done |
| ) |
| |
| func_fix_path () |
| { |
| # For w32, hardcoding cannot work, but $libdir/../bin is where binaries |
| # usually are installed. Since we use several prefixes for testing |
| # convenience -- it allows us to replace the good libraries easily with |
| # broken ones and vice versa -- we have to set PATH to find them. |
| # Since OTOH we put broken libs of all names in the "moved" prefixes, |
| # we have to ensure that this prefix comes last: otherwise we may link |
| # against a broken library but the good one would come later in the PATH. |
| # So we let the caller of this function set the order: the "other" two |
| # come first. |
| if test "$shlibpath_var" = PATH; then |
| save_PATH=$PATH |
| sep= |
| test -z "$PATH" || sep=: |
| PATH=${2}/bin:${3}/bin:${1}/bin$sep$PATH |
| fi |
| |
| } |
| |
| func_restore_path () |
| { |
| if test "$shlibpath_var" = PATH; then |
| PATH=$save_PATH |
| fi |
| } |
| |
| # func_move_libs srcdir_to_move prefix_to_move other_prefix other_prefix |
| func_move_libs () |
| { |
| LT_AT_MVDIR(["${1}"], ["${1}-moved"]) |
| LT_AT_MVDIR(["${2}"], ["${2}-moved"]) |
| LT_AT_MVDIR(["$srcdir_broken"], ["${1}"]) |
| LT_AT_MVDIR(["$prefix_broken"], ["${2}"]) |
| func_fix_path ${2} ${3} ${4} |
| } |
| |
| # func_restore_libs srcdir_to_restore prefix_to_restore |
| func_restore_libs () |
| { |
| func_restore_path |
| LT_AT_MVDIR(["${2}"], ["$prefix_broken"]) |
| LT_AT_MVDIR(["${1}"], ["$srcdir_broken"]) |
| LT_AT_MVDIR(["${2}-moved"], ["${2}"]) |
| LT_AT_MVDIR(["${1}-moved"], ["${1}"]) |
| } |
| |
| # make sure the program can be run. |
| func_test_exec () |
| { |
| # On AIX without runtimelinking, this does not make sense. |
| if $have_static; then |
| echo "## The following should succeed:" |
| for st |
| do |
| echo "# m$st" |
| LT_AT_EXEC_CHECK([./m$st]) |
| # For some per-deplib flag combinations there may be no installed program, |
| # because liba2 is not yet installed. |
| if test -f "$bindir/m$st"; then |
| LT_AT_EXEC_CHECK([$bindir/m$st]) |
| fi |
| done |
| fi |
| } |
| |
| # make sure the program cannot be run. |
| func_test_exec_fail () |
| { |
| # No point in testing if we're linking statically anyway. |
| # TODO: Maybe in the `else' case we could test for success? |
| if $have_shared; then |
| echo "## The following should fail:" |
| for st |
| do |
| echo "# m$st" |
| LT_AT_EXEC_CHECK([./m$st || (exit 1)], [1], [], [ignore]) |
| # For some per-deplib flag combinations there may be no installed program, |
| # because liba2 is not yet installed. |
| if test -f "$bindir/m$st"; then |
| LT_AT_EXEC_CHECK([$bindir/m$st || (exit 1)], [1], [], [ignore]) |
| fi |
| done |
| fi |
| } |
| |
| |
| # Try three independent libraries, |
| # one installed libtool library, |
| # one uninstalled libtool library, |
| # one non-libtool library, |
| # the libtool libraries each having a dependency, or not. |
| # Try both an uninstalled and the corresponding installed program. |
| |
| for withdep in no yes; do |
| echo |
| echo "### libraries with dependencies: $withdep" |
| rm -rf src $prefix $prefix1 $prefix2 $prefix3 |
| mkdir src $prefix $bindir $prefix1 $prefix2 $prefix3 |
| cd src |
| |
| ### build the libraries. |
| for i in 1 2 3; do |
| eval ldir=\$libdir$i |
| mkdir a$i $ldir |
| cd a$i |
| case $withdep,$i in |
| no,* | yes,3) |
| echo "int a$i() { return 0; }" > a$i.c |
| $LIBTOOL --mode=compile $CC $CPPFLAGS $CFLAGS -c a$i.c |
| $LIBTOOL --mode=link $CC $CFLAGS $LDFLAGS -o liba$i.la a$i.lo -rpath $ldir |
| ;; |
| *) |
| echo "int a${i}dep() { return 0; }" > a${i}dep.c |
| $LIBTOOL --mode=compile $CC $CPPFLAGS $CFLAGS -c a${i}dep.c |
| $LIBTOOL --mode=link $CC $CFLAGS $LDFLAGS -o liba${i}dep.la a${i}dep.lo -rpath $ldir |
| echo "extern int a${i}dep(); int a$i() { return a${i}dep(); }" > a$i.c |
| $LIBTOOL --mode=compile $CC $CPPFLAGS $CFLAGS -c a$i.c |
| $LIBTOOL --mode=link $CC $CFLAGS $LDFLAGS -o liba$i.la a$i.lo -rpath $ldir ./liba${i}dep.la |
| ;; |
| esac |
| cd .. |
| done |
| |
| ### install the libraries. |
| test "$withdep" = yes && $LIBTOOL --mode=install cp a1/liba1dep.la $libdir1/liba1dep.la |
| $LIBTOOL --mode=install cp a1/liba1.la $libdir1/liba1.la |
| $LIBTOOL --mode=install cp a3/liba3.la $libdir3/liba3.la |
| $LIBTOOL --mode=clean rm -f a1/liba1.la a3/liba3.la |
| test "$withdep" = yes && $LIBTOOL --mode=clean rm -f a1/liba1dep.la |
| # simulate a non-libtool lib: |
| rm -f $libdir3/liba3.la |
| |
| |
| ### build the programs. |
| echo 'extern int a1(), a2(), a3(); |
| int main() { return a1() + a2() + a3(); }' > m.c |
| $CC $CPPFLAGS $CFLAGS -c m.c |
| |
| # global static flags. |
| for st in -static -static-libtool-libs $can_link_all_static; do |
| AT_CHECK([$LIBTOOL --mode=link $CC $CFLAGS $LDFLAGS $st -o m$st m.$OBJEXT \ |
| -L$libdir1 -la1 a2/liba2.la -L$libdir3 -R$libdir3 -la3], |
| [0], [ignore], [ignore]) |
| done |
| |
| # per-deplib static/shared flags. |
| # also try a bit redundant flags, and shuffled order (for run paths check). |
| if $per_deplib; then |
| AT_CHECK([$LIBTOOL --mode=link $CC $CFLAGS $LDFLAGS -o m1 m.$OBJEXT \ |
| -L$libdir1 -Bstatic -la1 -Bdynamic a2/liba2.la -L$libdir3 -R$libdir3 -la3], |
| [0], [ignore], [ignore]) |
| AT_CHECK([$LIBTOOL --mode=link $CC $CFLAGS $LDFLAGS -o m2 m.$OBJEXT \ |
| -L$libdir1 -la1 -Bstatic a2/liba2.la -Bdynamic -L$libdir3 -R$libdir3 -la3], |
| [0], [ignore], [ignore]) |
| AT_CHECK([$LIBTOOL --mode=link $CC $CFLAGS $LDFLAGS -o m3 m.$OBJEXT \ |
| -L$libdir1 -la1 a2/liba2.la -L$libdir3 -Bstatic -la3 -Bdynamic], |
| [0], [ignore], [ignore]) |
| AT_CHECK([$LIBTOOL --mode=link $CC $CFLAGS $LDFLAGS -o m12 m.$OBJEXT \ |
| -L$libdir1 -Bstatic -la1 a2/liba2.la -Bdynamic -L$libdir3 -R$libdir3 -la3], |
| [0], [ignore], [ignore]) |
| AT_CHECK([$LIBTOOL --mode=link $CC $CFLAGS $LDFLAGS -o m13 m.$OBJEXT \ |
| -L$libdir1 -Bstatic -la1 -Bdynamic a2/liba2.la \ |
| -L$libdir3 -Bstatic -la3 -Bdynamic], |
| [0], [ignore], [ignore]) |
| AT_CHECK([$LIBTOOL --mode=link $CC $CFLAGS $LDFLAGS -o m31 m.$OBJEXT \ |
| -L$libdir3 -Bstatic -la3 -Bdynamic a2/liba2.la \ |
| -L$libdir1 -Bstatic -la1 -Bdynamic], |
| [0], [ignore], [ignore]) |
| AT_CHECK([$LIBTOOL --mode=link $CC $CFLAGS $LDFLAGS -o m23 m.$OBJEXT \ |
| -L$libdir1 -la1 -Bstatic a2/liba2.la -Bdynamic \ |
| -L$libdir3 -Bstatic -la3 -Bdynamic], |
| [0], [ignore], [ignore]) |
| AT_CHECK([$LIBTOOL --mode=link $CC $CFLAGS $LDFLAGS -o m123 m.$OBJEXT \ |
| -L$libdir1 -Bstatic -la1 a2/liba2.la -L$libdir3 -la3 -Bdynamic], |
| [0], [ignore], [ignore]) |
| AT_CHECK([$LIBTOOL --mode=link $CC $CFLAGS $LDFLAGS -o m123a m.$OBJEXT \ |
| -L$libdir1 -Bstatic -la1 -Bdynamic -Bstatic a2/liba2.la -Bdynamic \ |
| -Bstatic -L$libdir3 -la3 -Bdynamic], |
| [0], [ignore], [ignore]) |
| dnl # This usually fails. So don't do it. |
| dnl AT_CHECK([$LIBTOOL --mode=link $CC $CFLAGS $LDFLAGS -o m123b m.$OBJEXT \ |
| dnl -L$libdir1 -Bstatic -la1 a2/liba2.la -L$libdir3 -la3], |
| dnl [0], [ignore], [ignore]) |
| fi |
| |
| ### install the programs. |
| # We can't install any program that links dynamically against liba2. |
| for st in -static -static-libtool-libs $can_link_all_static `$per_deplib && echo 2 12 23 123 123a`; do |
| echo "# m$st" |
| AT_CHECK([$LIBTOOL --mode=install cp m$st $bindir/m$st], [0], [ignore], [stderr]) |
| if $have_static; then |
| AT_CHECK([$EGREP 'relinking|has not been installed' stderr], [1], [], []) |
| fi |
| done |
| dnl AT_CHECK([$LIBTOOL --mode=install cp m123b $bindir/m123b], [0], [ignore], [ignore]) |
| |
| |
| ### Run each program once so that relinking has happened. |
| |
| func_fix_path $prefix1 $prefix2 $prefix3 |
| func_test_exec -static -static-libtool-libs -all-static `$per_deplib && echo 1 2 3 12 13 23 31 123 123a` |
| func_restore_path |
| |
| # For each library: |
| # - remove the library images to catch failure to link statically/dynamically, |
| # - add false other deplibs in the paths to catch (some) wrongly added run paths. |
| |
| # if -all-static does not work, do not exercise it any more. |
| all_static=-all-static |
| test -z "$link_static_flag" && all_static= |
| |
| echo "### test whether installed libtool library liba2 was linked statically" |
| func_move_libs a2 $prefix2 $prefix3 $prefix1 |
| func_test_exec -static -static-libtool-libs $all_static `$per_deplib && echo 2 12 23 123 123a` |
| $per_deplib && func_test_exec_fail 1 3 13 31 |
| func_restore_libs a2 $prefix2 |
| |
| echo "### test whether uninstalled libtool library liba1 was linked statically" |
| func_move_libs a1 $prefix1 $prefix2 $prefix3 |
| func_test_exec -static-libtool-libs $all_static `$per_deplib && echo 1 12 13 31 123 123a` |
| $per_deplib && func_test_exec_fail -static 2 3 23 |
| func_restore_libs a1 $prefix1 |
| |
| echo "### test whether non-libtool library liba3 was linked statically" |
| func_move_libs a3 $prefix3 $prefix1 $prefix2 |
| func_test_exec $all_static `$per_deplib && echo 3 13 23 31 123 123a` |
| func_test_exec_fail -static -static-libtool-libs `$per_deplib && echo 1 2 12` |
| func_restore_libs a3 $prefix3 |
| |
| cd .. |
| done |
| |
| AT_CLEANUP |
| |
| |
| AT_SETUP([ccache -all-static]) |
| |
| AT_DATA([ccache], |
| [[#! /bin/sh |
| # poor man's ccache clone |
| case $1 in |
| -*) echo "bogus argument: $1" >&2; exit 1 ;; |
| esac |
| exec "$@" |
| ]]) |
| chmod +x ./ccache |
| |
| AT_DATA([a.c], |
| [[int main(void) { return 0; } |
| ]]) |
| |
| AT_CHECK([$CC $CPPFLAGS $CFLAGS -c a.c], [], [ignore]) |
| AT_CHECK([$LIBTOOL --mode=link --tag=CC ./ccache $CC $CFLAGS $LDFLAGS -all-static a.$OBJEXT -o a], |
| [], [ignore], [ignore]) |
| |
| AT_CLEANUP |