| # bindir.at - Test the -bindir option |
| # |
| # Copyright (C) 2009 Free Software Foundation, Inc. |
| # Written by Dave Korn, 2009 |
| # |
| # 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. |
| #### |
| |
| #### |
| # In this testcase, and in the chunk of code that makes use |
| # of $bindir in ltmain.m4sh, we would very much have liked to |
| # automatically decide which systems require dynamically-loaded |
| # libraries to be installed to a directory in $PATH according |
| # to the libtool properties that tell us that "the system provides |
| # no way to hard-code library paths into executables, and also |
| # has no $shlibpath_var independent of the PATH variable", in |
| # Ralf's words. But it turns out this is not possible, as:- |
| # |
| #> * Dave Korn wrote on Fri, Aug 14, 2009 at 04:30:27AM CEST: |
| #>>> Ralf Wildenhues wrote: |
| #>>> |
| #>>>>> But in this particular case, I would argue that either you look at |
| #>>>>> the libtool variables shlibpath_var and hardcode_action for "PATH" |
| #>>>>> and "unsupported". |
| #>>> |
| #>>> On Cygwin, $hardcode_action = "immediate" in the generated libtool |
| #>>> script. Did you perhaps mean $hardcode_shlibpath_var, which is indeed |
| #>>> "unsupported"? |
| #> |
| #> Oh brother, yes, I forgot about those bogus hardcode_libdir_flag_spec |
| #> settings. They fool _LT_LINKER_HARDCODE_LIBPATH. I don't remember whether |
| #> they were needed in order to not break some semantics in ltmain (they |
| #> probably were). |
| #> |
| #> Anyway, $hardcode_action = "immediate" is definitely wrong, but fixing that |
| #> now is also way out of scope of this patch. So I guess we need to stick to |
| #> host matching in the code, and work out a separate fix for the setting of |
| #> $hardcode_libdir_flag_spec. |
| # |
| # So alas we punt for now, and just hardcode the relevant OSs that require |
| # this functionality. That's Cygwin, MinGW and CeGCC for now; see the case |
| # statement in libtool.m4sh around where the 'tdlname' variable is set. |
| |
| #### |
| # Verify compiling works, and skip remaining tests if not. |
| # |
| |
| AT_SETUP([bindir compile check]) |
| |
| AT_DATA([simple.c] ,[[ |
| int main() { return 0;} |
| ]]) |
| |
| $CC $CPPFLAGS $CFLAGS -o simple simple.c || noskip=false |
| rm -f simple |
| |
| AT_CHECK([$noskip || (exit 77)]) |
| |
| AT_CLEANUP |
| |
| #### |
| # Now run the tests themselves. First a simple test that we can |
| # build and run an executable with a couple of tiny libraries. |
| |
| AT_SETUP([bindir basic lib test]) |
| |
| bindirneeded=: |
| case "$host_os" in |
| cygwin*|mingw*|cegcc*) |
| ;; |
| *) |
| bindirneeded=false |
| ;; |
| esac |
| |
| #### |
| # These routines save the PATH before a test and restore it after, |
| # prepending a chosen directory to the path on the platforms where |
| # -bindir is needed after saving. |
| # |
| |
| func_save_and_prepend_path () |
| { |
| save_PATH=$PATH |
| if $bindirneeded ; then |
| PATH=$1:$PATH |
| fi |
| export PATH |
| } |
| |
| func_restore_path () |
| { |
| PATH=$save_PATH |
| export PATH |
| } |
| |
| AT_DATA([foo.c],[[ |
| int x=11; |
| ]]) |
| |
| AT_DATA([baz.c],[[ |
| extern int x; |
| int baz (void); |
| int baz (void) { return x;} |
| ]]) |
| |
| AT_DATA([bar.c],[[ |
| extern int baz (void); |
| int y=3; |
| int bar (void); |
| int bar (void) { return y + baz ();} |
| ]]) |
| |
| AT_DATA([main.c],[[ |
| #include <stdlib.h> |
| extern int baz (void); |
| extern int bar (void); |
| int main() { |
| if (baz () + bar () - 25) abort (); |
| return 0; |
| } |
| ]]) |
| |
| |
| curdir=`pwd` |
| eval "`$LIBTOOL --config | grep '^objdir='`" |
| |
| AT_CHECK([$LIBTOOL --mode=compile --tag=CC $CC -c -o foo.lo $CPPFLAGS $CFLAGS foo.c],[0],[ignore],[ignore]) |
| AT_CHECK([$LIBTOOL --mode=compile --tag=CC $CC -c -o baz.lo $CPPFLAGS $CFLAGS baz.c],[0],[ignore],[ignore]) |
| AT_CHECK([$LIBTOOL --mode=link --tag=CC $CC -no-undefined -o libfoo.la $CPPFLAGS $CFLAGS $LDFLAGS foo.lo baz.lo -rpath $curdir/$objdir],[0],[ignore],[ignore]) |
| |
| AT_CHECK([$LIBTOOL --mode=compile --tag=CC $CC -c -o bar.lo $CPPFLAGS $CFLAGS bar.c],[0],[ignore],[ignore]) |
| AT_CHECK([$LIBTOOL --mode=link --tag=CC $CC -no-undefined -o libbar.la $CPPFLAGS $CFLAGS $LDFLAGS bar.lo libfoo.la -rpath $curdir/$objdir],[0],[ignore],[ignore]) |
| |
| AT_CHECK([$LIBTOOL --mode=compile --tag=CC $CC -c -o main.lo $CPPFLAGS $CFLAGS main.c],[0],[ignore],[ignore]) |
| AT_CHECK([$LIBTOOL --mode=link --tag=CC $CC -o main$EXEEXT $CPPFLAGS $CFLAGS $LDFLAGS main.lo libbar.la libfoo.la],[0],[ignore],[ignore]) |
| |
| # Check both static and shared versions run. We don't install them |
| # here, that will be covered by the later tests; we've rpath'd things |
| # so that they can all be run in situ. |
| |
| LT_AT_NOINST_EXEC_CHECK([$LIBTOOL], [], [0], [ignore], [ignore], [--mode=execute ./main$EXEEXT]) |
| |
| # Ensure libraries can be found on PATH, if we are on one |
| # of the affected platforms, before testing the shared version. |
| |
| func_save_and_prepend_path $curdir/$objdir |
| $bindirneeded && { |
| LT_AT_NOINST_EXEC_CHECK([$LIBTOOL], [], [0], [ignore], [ignore], [--mode=execute $objdir/main$EXEEXT]) |
| } |
| |
| # In fact, prepending the PATH as above is superfluous on the windows |
| # platforms that this feature is primarily aimed at, as the DLL search |
| # path always includes the directory from which the app was launched. |
| # To make sure it still works even when not side-by-side, we'll install |
| # the main executable and execute it from there while the PATH still |
| # points to the shared libs in the .libs subdir. On other platforms, |
| # the rpaths we set at link time will guarantee it runs from the bindir. |
| |
| mkdir $curdir/bin |
| AT_CHECK([$LIBTOOL --mode=install $lt_INSTALL main$EXEEXT $curdir/bin/main$EXEEXT], [], [ignore], [ignore]) |
| LT_AT_EXEC_CHECK([$curdir/bin/main$EXEEXT], [0], [ignore], [ignore], []) |
| func_restore_path |
| |
| AT_CLEANUP |
| |
| #### |
| # This is the main testcase. For a variety of bindir and libdir |
| # settings, it verifies that all the files get installed exactly |
| # where we want them to go, and that they can be executed once |
| # installed. |
| # |
| |
| AT_SETUP([bindir install tests]) |
| |
| bindirneeded=: |
| case "$host_os" in |
| cygwin*|mingw*|cegcc*) |
| ;; |
| *) |
| bindirneeded=false |
| ;; |
| esac |
| |
| #### |
| # These routines save the PATH before a test and restore it after, |
| # prepending a chosen directory to the path on the platforms where |
| # -bindir is needed after saving. |
| # |
| |
| func_save_and_prepend_path () |
| { |
| save_PATH=$PATH |
| if $bindirneeded ; then |
| PATH=$1:$PATH |
| fi |
| export PATH |
| } |
| |
| func_restore_path () |
| { |
| PATH=$save_PATH |
| export PATH |
| } |
| |
| AT_DATA([foo.c],[[ |
| int x=11; |
| ]]) |
| |
| AT_DATA([baz.c],[[ |
| extern int x; |
| int baz (void); |
| int baz (void) { return x;} |
| ]]) |
| |
| AT_DATA([bar.c],[[ |
| extern int baz (void); |
| int y=3; |
| int bar (void); |
| int bar (void) { return y + baz ();} |
| ]]) |
| |
| AT_DATA([main.c],[[ |
| #include <stdlib.h> |
| extern int baz (void); |
| extern int bar (void); |
| int main() { |
| if (baz () + bar () - 25) abort (); |
| return 0; |
| } |
| ]]) |
| |
| # We only need to compile once, but we'll need to relink for each different value |
| # of libdir in order to set the rpath, and we'll install for each combination of |
| # libdir and bindir. |
| |
| AT_CHECK([$LIBTOOL --mode=compile --tag=CC $CC -c -o foo.lo $CPPFLAGS $CFLAGS foo.c],[0],[ignore],[ignore]) |
| AT_CHECK([$LIBTOOL --mode=compile --tag=CC $CC -c -o baz.lo $CPPFLAGS $CFLAGS baz.c],[0],[ignore],[ignore]) |
| AT_CHECK([$LIBTOOL --mode=compile --tag=CC $CC -c -o bar.lo $CPPFLAGS $CFLAGS bar.c],[0],[ignore],[ignore]) |
| AT_CHECK([$LIBTOOL --mode=compile --tag=CC $CC -c -o main.lo $CPPFLAGS $CFLAGS main.c],[0],[ignore],[ignore]) |
| |
| # Now try installing the libs. There are the following cases: |
| # No -bindir |
| # -bindir below lib install dir |
| # -bindir is lib install dir |
| # -bindir beside lib install dir |
| # -bindir above lib dir |
| # -bindir above and beside lib dir |
| # -bindir in entirely unrelated prefix. |
| |
| curdir=`pwd` |
| for libdir in \ |
| $curdir/usr/lib/gcc/i686-pc-cygwin/4.5.0 \ |
| $curdir/usr/lib/gcc/../gcc/.//i686-pc-cygwin/4.5.0/../../././//. \ |
| $curdir/usr/lib/ \ |
| $curdir/usr/lib \ |
| $curdir/baz \ |
| $curdir/baz/lib/ ; |
| do |
| |
| # Do a basic install with no -bindir option for reference. We use the sbin/ |
| # dir for the main exe to avoid the potential "this only works because it's |
| # side-by-side with the libs" default DLL search path problem mentioned above. |
| rm -rf $libdir $curdir/bin $curdir/sbin $curdir/baz $curdir/usr |
| AS_MKDIR_P($libdir) |
| AS_MKDIR_P($curdir/sbin) |
| AT_CHECK([$LIBTOOL --mode=link --tag=CC $CC -no-undefined -o libfoo.la $CPPFLAGS $CFLAGS $LDFLAGS foo.lo bar.lo baz.lo -rpath $libdir],[0],[ignore],[ignore]) |
| AT_CHECK([$LIBTOOL --mode=link --tag=CC $CC -o main$EXEEXT $CPPFLAGS $CFLAGS $LDFLAGS main.lo libfoo.la -rpath $libdir],[0],[ignore],[ignore]) |
| AT_CHECK([$LIBTOOL --mode=install $lt_INSTALL libfoo.la $libdir], [], [ignore], [ignore]) |
| AT_CHECK([$LIBTOOL --mode=install $lt_INSTALL main$EXEEXT $curdir/sbin/main$EXEEXT], [], [ignore], [ignore]) |
| |
| # And ensure it went where we expect. Could be looking for any of 'cygfoo-0.dll', |
| # 'libfoo-0.dll', or 'libfoo.so.0'. We'll simplify this check by taking advantage |
| # of the fact that if it's a DLL, it has to go in bindir, so we'll not check for |
| # both forms in libdir. |
| AT_CHECK([$bindirneeded && { test -f $libdir/../bin/???foo-0.dll || ls $libdir/../bin/*foo*0* 2>/dev/null ; } || ls $libdir/*foo*0* 2>/dev/null], [], [ignore], [ignore]) |
| |
| # And that it can be executed. |
| extrapath= |
| $bindirneeded && extrapath=$libdir/../bin |
| func_save_and_prepend_path $extrapath |
| LT_AT_EXEC_CHECK([$curdir/sbin/main$EXEEXT], [0], [ignore], [ignore], []) |
| func_restore_path |
| |
| for bindir in \ |
| $curdir/usr/lib/gcc/i686-pc-cygwin/4.5.0/bin/ \ |
| $curdir/usr/lib/gcc/i686-pc-cygwin/4.5.0/bin \ |
| $curdir/usr/lib/gcc/i686-pc-cygwin/4.5.0/ \ |
| $curdir/usr/lib/gcc/i686-pc-cygwin/4.5.0 \ |
| $curdir/usr/lib/gcc/i686-pc-cygwin/bin/ \ |
| $curdir/usr/lib/gcc/i686-pc-cygwin/bin \ |
| $curdir/usr/lib/gcc/i686-pc-cygwin/ \ |
| $curdir/usr/lib/gcc/i686-pc-cygwin \ |
| $curdir/usr/lib/bin/ \ |
| $curdir/usr/lib/bin \ |
| $curdir/usr/bin/ \ |
| $curdir/usr/bin \ |
| $curdir/bin/ \ |
| $curdir/bin \ |
| /tmp/foo/bar ; |
| do |
| |
| # Clear any old stuff out before we install. Because bindir |
| # may be in /tmp, we have to take care to create it securely |
| # and not to delete and recreate it if we do. |
| rm -rf $libdir $curdir/bin $curdir/sbin $curdir/baz $curdir/usr |
| |
| tmp= |
| case $bindir in |
| /tmp*) |
| # Create a temporary directory $tmp in $TMPDIR (default /tmp). |
| # Use mktemp if possible; otherwise fall back on mkdir, |
| # with $RANDOM to make collisions less likely. |
| : ${TMPDIR=/tmp} |
| { |
| tmp=` |
| (umask 077 && mktemp -d "$TMPDIR/fooXXXXXX") 2>/dev/null |
| ` && |
| test -n "$tmp" && test -d "$tmp" |
| } || { |
| tmp=$TMPDIR/foo$$-$RANDOM |
| (umask 077 && mkdir "$tmp") |
| } || exit 77 |
| bindir=$tmp/bar |
| ;; |
| *) |
| # Clear any old stuff out before we install. |
| rm -rf $bindir |
| AS_MKDIR_P($bindir) |
| ;; |
| esac |
| |
| # Relink with new rpaths. |
| AT_CHECK([$LIBTOOL --mode=link --tag=CC $CC -no-undefined -bindir $bindir -o libfoo.la $CPPFLAGS $CFLAGS $LDFLAGS foo.lo bar.lo baz.lo -rpath $libdir],[0],[ignore],[ignore]) |
| AT_CHECK([$LIBTOOL --mode=link --tag=CC $CC -o main$EXEEXT $CPPFLAGS $CFLAGS $LDFLAGS main.lo libfoo.la],[0],[ignore],[ignore]) |
| |
| # Recreate directories (bindir already done) and install. |
| AS_MKDIR_P($libdir) |
| AS_MKDIR_P($curdir/sbin) |
| AT_CHECK([$LIBTOOL --mode=install $lt_INSTALL libfoo.la $libdir], [], [ignore], [ignore]) |
| AT_CHECK([$LIBTOOL --mode=install $lt_INSTALL main$EXEEXT $curdir/sbin/main$EXEEXT], [], [ignore], [ignore]) |
| |
| # Ensure it went to bindir rather than default dir this time. |
| AT_CHECK([$bindirneeded && { test -f $bindir/???foo-0.dll || ls $bindir/*foo*0* 2>/dev/null ; } || ls $libdir/*foo*0* 2>/dev/null], [], [ignore], [ignore]) |
| |
| # And that it can be executed. |
| extrapath= |
| $bindirneeded && extrapath=$bindir |
| func_save_and_prepend_path $extrapath |
| LT_AT_EXEC_CHECK([$curdir/sbin/main$EXEEXT], [0], [ignore], [ignore], []) |
| func_restore_path |
| |
| # Clean up if we made a temp dir. Subdirs under our testdir get rm'd |
| # and recreated at the top of the loop. Securely created subdirs under |
| # /tmp get created precisely once and rm'd when we're done with them. |
| if test ! -z "$tmp" ; then |
| rm -rf "$tmp" |
| fi |
| |
| done |
| done |
| |
| AT_CLEANUP |