diff mbox

PATCH RFA: Build system: Check for -static-libstdc++

Message ID mcrpqunowg8.fsf@google.com
State New
Headers show

Commit Message

Ian Lance Taylor Nov. 3, 2010, 4:36 a.m. UTC
The -static-libstdc++ option was added to g++ in the gcc 4.5 release.
The Go frontend wants to use it when linking, so that the Go frontend is
independent of the installed libstdc++.so.  This is particularly useful
when bootstrapping, and is generally desirable as it permits moving the
compiler around.

This patch to gcc/configure.ac checks whether $(CXX) supports
-static-libstdc++, and sets a variable in Makefile.in.  This is not used
yet, but it will be used by the Go frontend when it goes in.

Bootstrapped on x86_64-unknown-linux-gnu.  OK for mainline?

Ian


2010-11-02  Ian Lance Taylor  <iant@google.com>

	* configure.ac: Set and substitute STATIC_LIBSTDCXX.
	* Makefile.in (STATIC_LIBSTDCXX): New variable.
	* configure: Rebuild.

Comments

Ralf Wildenhues Nov. 3, 2010, 6:08 a.m. UTC | #1
Hello Ian,

* Ian Lance Taylor wrote on Wed, Nov 03, 2010 at 05:36:07AM CET:
> 2010-11-02  Ian Lance Taylor  <iant@google.com>
> 
> 	* configure.ac: Set and substitute STATIC_LIBSTDCXX.
> 	* Makefile.in (STATIC_LIBSTDCXX): New variable.
> 	* configure: Rebuild.

> --- gcc/configure.ac	(revision 166230)
> +++ gcc/configure.ac	(working copy)
> @@ -4497,6 +4497,22 @@ done
>  # UNSORTED
>  # --------
>  
> +# Test whether $CXX supports -static-libstdc++
> +AC_CACHE_CHECK([whether $CXX supports -static-libstdc++],
> +	gcc_cv_cxx_supports_static_libstdcxx,
> +	[if $CXX -static-libstdc++ 2>&1 >/dev/null | 
> +	    grep 'unrecognized option' >/dev/null; then

This will not work with non-GCC compilers that print something other
than "unrecognized option" upon such an option.  I think you should at
least check that you can form a command with the flag that exits zero,
that way you may still have warnings during Stage 1 but at least not a
hard build failure.

Alternatively, you could check whether $GXX is yes, to be sure to only
accept the flag for GCC.

> +	   gcc_cv_cxx_supports_static_libstdcxx=no
> +	 else
> +	   gcc_cv_cxx_supports_static_libstdcxx=yes
> +	 fi])

Cheers,
Ralf
Mike Stump Nov. 3, 2010, 5:28 p.m. UTC | #2
On Nov 2, 2010, at 9:36 PM, Ian Lance Taylor wrote:
> The Go frontend wants to use it when linking, so that the Go frontend is
> independent of the installed libstdc++.so.  This is particularly useful
> when bootstrapping, and is generally desirable as it permits moving the
> compiler around.

I don't think this is the way forward.  A platform selects shared or non-shared libraries for platform reasons.  You ignore those reasons and seek to change them.  If everyone did that, we'd be back in 1989 with software installations that are 20x or more of what they should be.  So, my question, is what makes go so special that the default should not apply?

People that move the compiler around, are already aware of the magic games they have to play with the shared libraries.
Ian Lance Taylor Nov. 3, 2010, 5:35 p.m. UTC | #3
Mike Stump <mikestump@comcast.net> writes:

> On Nov 2, 2010, at 9:36 PM, Ian Lance Taylor wrote:
>> The Go frontend wants to use it when linking, so that the Go frontend is
>> independent of the installed libstdc++.so.  This is particularly useful
>> when bootstrapping, and is generally desirable as it permits moving the
>> compiler around.
>
> I don't think this is the way forward.  A platform selects shared or non-shared libraries for platform reasons.  You ignore those reasons and seek to change them.  If everyone did that, we'd be back in 1989 with software installations that are 20x or more of what they should be.  So, my question, is what makes go so special that the default should not apply?
>
> People that move the compiler around, are already aware of the magic games they have to play with the shared libraries.

This is different from the usual case of moving the compiler around.
The issue here is that the Go compiler itself is linked against
libstdc++.so.  Moreover, in the normal case of a doing a bootstrap, the
Go compiler will be linked against the libstdc++.so of the newly built
gcc.  That means that when somebody bootstraps a new version of gcc,
they will normally get a Go compiler which does not run with the
installed libstdc++.so; it will require the libstdc++.so which was just
created.  The only way to make that work reliably is to use a
-Wl,--rpath option when linking the Go compiler to point to the
installed location of libstdc++.so.  And that will fail if the compiler
is moved to a new location or to a new machine.

