Oops. Forgot to change the test names when I renamed win32.at; fixed in this revision. Tests run to completion this time, with no regressions.
libtool/ChangeLog: * Makefile.am (TESTSUITE_AT): Add pe-dll-inst-bindir.at. * libltdl/config/general.m4sh (func_relative_path): New function. * libltdl/config/ltmain.m4sh (func_mode_link): Accept new -bindir option and use it, if supplied, to place Windows DLLs. * tests/pe-dll-inst-bindir.at: New file for DLL install tests. * doc/libtool.texi (Link Mode): Update documentation. And that, unless anyone has any more review comments, is the final revision. Now we twiddle our thumbs and wait for the paperwork, I guess! cheers, DaveK
diff --git a/Makefile.am b/Makefile.am old mode 100644 new mode 100755 index a18955e..fdeeffd --- a/Makefile.am +++ b/Makefile.am @@ -494,7 +494,8 @@ TESTSUITE_AT = tests/testsuite.at \ tests/configure-iface.at \ tests/stresstest.at \ tests/cmdline_wrap.at \ - tests/darwin.at + tests/darwin.at \ + tests/pe-dll-inst-bindir.at EXTRA_DIST += $(srcdir)/$(TESTSUITE) $(TESTSUITE_AT) $(srcdir)/tests/package.m4 diff --git a/doc/libtool.texi b/doc/libtool.texi old mode 100644 new mode 100755 index a7872c6..61a4e8e --- a/doc/libtool.texi +++ b/doc/libtool.texi @@ -1376,6 +1376,15 @@ Tries to avoid versioning (@pxref{Versioning}) for libraries and modules, i.e.@: no version information is stored and no symbolic links are created. If the platform requires versioning, this option has no effect. +...@item -bindir +When linking a DLL for Windows or another PE platform, this option tells +libtool where to eventually install the @samp{.dll} file. The output path +is used to install the @samp{.la} control file, usually into a @samp{.../lib/} +subdirectory of the @var{prefix}; except in the case of a dlopen()-able +module (@pxref{Modules for libltdl}), it is usually desirable to install the +DLL into a @samp{.../bin/} directory alongside. This option specifies the +absolute path to the @var{bindir}. + @item -dlopen @var{file} Same as @option{-dlpreopen @var{file}}, if native dlopening is not supported on the host platform (@pxref{Dlopened modules}) or if @@ -1460,7 +1469,10 @@ the @option{-version-info} flag instead (@pxref{Versioning}). @item -rpath @var{libdir} If @var{output-file} is a library, it will eventually be installed in @var{libdir}. If @var{output-file} is a program, add @var{libdir} to -the run-time path of the program. +the run-time path of the program. If @var{output-file} is a Windows +(or other PE platform) DLL, the @samp{.la} control file will be +installed in @var{libdir}, but see @option{-bindir} above for the +eventual destination of the @samp{.dll} file itself. @item -R @var{libdir} If @var{output-file} is a program, add @var{libdir} to its run-time diff --git a/libltdl/config/general.m4sh b/libltdl/config/general.m4sh old mode 100644 new mode 100755 index 4bc304c..496cac5 --- a/libltdl/config/general.m4sh +++ b/libltdl/config/general.m4sh @@ -100,6 +100,76 @@ func_dirname_and_basename () # Generated shell functions inserted here. +# func_relative_path libdir bindir +# generates a relative path from LIBDIR to BINDIR, intended +# for supporting installation of windows DLLs into -bindir. +# call: +# func_dirname: +# func_dirname file append nondir_replacement +# Compute the dirname of FILE. If nonempty, +# add APPEND to the result, otherwise set result +# to NONDIR_REPLACEMENT. +# value returned in "$func_dirname_result" +# func_stripname: +# func_stripname prefix suffix name +# Strip PREFIX and SUFFIX off of NAME. PREFIX and +# SUFFIX must not contain globbing or regex special +# characters, hashes, percent signs, but SUFFIX may +# contain a leading dot (in which case that matches +# only a dot). +# value returned in "$func_stripname_result" +func_relative_path () +{ + func_relative_path_result= + func_stripname '' '/' "$1" + func_relative_path_tlibdir=$func_stripname_result + func_stripname '' '/' "$2" + func_relative_path_tbindir=$func_stripname_result + + # Ascend the tree starting from libdir + while :; do + # check if we have found a prefix of bindir + case "$func_relative_path_tbindir" in + $func_relative_path_tlibdir*) # found a matching prefix + func_stripname "$func_relative_path_tlibdir" '' "$func_relative_path_tbindir" + func_relative_path_tcancelled=$func_stripname_result + if test -z "$func_relative_path_result"; then + func_relative_path_result=. + fi + break + ;; + *) + func_dirname $func_relative_path_tlibdir + func_relative_path_tlibdir=${func_dirname_result} + if test x$func_relative_path_tlibdir = x ; then + # Have to descend all the way to the root! + func_relative_path_result=../$func_relative_path_result + func_relative_path_tcancelled="$func_relative_path_tbindir" + break + fi + func_relative_path_result=../$func_relative_path_result + ;; + esac + done + + # Now calculate path; take care to avoid doubling-up slashes. + func_stripname '' '/' "$func_relative_path_result" + func_relative_path_result=$func_stripname_result + func_stripname '' '/' "$func_relative_path_tcancelled" + func_relative_path_result=${func_relative_path_result}${func_stripname_result} + + # Normalisation. If bindir is libdir, return empty string, + # if subdir return string beginning './', else relative path + # ending with a slash; either way, target file name can be + # directly appended. + if test -z "$func_relative_path_result"; then + func_relative_path_result=./ + else + func_stripname './' '' "$func_relative_path_result/" + func_relative_path_result=$func_stripname_result + fi +} + # The name of this program: func_dirname_and_basename "$progpath" progname=$func_basename_result diff --git a/libltdl/config/ltmain.m4sh b/libltdl/config/ltmain.m4sh old mode 100644 new mode 100755 index ebd3909..5403d80 --- a/libltdl/config/ltmain.m4sh +++ b/libltdl/config/ltmain.m4sh @@ -1129,6 +1129,8 @@ The following components of LINK-COMMAND are treated specially: -all-static do not do any dynamic linking at all -avoid-version do not add a version suffix if possible + -bindir BINDIR specify path to $prefix/bin (needed only when installing + a Windows DLL) -dlopen FILE \`-dlpreopen' FILE if it cannot be dlopened at runtime -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) @@ -3659,6 +3661,7 @@ func_mode_link () new_inherited_linker_flags= avoid_version=no + bindir= dlfiles= dlprefiles= dlself=no @@ -3751,6 +3754,11 @@ func_mode_link () esac case $prev in + bindir) + bindir="$arg" + prev= + continue + ;; dlfiles|dlprefiles) if test "$preload" = no; then # Add the symbol object into the linking commands. @@ -4012,6 +4020,11 @@ func_mode_link () continue ;; + -bindir) + prev=bindir + continue + ;; + -dlopen) prev=dlfiles continue @@ -7706,7 +7719,17 @@ EOF # place dlname in correct position for cygwin tdlname=$dlname case $host,$output,$installed,$module,$dlname in - *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll) tdlname=../bin/$dlname ;; + *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll) + # If a -bindir argument was supplied, place the dll there. + if test "x$bindir" != x ; + then + func_relative_path "$install_libdir" "$bindir" + tdlname="${func_relative_path_result}$dlname" + else + # Otherwise fall back on heuristic. + tdlname=../bin/$dlname + fi + ;; esac $ECHO > $output "\ # $outputname - a libtool library file diff --git a/tests/pe-dll-inst-bindir.at b/tests/pe-dll-inst-bindir.at new file mode 100755 index 0000000..a0f45e5 --- /dev/null +++ b/tests/pe-dll-inst-bindir.at @@ -0,0 +1,171 @@ +# pe-dll-inst-bindir.at - Test the -bindir option for installing +# DLLs on PE format architectures. +# +# 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. +#### + +noskip=: +case "$host_os" in +cygwin*|mingw*|cegcc*) ;; +*) noskip=false ;; +esac + +$noskip && { + +AT_BANNER([PE DLL install tests]) +AT_SETUP([simple compile check]) + +# Verify compiling works. + +AT_DATA([simple.c] ,[[ +int main() { return 0;} +]]) + +$noskip && { +$CC $CPPFLAGS $CFLAGS -o simple simple.c 2>&1 > /dev/null || noskip=false +rm -f simple +} + +AT_CHECK([$noskip || (exit 77)]) + +AT_CLEANUP + +# Now the tests themselves. + +AT_SETUP([dll basic test]) + +AT_DATA([foo.c],[[ +int x=0; +]]) + +AT_DATA([baz.c],[[ +int y=0; +]]) + +AT_DATA([bar.c],[[ +extern int x; +int bar(void); +int bar() { return x;} +]]) + +AT_DATA([main.c],[[ +extern int x; +extern int y; + +int main() { +return x+y; +} +]]) + +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 -shared -o libfoo.la $CPPFLAGS $CFLAGS $LDFLAGS foo.lo baz.lo -rpath /nonexistent],[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 -shared -o libbar.la $CPPFLAGS $CFLAGS $LDFLAGS bar.lo libfoo.la -rpath /nonexistent],[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],[0],[ignore],[ignore]) + +AT_CLEANUP + +AT_SETUP([dll install to bindir]) + +AT_DATA([foo.c],[[ +int x=0; +]]) + +AT_DATA([bar.c],[[ +extern int x; +int bar(void); +int bar() { return x;} +]]) + +AT_DATA([baz.c],[[ +int y=0; +]]) + +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 -shared -o libfoo.la $CPPFLAGS $CFLAGS $LDFLAGS foo.lo baz.lo -rpath /nonexistent],[0],[ignore],[ignore]) + +AT_CHECK([$LIBTOOL --mode=compile --tag=CC $CC -c -o bar.lo $CPPFLAGS $CFLAGS bar.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` +libdir=${curdir}/usr/lib/gcc/i686-pc-cygwin/4.5.0 + +# Do a basic install with no -bindir option for reference + +AT_CHECK([$LIBTOOL --mode=link --tag=CC $CC -no-undefined -shared -o libbar.la $CPPFLAGS $CFLAGS $LDFLAGS bar.lo libfoo.la -rpath ${libdir}],[0],[ignore],[ignore]) +rm -rf ${curdir}/usr +mkdir -p ${libdir} +AT_CHECK([$LIBTOOL --mode=install $lt_INSTALL libbar.la $libdir], + [], [ignore], [ignore]) + +# And ensure it went where we expect. +AT_CHECK(test -f $libdir/../bin/???bar-0.dll) + +for x 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 + + AT_CHECK([$LIBTOOL --mode=link --tag=CC $CC -no-undefined -bindir $x -shared -o libbar.la $CPPFLAGS $CFLAGS $LDFLAGS bar.lo libfoo.la -rpath ${libdir}],[0],[ignore],[ignore]) + + rm -rf ${curdir}/usr ${curdir}/bin /tmp/$$ + mkdir -p ${libdir} $x ${curdir}/usr ${curdir}/bin /tmp/$$ + AT_CHECK([$LIBTOOL --mode=install $lt_INSTALL libbar.la $libdir], + [], [ignore], [ignore]) + # Ensure it went to bindir this time. + AT_CHECK(test -f $x/???bar-0.dll) +done + +AT_CLEANUP + +} +