On 2013-11-08 20:07, Charles Wilson wrote:
> On 11/8/2013 1:49 PM, Bob Friesenhahn wrote:
>> Isn't it because libtool wants to control the order of the linking and
>> assure that all dependencies (including static) are tracked/known and
>> applied at the correct times?  It wants to assure that static
>> dependencies are linked into the dependent program rather than into some
>> dependent shared library (and thus causing a problem).
>>
>> It was common (and perhaps still is) for the GNU C++ library to be
>> delivered as a static library for Windows/MinGW because C++ exceptions
>> were not handled properly when thrown by DLLs.
>>
>> Quite a lot of effort went into making this work the way it currently does.

I realize that, but if it really works or not is a different question :-)

>> First libtool tries to take away all of the libraries which would be
>> added automatically and then it applies the libraries that GCC says it
>> would use at the correct time.
>
> One of my wishlist roundtuit items is to special-case this behavior
> for libtool + GNU toolchains. For that combo, instead of the
> procedure Bob outlines, and then using $LD to link....just use the
> compiler driver (e.g. g++, or gfortran, or gcc) to link, WITHOUT
> -nostdlib [1]. We're already passing the ABI-modifying -m and -f
> flags anyway, and it would really REALLY simplify libtool's logic...
>
> [1] unless of course the end user put -nostdlib in $LDFLAGS or something.

Hmmm, I don't get it. For me (on Cygwin, but reading the code suggests that
the following holds for all hosts) libtool already uses the compiler driver
to link C++ for GNU toolchains. The only "abnormal" thing I see is the
-nostdlib dance.

I.e., as far as I can tell, $LD is not used for linking. $CXX is used, with
-nostdlib and some manually detected libs/objects, which end up wrong if
different flags (such as -pthread) are used when digging and actually linking.

I also had a closer look at the result of my first patch and have attached
a 2nd attempt that zaps more cruft (predep and postdep libraries) from the
linking stage. This version should be close to the above wishlist item
mentioned by Chuck (even if the complicated logic isn't actually removed
by my small change, it's just bypassed for g++).

Googling a bit more turned up this old quote from Ralf [1] on this subject:

   BTW, I believe libtool does the -nostdlib stuff because, at least in the 
past,
   not using it could cause situations where later libstdc++ would not be found
   automatically.  I think at least for dlopen'ed modules depending on C++
   libraries this is still the case (completely untested).

That was 8 years ago, even then it appears noone really knew why -nostdlib
is used (which is interesting in itself).

So, someone needs to write some test cases that tries to build a library
with --static-libgcc and then use that in a program w/o --static-libgcc
(and vice versa), as well as doing some dlopen test with C++ modules to
try to deduce if the above problem described by Ralf can still be
reproduced (but his wording suggest that it might be subtle). And lastly we
might need some test that tries to throw C++ exceptions over DLL boundaries,
if that isn't already done by tests/exceptions.at...

Is that it?

Cheers,
Peter

[1] http://gcc.gnu.org/bugzilla/show_bug.cgi?id=25460

>From 56080c9349ae56fcac6e7bf7f6081dfa48a7fc67 Mon Sep 17 00:00:00 2001
From: Peter Rosin <p...@lysator.liu.se>
Date: Mon, 11 Nov 2013 09:48:23 +0100
Subject: [PATCH] libtool: Do not use -nostdlib when linking with g++.

Fixes part of bug#15646 and Debian bug 468555.

* m4/libtool.m4 (_LT_LANG_CXX_CONFIG) [g++] <archive_cmds>
<archive_expsym_cmds>: Drop -nostdlib, $predep_objects and
$postdep_objects.
(_LT_LANG_CXX_CONFIG) [g++]: Do not look for hidden library
dependencies.
* NEWS: Update.
---
 NEWS          |    6 ++++++
 m4/libtool.m4 |   34 ++++++++++++++++++----------------
 2 files changed, 24 insertions(+), 16 deletions(-)

diff --git a/NEWS b/NEWS
index 0c85812..5717385 100644
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,12 @@ NEWS - list of user-visible changes between releases of GNU Libtool
 
 * Noteworthy changes in release ?.? (????-??-??) [?]
 
+** Important incompatible changes:
+
+  - When linking shared libraries with g++, trust the compiler driver to
+    interface correctly with the linker.  I.e., drop the -nostdlib
+    option in this case. Fixes point 2 (and perhaps 3) in bug#15646, as
+    well as Debian bug 468555.
 
 * Noteworthy changes in release 2.4.2.418 (2013-10-27) [alpha]
 
diff --git a/m4/libtool.m4 b/m4/libtool.m4
index 4bc6b22..e34e021 100644
--- a/m4/libtool.m4
+++ b/m4/libtool.m4
@@ -6046,8 +6046,8 @@ if test yes != "$_lt_caught_CXX_error"; then
       # Check if GNU C++ uses GNU ld as the underlying linker, since the
       # archiving commands below assume that GNU ld is being used.
       if test yes = "$with_gnu_ld"; then
-        _LT_TAGVAR(archive_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib'
-        _LT_TAGVAR(archive_expsym_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
+        _LT_TAGVAR(archive_cmds, $1)='$CC $pic_flag -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+        _LT_TAGVAR(archive_expsym_cmds, $1)='$CC $pic_flag -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
 
         _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
         _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic'
@@ -6073,7 +6073,7 @@ if test yes != "$_lt_caught_CXX_error"; then
         # linker, instead of GNU ld.  If possible, this setting should
         # overridden to take advantage of the native linker features on
         # the platform it is being used on.
-        _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
+        _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $lib'
       fi
 
       # Commands to make compiler produce verbose output that lists
@@ -6296,7 +6296,7 @@ if test yes != "$_lt_caught_CXX_error"; then
 	  _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
 
 	  if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then
-	    _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+	    _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
 	    # If the export-symbols file already is a .def file, use it as
 	    # is; otherwise, prepend EXPORTS...
 	    _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then
@@ -6305,7 +6305,7 @@ if test yes != "$_lt_caught_CXX_error"; then
               echo EXPORTS > $output_objdir/$soname.def;
               cat $export_symbols >> $output_objdir/$soname.def;
             fi~
-            $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+            $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
 	  else
 	    _LT_TAGVAR(ld_shlibs, $1)=no
 	  fi
@@ -6383,7 +6383,7 @@ if test yes != "$_lt_caught_CXX_error"; then
             ;;
           *)
             if test yes = "$GXX"; then
-              _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib'
+              _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib'
             else
               # FIXME: insert proper C++ library support
               _LT_TAGVAR(ld_shlibs, $1)=no
@@ -6451,13 +6451,13 @@ if test yes != "$_lt_caught_CXX_error"; then
 	      if test no = "$with_gnu_ld"; then
 	        case $host_cpu in
 	          hppa*64*)
-	            _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+	            _LT_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags'
 	            ;;
 	          ia64*)