I believe that the least confusing option is to link the Go compiler
with -static-libstdc++.  Just as I believe that when and if we convert
gcc itself to compile with C++, we should link gcc itself with
-static-libstdc++.

In other words, yes, this is a special case, and the default should not
apply.

Ian
H.J. Lu Nov. 3, 2010, 6:30 p.m. UTC | #4
On Wed, Nov 3, 2010 at 10:35 AM, Ian Lance Taylor <iant@google.com> wrote:
> Mike Stump <mikestump@comcast.net> writes:
>
>> On Nov 2, 2010, at 9:36 PM, Ian Lance Taylor wrote:
>>> The Go frontend wants to use it when linking, so that the Go frontend is
>>> independent of the installed libstdc++.so.  This is particularly useful
>>> when bootstrapping, and is generally desirable as it permits moving the
>>> compiler around.
>>
>> I don't think this is the way forward.  A platform selects shared or non-shared libraries for platform reasons.  You ignore those reasons and seek to change them.  If everyone did that, we'd be back in 1989 with software installations that are 20x or more of what they should be.  So, my question, is what makes go so special that the default should not apply?
>>
>> People that move the compiler around, are already aware of the magic games they have to play with the shared libraries.
>
> This is different from the usual case of moving the compiler around.
> The issue here is that the Go compiler itself is linked against
> libstdc++.so.  Moreover, in the normal case of a doing a bootstrap, the
> Go compiler will be linked against the libstdc++.so of the newly built
> gcc.  That means that when somebody bootstraps a new version of gcc,
> they will normally get a Go compiler which does not run with the
> installed libstdc++.so; it will require the libstdc++.so which was just
> created.  The only way to make that work reliably is to use a
> -Wl,--rpath option when linking the Go compiler to point to the
> installed location of libstdc++.so.  And that will fail if the compiler
> is moved to a new location or to a new machine.
>
> I believe that the least confusing option is to link the Go compiler
> with -static-libstdc++.  Just as I believe that when and if we convert
> gcc itself to compile with C++, we should link gcc itself with
> -static-libstdc++.
>

How can you avoid:

[hjl@gnu-6 gcc]$ ldd cc1
	linux-vdso.so.1 =>  (0x00007ffff7ffe000)
	libcloog.so.0 => /usr/lib64/libcloog.so.0 (0x0000003f22a00000)
	libppl_c.so.2 => /usr/lib64/libppl_c.so.2 (0x0000003f22400000)
	libppl.so.7 => /usr/lib64/libppl.so.7 (0x0000003f22000000)
	libgmpxx.so.4 => /usr/lib64/libgmpxx.so.4 (0x0000003f21c00000)
	libmpc.so.2 => /usr/lib64/libmpc.so.2 (0x00007ffff7dcd000)
	libmpfr.so.1 => /usr/lib64/libmpfr.so.1 (0x00007ffff7b7e000)
	libgmp.so.3 => /usr/lib64/libgmp.so.3 (0x0000003f2b400000)
	libdl.so.2 => /lib64/libdl.so.2 (0x00007ffff797a000)
	libz.so.1 => /lib64/libz.so.1 (0x00007ffff7764000)
	libc.so.6 => /lib64/libc.so.6 (0x0000003f21400000)
	libstdc++.so.6 => /usr/lib64/libstdc++.so.6 (0x0000003f2d000000)
	libm.so.6 => /lib64/libm.so.6 (0x0000003f21800000)
	libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x0000003f2bc00000)
	/lib64/ld-linux-x86-64.so.2 (0x0000003f21000000)
[hjl@gnu-6 gcc]$

Please note:

1. GCC is still in C.
2. libstdc++.so.6 dependency comes from other DSOes.
Ian Lance Taylor Nov. 3, 2010, 6:54 p.m. UTC | #5
"H.J. Lu" <hjl.tools@gmail.com> writes:

