This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Fix installation of DLLs on PE platforms (win/cyg/ming/ce)


    Hi folks,

  The attached patch is a backport of a new feature that has already been
submitted to upstream libtool and met with broad agreement there.  We're
waiting for assign paperwork before it can be committed there, but there's no
reason not to submit it here in the meantime, and the clock is ticking on stage 1.

  The problem it addresses is that on PE-based platforms that use DLLs, the
shared library must be visible in $PATH.  We prefer not to add our $prefix/lib
dirs to $PATH (since searching among all those non-executables will slow down
all path searches needlessly) but instead to install our DLLs to $prefix/bin.

  However libtool (at install time) only knows about the path to $libdir,
where it must install the .la control file; it doesn't know $bindir, which may
stand in any fairly arbitrary relation to $libdir, depending how creative the
user has been with configure options.  To solve this, it records not just a
name but a relative path in the .la file's dlname parameter at link time, so
that when the DLL is copied to its final installed $dlname, it ends up in the
bin dir.

  That's the theory, but since libtool doesn't know where the bin dir actually
is, it just has a heuristic; it assumes all .la files are being installed into
$prefix/lib, and so creates the dlname as "../bin/$dlname" so that the DLL
ends up in $prefix/lib/../bin/, or IOW $prefix/bin.

  That fails even in the default configuration for GCC, since we're installing
our .la files into $prefix/lib/gcc/$target/$version/, and as a consequence all
the DLLs end up in $prefix/lib/gcc/$target/bin/.

  The patch extends libtool's --link mode to accept a -bindir argument, and
adds that argument to libtool flags everywhere there is a -no-undefined flag
(which is the PE-specific flag needed to enable DLLs on these platforms, where
undefined references are not allowed in libraries).  Libtool can then
calculate a proper relative path instead of just guessing, and the DLLs will
always end up in the user's chosen (or default) $bindir.

libgomp/ChangeLog:

	* Makefile.am (libgomp_la_LDFLAGS): Add -bindir flag.
	* Makefile.in: Regenerate.

ChangeLog:

	* ltmain.sh (func_relative_path): New function.
	(func_mode_help): Document new -bindir option for link mode.
	(func_mode_link): Add new -bindir option, and use it to place
	output DLL if specified.

libgfortran/ChangeLog:

	* Makefile.am (LTLDFLAGS): Add -bindir flag.
	* Makefile.in: Regenerate.

libssp/ChangeLog:

	* Makefile.am (libssp_la_LDFLAGS): Add -bindir flag.
	* Makefile.in: Regenerate.

libjava/libltdl/ChangeLog:

	* Makefile.am (libltdl_la_LDFLAGS): Add -bindir flag.
	* Makefile.in: Regenerate.

libjava/classpath/ChangeLog:

	* ltmain.sh (func_relative_path): New function.
	(func_mode_help): Document new -bindir option for link mode.
	(func_mode_link): Add new -bindir option, and use it to place
	output DLL if specified.


  Tested by bootstrap and make install with DESTDIR, and then manual
inspection of the DESTDIR prefix layout.  Ok for HEAD?

  BTW, I tested this on top of my still-pending patch to build libstdc++-v3 as
a DLL on Cygwin, and it worked fine there too, so I would like pre-approval to
add the bindir flag there too once that patch is committed.  Ok?

    cheers,
      DaveK

Index: libgomp/Makefile.am
===================================================================
--- libgomp/Makefile.am	(revision 150578)
+++ libgomp/Makefile.am	(working copy)
@@ -28,7 +28,7 @@ libgomp_version_script =
 endif
 libgomp_version_info = -version-info $(libtool_VERSION)
 libgomp_la_LDFLAGS = $(libgomp_version_info) $(libgomp_version_script) \
-        -no-undefined
+        -no-undefined -bindir "$(bindir)"
 
 libgomp_la_SOURCES = alloc.c barrier.c critical.c env.c error.c iter.c \
 	iter_ull.c loop.c loop_ull.c ordered.c parallel.c sections.c single.c \
