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