> On Wed, Nov 3, 2010 at 10:35 AM, Ian Lance Taylor <iant@google.com> wrote:
>>
>> This is different from the usual case of moving the compiler around.
>> The issue here is that the Go compiler itself is linked against
>> libstdc++.so.  Moreover, in the normal case of a doing a bootstrap, the
>> Go compiler will be linked against the libstdc++.so of the newly built
>> gcc.  That means that when somebody bootstraps a new version of gcc,
>> they will normally get a Go compiler which does not run with the
>> installed libstdc++.so; it will require the libstdc++.so which was just
>> created.  The only way to make that work reliably is to use a
>> -Wl,--rpath option when linking the Go compiler to point to the
>> installed location of libstdc++.so.  And that will fail if the compiler
>> is moved to a new location or to a new machine.
>>
>> I believe that the least confusing option is to link the Go compiler
>> with -static-libstdc++.  Just as I believe that when and if we convert
>> gcc itself to compile with C++, we should link gcc itself with
>> -static-libstdc++.
>>
>
> How can you avoid:
>
> [hjl@gnu-6 gcc]$ ldd cc1
> 	linux-vdso.so.1 =>  (0x00007ffff7ffe000)
> 	libcloog.so.0 => /usr/lib64/libcloog.so.0 (0x0000003f22a00000)
> 	libppl_c.so.2 => /usr/lib64/libppl_c.so.2 (0x0000003f22400000)
> 	libppl.so.7 => /usr/lib64/libppl.so.7 (0x0000003f22000000)
> 	libgmpxx.so.4 => /usr/lib64/libgmpxx.so.4 (0x0000003f21c00000)
> 	libmpc.so.2 => /usr/lib64/libmpc.so.2 (0x00007ffff7dcd000)
> 	libmpfr.so.1 => /usr/lib64/libmpfr.so.1 (0x00007ffff7b7e000)
> 	libgmp.so.3 => /usr/lib64/libgmp.so.3 (0x0000003f2b400000)
> 	libdl.so.2 => /lib64/libdl.so.2 (0x00007ffff797a000)
> 	libz.so.1 => /lib64/libz.so.1 (0x00007ffff7764000)
> 	libc.so.6 => /lib64/libc.so.6 (0x0000003f21400000)
> 	libstdc++.so.6 => /usr/lib64/libstdc++.so.6 (0x0000003f2d000000)
> 	libm.so.6 => /lib64/libm.so.6 (0x0000003f21800000)
> 	libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x0000003f2bc00000)
> 	/lib64/ld-linux-x86-64.so.2 (0x0000003f21000000)
> [hjl@gnu-6 gcc]$
>
> Please note:
>
> 1. GCC is still in C.
> 2. libstdc++.so.6 dependency comes from other DSOes.

That case is different.  The libstdc++.so there is not the one from the
bootstrapped compiler.  It is the system one, brought in from the
dependencies of the other shared libraries.  This causes no unusual
difficulty.

The difficulty comes when gcc itself is linked against the newly built
bootstrapped libstdc++.so, a libstdc++.so which in the general case is
newer than the system libstdc++.so.

Ian
Richard Biener Nov. 3, 2010, 9:09 p.m. UTC | #6
On Wed, Nov 3, 2010 at 7:54 PM, Ian Lance Taylor <iant@google.com> wrote:
> "H.J. Lu" <hjl.tools@gmail.com> writes:
>
>> On Wed, Nov 3, 2010 at 10:35 AM, Ian Lance Taylor <iant@google.com> wrote:
>>>
>>> This is different from the usual case of moving the compiler around.
>>> The issue here is that the Go compiler itself is linked against
>>> libstdc++.so.  Moreover, in the normal case of a doing a bootstrap, the
>>> Go compiler will be linked against the libstdc++.so of the newly built
>>> gcc.  That means that when somebody bootstraps a new version of gcc,
>>> they will normally get a Go compiler which does not run with the
>>> installed libstdc++.so; it will require the libstdc++.so which was just
>>> created.  The only way to make that work reliably is to use a
>>> -Wl,--rpath option when linking the Go compiler to point to the
>>> installed location of libstdc++.so.  And that will fail if the compiler
>>> is moved to a new location or to a new machine.
>>>
>>> I believe that the least confusing option is to link the Go compiler
>>> with -static-libstdc++.  Just as I believe that when and if we convert
>>> gcc itself to compile with C++, we should link gcc itself with
>>> -static-libstdc++.
>>>
>>
>> How can you avoid:
>>
>> [hjl@gnu-6 gcc]$ ldd cc1
>>       linux-vdso.so.1 =>  (0x00007ffff7ffe000)
>>       libcloog.so.0 => /usr/lib64/libcloog.so.0 (0x0000003f22a00000)
>>       libppl_c.so.2 => /usr/lib64/libppl_c.so.2 (0x0000003f22400000)
>>       libppl.so.7 => /usr/lib64/libppl.so.7 (0x0000003f22000000)
>>       libgmpxx.so.4 => /usr/lib64/libgmpxx.so.4 (0x0000003f21c00000)
>>       libmpc.so.2 => /usr/lib64/libmpc.so.2 (0x00007ffff7dcd000)
>>       libmpfr.so.1 => /usr/lib64/libmpfr.so.1 (0x00007ffff7b7e000)
>>       libgmp.so.3 => /usr/lib64/libgmp.so.3 (0x0000003f2b400000)
>>       libdl.so.2 => /lib64/libdl.so.2 (0x00007ffff797a000)
>>       libz.so.1 => /lib64/libz.so.1 (0x00007ffff7764000)
>>       libc.so.6 => /lib64/libc.so.6 (0x0000003f21400000)
>>       libstdc++.so.6 => /usr/lib64/libstdc++.so.6 (0x0000003f2d000000)
>>       libm.so.6 => /lib64/libm.so.6 (0x0000003f21800000)
>>       libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x0000003f2bc00000)
>>       /lib64/ld-linux-x86-64.so.2 (0x0000003f21000000)
>> [hjl@gnu-6 gcc]$
>>
>> Please note:
>>
>> 1. GCC is still in C.
>> 2. libstdc++.so.6 dependency comes from other DSOes.
>
> That case is different.  The libstdc++.so there is not the one from the
> bootstrapped compiler.  It is the system one, brought in from the
> dependencies of the other shared libraries.  This causes no unusual
> difficulty.
>
> The difficulty comes when gcc itself is linked against the newly built
> bootstrapped libstdc++.so, a libstdc++.so which in the general case is
> newer than the system libstdc++.so.