Index: ltmain.sh
===================================================================
--- ltmain.sh	(revision 150578)
+++ ltmain.sh	(working copy)
@@ -170,6 +170,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
+}
+
 # Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh
 # is ksh but when the shell is invoked as "sh" and the current value of
 # the _XPG environment variable is not equal to 1 (one), the special
@@ -1558,6 +1628,8 @@ The following components of LINK-COMMAND are treat
 
   -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)
@@ -4072,6 +4144,7 @@ func_mode_link ()
     new_inherited_linker_flags=
 
     avoid_version=no
+    bindir=
     dlfiles=
     dlprefiles=
     dlself=no
@@ -4164,6 +4237,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.
@@ -4425,6 +4503,11 @@ func_mode_link ()
 	continue
 	;;
 
+      -bindir)
+	prev=bindir
+	continue
+	;;
+
       -dlopen)
 	prev=dlfiles
 	continue
@@ -8123,7 +8206,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
Index: libgfortran/Makefile.am
===================================================================
--- libgfortran/Makefile.am	(revision 150578)
+++ libgfortran/Makefile.am	(working copy)
@@ -13,7 +13,8 @@ else
 version_arg =
 endif
 
-LTLDFLAGS = $(shell $(SHELL) $(top_srcdir)/../libtool-ldflags $(LDFLAGS))
+LTLDFLAGS = $(shell $(SHELL) $(top_srcdir)/../libtool-ldflags $(LDFLAGS)) \
+        -no-undefined -bindir "$(bindir)"
 
 toolexeclib_LTLIBRARIES = libgfortran.la
 libgfortran_la_LINK = $(LINK)
Index: libssp/Makefile.am
===================================================================
--- libssp/Makefile.am	(revision 150578)
+++ libssp/Makefile.am	(working copy)
@@ -35,7 +35,7 @@ libssp_la_SOURCES = \
 libssp_la_LIBADD = 
 libssp_la_DEPENDENCIES = $(version_dep) $(libssp_la_LIBADD)
 libssp_la_LDFLAGS = -version-info `grep -v '^\#' $(srcdir)/libtool-version` \
-		    $(version_arg) -no-undefined
+		    $(version_arg) -no-undefined -bindir "$(bindir)"
 
 libssp_nonshared_la_SOURCES = \
 	ssp-local.c
Index: libjava/libltdl/Makefile.am
===================================================================
--- libjava/libltdl/Makefile.am	(revision 150578)
+++ libjava/libltdl/Makefile.am	(working copy)
@@ -22,7 +22,7 @@ endif
 CLEANFILES = libltdl.la libltdlc.la
 
 libltdl_la_SOURCES = ltdl.c
-libltdl_la_LDFLAGS = -no-undefined -version-info 4:1:1
+libltdl_la_LDFLAGS = -no-undefined -bindir "$(bindir)" -version-info 4:1:1
 libltdl_la_LIBADD = $(LIBADD_DL)
 
 libltdlc_la_SOURCES = ltdl.c
Index: libjava/classpath/ltmain.sh
===================================================================
--- libjava/classpath/ltmain.sh	(revision 150578)
+++ libjava/classpath/ltmain.sh	(working copy)
@@ -170,6 +170,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
+}
+
 # Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh
 # is ksh but when the shell is invoked as "sh" and the current value of
 # the _XPG environment variable is not equal to 1 (one), the special
@@ -1558,6 +1628,8 @@ The following components of LINK-COMMAND are treat
 
   -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)
@@ -4072,6 +4144,7 @@ func_mode_link ()
     new_inherited_linker_flags=
 
     avoid_version=no
+    bindir=
     dlfiles=
     dlprefiles=
     dlself=no
@@ -4164,6 +4237,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.
@@ -4425,6 +4503,11 @@ func_mode_link ()
 	continue
 	;;
 
+      -bindir)
+	prev=bindir
+	continue
+	;;
+
       -dlopen)
 	prev=dlfiles
 	continue
@@ -8123,7 +8206,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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]