-	            _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+	            _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
 	            ;;
 	          *)
-	            _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+	            _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
 	            ;;
 	        esac
 	      fi
@@ -6498,9 +6498,9 @@ if test yes != "$_lt_caught_CXX_error"; then
           *)
 	    if test yes = "$GXX"; then
 	      if test no = "$with_gnu_ld"; then
-	        _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
+	        _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
 	      else
-	        _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` -o $lib'
+	        _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` -o $lib'
 	      fi
 	    fi
 	    _LT_TAGVAR(link_all_deplibs, $1)=yes
@@ -6860,9 +6860,9 @@ if test yes != "$_lt_caught_CXX_error"; then
 	    if test yes,no = "$GXX,$with_gnu_ld"; then
 	      _LT_TAGVAR(no_undefined_flag, $1)=' $wl-z ${wl}defs'
 	      if $CC --version | $GREP -v '^2\.7' > /dev/null; then
-	        _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib'
+	        _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h $wl$soname -o $lib'
 	        _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
-                  $CC -shared $pic_flag -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'
+                  $CC -shared $pic_flag $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp'
 
 	        # Commands to make compiler produce verbose output that lists
 	        # what "hidden" libraries, object files and flags are used when
@@ -6871,9 +6871,9 @@ if test yes != "$_lt_caught_CXX_error"; then
 	      else
 	        # g++ 2.7 appears to require '-G' NOT '-shared' on this
 	        # platform.
-	        _LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib'
+	        _LT_TAGVAR(archive_cmds, $1)='$CC -G $libobjs $deplibs $compiler_flags $wl-h $wl$soname -o $lib'
 	        _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
-                  $CC -G -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'
+                  $CC -G $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp'
 
 	        # Commands to make compiler produce verbose output that lists
 	        # what "hidden" libraries, object files and flags are used when
@@ -6979,7 +6979,9 @@ if test yes != "$_lt_caught_CXX_error"; then
     ## There is no encapsulation within the following macros, do not change
     ## the running order or otherwise move them around unless you know exactly
     ## what you are doing...
-    _LT_SYS_HIDDEN_LIBDEPS($1)
+    if test yes != "$GXX"; then
+      _LT_SYS_HIDDEN_LIBDEPS($1)
+    fi
     _LT_COMPILER_PIC($1)
     _LT_COMPILER_C_O($1)
     _LT_COMPILER_FILE_LOCKS($1)
-- 
1.7.9

Reply via email to