Can we at least have the option to link the stage1 go1 binary (or whatever
it is called) dynamically against the just built libstdc++ please?  It would
be very annoying to have statically linked libstdc++ from a distributors
point of view.

Richard.

> Ian
>
Ian Lance Taylor Nov. 3, 2010, 9:34 p.m. UTC | #7
Richard Guenther <richard.guenther@gmail.com> writes:

> Can we at least have the option to link the stage1 go1 binary (or whatever
> it is called) dynamically against the just built libstdc++ please?  It would
> be very annoying to have statically linked libstdc++ from a distributors
> point of view.

I assume you mean the stage2/3 go1 binary.

I can add a configure option for this, but it will be independent of
this patch.  This patch just checks whether -static-libstdc++ is
available, and so, in effect, would set the default for the configure
option.  The configure option would be a different patch.

We already have three configure options along these lines:
--with-host-libstdcxx, --with-boot-ldflags, and --with-boot-libs.
Currently when none of these options are used, and
--enable-build-with-cxx is used, the default for --with-boot-ldflags is
-static-libstdc++ -static-libgcc.  The only difference here is that go1
is always built using C++.  But perhaps these options suffice, and we
can just tweak them a bit to set the default for go1 when they are not
used.  In fact, that seems fine to me, as just setting them to any value
would be enough to avoid the default.


Anyhow, is this patch OK for mainline?
    http://gcc.gnu.org/ml/gcc-patches/2010-11/msg00239.html

Ian
Ian Lance Taylor Nov. 3, 2010, 9:49 p.m. UTC | #8
Dave Korn <dave.korn.cygwin@gmail.com> writes:

>   Yes, but what about the _usual_ difficulties of having two independent
> copies of a library linked into the same executable?  We may not be using
> new/delete or throwing exceptions in the compiler just yet, but it still looks
> really like an accident waiting to happen to me.
>
>   For example: suppose there's a pair of functions in gmpxx or ppl or cloog,
> called from the middle-end of the go1 executable, that allocate and deallocate
> some object or other; suppose the allocate function is an extern, prototyped
> in the related lib's header file, but the deallocator is inline; go1 calls the
> allocater, which invokes the system libstdc DSO's operator new; then go1 calls
> the deallocater, which gets inlined, and ends up invoking the
> statically-linked libstdc's operator delete.  Couldn't that happen?

I don't think that can happen for libraries explicitly mentioned on the
link line.  The linker will see the reference in the shared library, and
will pull in the function from the statically linked libstdc++.

For what it's worth, on my Ubuntu system I do not see any references to
libstdc++.so from the system libgmp, libmpfr and libmpc libraries.  So
the references are presumably coming from PPL, and we already have
special configure options to handle the difficulties which arise in that
case.  I think it's fine to continue requiring those configure options,
as long as the default works in a way that people find easy to use.

Ian
Dave Korn Nov. 3, 2010, 9:53 p.m. UTC | #9
On 03/11/2010 18:54, Ian Lance Taylor wrote:
> "H.J. Lu" <hjl.tools@gmail.com> writes:

>> How can you avoid:
>>
>> [hjl@gnu-6 gcc]$ ldd cc1
>> 	linux-vdso.so.1 =>  (0x00007ffff7ffe000)
>> 	libcloog.so.0 => /usr/lib64/libcloog.so.0 (0x0000003f22a00000)
>> 	libppl_c.so.2 => /usr/lib64/libppl_c.so.2 (0x0000003f22400000)
>> 	libppl.so.7 => /usr/lib64/libppl.so.7 (0x0000003f22000000)
>> 	libgmpxx.so.4 => /usr/lib64/libgmpxx.so.4 (0x0000003f21c00000)
>> 	libmpc.so.2 => /usr/lib64/libmpc.so.2 (0x00007ffff7dcd000)
>> 	libmpfr.so.1 => /usr/lib64/libmpfr.so.1 (0x00007ffff7b7e000)
>> 	libgmp.so.3 => /usr/lib64/libgmp.so.3 (0x0000003f2b400000)
>> 	libdl.so.2 => /lib64/libdl.so.2 (0x00007ffff797a000)
>> 	libz.so.1 => /lib64/libz.so.1 (0x00007ffff7764000)
>> 	libc.so.6 => /lib64/libc.so.6 (0x0000003f21400000)
>> 	libstdc++.so.6 => /usr/lib64/libstdc++.so.6 (0x0000003f2d000000)
>> 	libm.so.6 => /lib64/libm.so.6 (0x0000003f21800000)
>> 	libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x0000003f2bc00000)
>> 	/lib64/ld-linux-x86-64.so.2 (0x0000003f21000000)
>> [hjl@gnu-6 gcc]$
>>
>> Please note:
>>
>> 1. GCC is still in C.
>> 2. libstdc++.so.6 dependency comes from other DSOes.
> 
> That case is different.  The libstdc++.so there is not the one from the
> bootstrapped compiler.  It is the system one, brought in from the
> dependencies of the other shared libraries.  This causes no unusual
> difficulty.

  Yes, but what about the _usual_ difficulties of having two independent
copies of a library linked into the same executable?  We may not be using
new/delete or throwing exceptions in the compiler just yet, but it still looks
really like an accident waiting to happen to me.

  For example: suppose there's a pair of functions in gmpxx or ppl or cloog,
called from the middle-end of the go1 executable, that allocate and deallocate
some object or other; suppose the allocate function is an extern, prototyped
in the related lib's header file, but the deallocator is inline; go1 calls the
allocater, which invokes the system libstdc DSO's operator new; then go1 calls
the deallocater, which gets inlined, and ends up invoking the
statically-linked libstdc's operator delete.  Couldn't that happen?

    cheers,
      DaveK
diff mbox

Patch

Index: gcc/configure.ac
===================================================================
--- gcc/configure.ac	(revision 166230)
+++ gcc/configure.ac	(working copy)
@@ -4497,6 +4497,22 @@  done
 # UNSORTED
 # --------
 
+# Test whether $CXX supports -static-libstdc++
+AC_CACHE_CHECK([whether $CXX supports -static-libstdc++],
+	gcc_cv_cxx_supports_static_libstdcxx,
+	[if $CXX -static-libstdc++ 2>&1 >/dev/null | 
+	    grep 'unrecognized option' >/dev/null; then
+	   gcc_cv_cxx_supports_static_libstdcxx=no
+	 else
+	   gcc_cv_cxx_supports_static_libstdcxx=yes
+	 fi])
+if test "$gcc_cv_cxx_supports_static_libstdcxx" = yes; then
+  STATIC_LIBSTDCXX=-static-libstdc++
+else
+  STATIC_LIBSTDCXX=
+fi
+AC_SUBST(STATIC_LIBSTDCXX)
+
 # Create .gdbinit.
 
 echo "dir ." > .gdbinit
Index: gcc/Makefile.in
===================================================================
--- gcc/Makefile.in	(revision 166230)
+++ gcc/Makefile.in	(working copy)
@@ -233,6 +233,10 @@  LINKER_FLAGS = $(CFLAGS)
 endif
 endif
 
+# This is set by the configure script to be -static-libstdc++ if
+# $(CXX) supports the option.
+STATIC_LIBSTDCXX = @STATIC_LIBSTDCXX@
+
 # -------------------------------------------
 # Programs which operate on the build machine
 # -------------------------------------------