Bug 58638 - libstdc++ builds as non-PIC when --with-pic is specified
Summary: libstdc++ builds as non-PIC when --with-pic is specified
Status: NEW
Alias: None
Product: gcc
Classification: Unclassified
Component: libstdc++ (show other bugs)
Version: 4.8.1
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: build
: 59380 106501 (view as bug list)
Depends on:
Blocks:
 
Reported: 2013-10-06 03:40 UTC by Daniel Richard G.
Modified: 2022-08-01 23:07 UTC (History)
3 users (show)

See Also:
Host: x86_64-unknown-linux-gnu
Target: x86_64-unknown-linux-gnu
Build: x86_64-unknown-linux-gnu
Known to work:
Known to fail:
Last reconfirmed: 2015-04-14 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Daniel Richard G. 2013-10-06 03:40:16 UTC
I built GCC 4.8.1 with "--disable-shared --with-pic" so that I can statically link libgcc/libstdc++ into executables, including shared-library builds. However, when I attempted to build a C++ shared object on Linux/amd64 using the new compiler, I got this:

libtool: link: g++  -fPIC -DPIC -shared -nostdlib /usr/lib/../lib64/crti.o /opt/tg-opt/gcc--4.8.1--linux64/bin/../lib/gcc/x86_64-unknown-linux-gnu/4.8.1/crtbeginS.o  .libs/Dqa_wrap.o .libs/dqa_func.o [...] -L/opt/tg-opt/gcc--4.8.1--linux64/bin/../lib/gcc/x86_64-unknown-linux-gnu/4.8.1/../../../../lib64 -L/lib/../lib64 -L/usr/lib/../lib64 -L/opt/tg-opt/gcc--4.8.1--linux64/bin/../lib/gcc/x86_64-unknown-linux-gnu/4.8.1/../../.. /opt/tg/lib/gcc/x86_64-unknown-linux-gnu/4.8.1/libstdc++.a -lm -lc -lgcc /opt/tg-opt/gcc--4.8.1--linux64/bin/../lib/gcc/x86_64-unknown-linux-gnu/4.8.1/crtendS.o /usr/lib/../lib64/crtn.o -march=opteron -mno-3dnow -O0   -pthread -Wl,-soname -Wl,libdqa_swig_interface.so -o .libs/libdqa_swig_interface.so
/usr/bin/ld: /opt/tg/lib/gcc/x86_64-unknown-linux-gnu/4.8.1/libstdc++.a(eh_throw.o): relocation R_X86_64_32S against `a local symbol' can not be used when making a shared object; recompile with -fPIC
/opt/tg/lib/gcc/x86_64-unknown-linux-gnu/4.8.1/libstdc++.a: could not read symbols: Bad value
collect2: error: ld returned 1 exit status
make[6]: *** [libdqa_swig_interface.la] Error 1


This is a regression from 4.7.x, when --with-pic correctly caused all (static) runtime libraries to be built with PIC code.
Comment 1 Daniel Richard G. 2013-10-07 06:18:54 UTC
A workaround for this issue is to build with CFLAGS="-fPIC" CXXFLAGS="-fPIC" (presuming that one is building with GCC), in addition to --with-pic. This results in a compiler build that does not fail as reported above.
Comment 2 H.J. Lu 2013-12-04 11:29:03 UTC
*** Bug 59380 has been marked as a duplicate of this bug. ***
Comment 3 Fredrik Nyström 2014-03-03 19:30:26 UTC
Seems to be a bug in libstdc++-v3/configure, same in both gcc-4.8 and gcc-4.9.

Suggested fix:

--- libstdc++-v3/configure~     2013-11-22 14:17:55.000000000 +0100
+++ libstdc++-v3/configure      2014-03-03 20:01:32.000000000 +0100
@@ -14909,25 +14909,25 @@
 # libtool variables for C++ shared and position-independent compiles.
 #
 # Use glibcxx_lt_pic_flag to designate the automake variable
 # used to encapsulate the default libtool approach to creating objects
 # with position-independent code. Default: -prefer-pic.
 #
 # Use glibcxx_compiler_shared_flag to designate a compile-time flags for
 # creating shared objects. Default: -D_GLIBCXX_SHARED.
 #
 # Use glibcxx_compiler_pic_flag to designate a compile-time flags for
 # creating position-independent objects. This varies with the target
 # hardware and operating system, but is often: -DPIC -fPIC.
-if test "$enable_shared" = yes; then
+if test "$enable_shared" = yes || test "${with_pic+set}" = set; then
   glibcxx_lt_pic_flag="-prefer-pic"
   glibcxx_compiler_pic_flag="$lt_prog_compiler_pic_CXX"
   glibcxx_compiler_shared_flag="-D_GLIBCXX_SHARED"
 
 else
   glibcxx_lt_pic_flag=
   glibcxx_compiler_pic_flag=
   glibcxx_compiler_shared_flag=
 fi
Comment 4 Jonathan Wakely 2014-05-21 10:23:35 UTC
(In reply to Daniel Richard G. from comment #0)
> I built GCC 4.8.1 with "--disable-shared --with-pic" so that I can
> statically link libgcc/libstdc++ into executables,

Instead of building GCC with --disable-shared, why not just use -static-libstdc++ when linking?
Comment 5 Jonathan Wakely 2014-05-21 20:25:29 UTC
I think the right fix is

--- a/libstdc++-v3/configure.ac
+++ b/libstdc++-v3/configure.ac
@@ -120,6 +120,11 @@ if test "$enable_shared" = yes; then
   glibcxx_compiler_pic_flag="$lt_prog_compiler_pic_CXX"
   glibcxx_compiler_shared_flag="-D_GLIBCXX_SHARED"
 
+else if test "${with_pic+set}" = set; then
+  glibcxx_lt_pic_flag="-prefer-pic"
+  glibcxx_compiler_pic_flag="$lt_prog_compiler_pic_CXX"
+  glibcxx_compiler_shared_flag=
+
 else
   glibcxx_lt_pic_flag=
   glibcxx_compiler_pic_flag=


Otherwise we define _GLIBCXX_SHARED for non-shared builds and get unwanted (and useless) symbols in the static lib.
Comment 6 Daniel Richard G. 2014-05-21 21:08:55 UTC
(In reply to Jonathan Wakely from comment #4)
> 
> Instead of building GCC with --disable-shared, why not just use
> -static-libstdc++ when linking?

It was a long time ago that I last tried that, so I can't say for sure, but it was probably that executables were being produced that still had some-or-other GCC shared-runtime dependency.

(This GCC instance is being used for production builds, so it's release-engineering considerations uber alles)
Comment 7 Jonathan Wakely 2014-05-22 12:49:29 UTC
Seems unlikely, but if -static-libgcc -static-libstdc++ gives you a runtime dependency on GCC then that should be reported as a bug.
Comment 8 Daniel Richard G. 2014-05-23 04:39:00 UTC
(In reply to Jonathan Wakely from comment #7)
> Seems unlikely, but if -static-libgcc -static-libstdc++ gives you a runtime
> dependency on GCC then that should be reported as a bug.

I tried a 4.9.0 build without --disable-shared to jog my memory. The problem was twofold:

First, GCC can't find its own runtime library when linking programs:

    /usr/bin/ld: cannot find -lgcc_s

I can specify -L$(PREFIX)/lib/gcc/x86_64-unknown-linux-gnu/lib64 manually, and that allows things to link. But then, unless I futz with ld.so.conf/LD_LIBRARY_PATH, the resulting executable uses the wrong instance of libgcc/libstdc++:

    $ ldd swig 
        linux-vdso.so.1 =>  (0x00007fff76839000)
	libdl.so.2 => /lib64/libdl.so.2 (0x000000302ee00000)
	libstdc++.so.6 => /usr/lib64/libstdc++.so.6 (0x0000003039a00000)
	libm.so.6 => /lib64/libm.so.6 (0x000000302e600000)
	libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x0000003035a00000)
	libc.so.6 => /lib64/libc.so.6 (0x000000302ea00000)
	/lib64/ld-linux-x86-64.so.2 (0x000000302e200000)

(Note: It's probably relevant that I also build GCC with --enable-version-specific-runtime-libs, to avoid a different way that the runtimes can get mixed up.)

Not having to specify -static-libblah is a bonus, but these were the real reasons that I was using --disable-shared. Should I file a new bug for this?
Comment 9 Scott Lipcon 2015-01-08 14:25:09 UTC
We saw the same issue with gcc 4.9.2 on x86_64 Linux - we build the compiler with --disable-shared in order to be able to deliver our software on systems without libstdc++.so.   Without the patches in this issue, we were unable to link our .sos to libstdc++.a because of the missing -fPIC.   The patch I ended up using was a bit different than those in the comments below, but seems to be working for our installation:

--- libstdc++-v3/configure.ac.orig	2015-01-08 08:40:40.480754159 -0500
+++ libstdc++-v3/configure.ac	2015-01-08 08:43:27.633844665 -0500
@@ -120,6 +120,11 @@
   glibcxx_compiler_pic_flag="$lt_prog_compiler_pic_CXX"
   glibcxx_compiler_shared_flag="-D_GLIBCXX_SHARED"
 
+elif test "${with_pic+set}" = set; then
+  glibcxx_lt_pic_flag="-prefer-pic"
+  glibcxx_compiler_pic_flag="$lt_prog_compiler_pic_CXX"
+  glibcxx_compiler_shared_flag=
+
 else
   glibcxx_lt_pic_flag=
   glibcxx_compiler_pic_flag=


I hope this gets applied to an official release at some point.
Comment 10 Jonathan Wakely 2016-01-18 16:26:41 UTC
(In reply to Daniel Richard G. from comment #8)
> First, GCC can't find its own runtime library when linking programs:
> 
>     /usr/bin/ld: cannot find -lgcc_s

That's Bug 35248, it's a problem with --enable-version-specific-runtime-libs

> I can specify -L$(PREFIX)/lib/gcc/x86_64-unknown-linux-gnu/lib64 manually,
> and that allows things to link. But then, unless I futz with
> ld.so.conf/LD_LIBRARY_PATH, the resulting executable uses the wrong instance
> of libgcc/libstdc++:

Yes, that's how linking works.

https://gcc.gnu.org/onlinedocs/libstdc++/faq.html#faq.how_to_set_paths
Comment 11 Alec Ari 2016-11-20 16:53:04 UTC
This fix worked for me:

--- a/libstdc++-v3/configure.ac
+++ b/libstdc++-v3/configure.ac
@@ -121,8 +121,8 @@ if test "$enable_shared" = yes; then
   glibcxx_compiler_shared_flag="-D_GLIBCXX_SHARED"
 
 else
-  glibcxx_lt_pic_flag=
-  glibcxx_compiler_pic_flag=
+  glibcxx_lt_pic_flag="-prefer-pic"
+  glibcxx_compiler_pic_flag="$lt_prog_compiler_pic_CXX"
   glibcxx_compiler_shared_flag=
 fi

(no elif / no else if)

Thanks guys, finally having GCC compiled!
Comment 12 Daniel Richard G. 2019-07-10 03:13:19 UTC
This issue appears to persist in 9.1.0, where it prevents bootstrap from completing:

[...]
libtool: link:  /tmp/gcc-9.1.0.build/./gcc/xg++ -B/tmp/gcc-9.1.0.build/./gcc/ -nostdinc++ -nostdinc++ -I/tmp/gcc-9.1.0.build/x86_64-pc-linux-gnu/libstdc++-v3/include/x86_64-pc-linux-gnu -I/tmp/gcc-9.1.0.build/x86_64-pc-linux-gnu/libstdc++-v3/include -I/home/src/gcc/gcc-9.1.0/libstdc++-v3/libsupc++ -I/home/src/gcc/gcc-9.1.0/libstdc++-v3/include/backward -I/home/src/gcc/gcc-9.1.0/libstdc++-v3/testsuite/util -L/tmp/gcc-9.1.0.build/x86_64-pc-linux-gnu/libstdc++-v3/src -L/tmp/gcc-9.1.0.build/x86_64-pc-linux-gnu/libstdc++-v3/src/.libs -L/tmp/gcc-9.1.0.build/x86_64-pc-linux-gnu/libstdc++-v3/libsupc++/.libs -B/tmp/gcc-9.1.0.build/x86_64-pc-linux-gnu/libstdc++-v3/src/.libs -B/tmp/gcc-9.1.0.build/x86_64-pc-linux-gnu/libstdc++-v3/libsupc++/.libs -B/opt/gnu/x86_64-pc-linux-gnu/bin/ -B/opt/gnu/x86_64-pc-linux-gnu/lib/ -isystem /opt/gnu/x86_64-pc-linux-gnu/include -isystem /opt/gnu/x86_64-pc-linux-gnu/sys-include   -fchecking=1  -fPIC -DPIC -shared -nostdlib /usr/lib/../lib64/crti.o /tmp/gcc-9.1.0.build/./gcc/crtbeginS.o  .libs/findcomp.o .libs/libcc1.o .libs/libcp1.o .libs/names.o .libs/callbacks.o .libs/connection.o .libs/marshall.o   -L/tmp/gcc-9.1.0.build/x86_64-pc-linux-gnu/libstdc++-v3/src/.libs -L/tmp/gcc-9.1.0.build/x86_64-pc-linux-gnu/libstdc++-v3/src -L/tmp/gcc-9.1.0.build/x86_64-pc-linux-gnu/libstdc++-v3/libsupc++/.libs -L/tmp/gcc-9.1.0.build/./gcc -L/lib/../lib64 -L/usr/lib/../lib64 /tmp/gcc-9.1.0.build/x86_64-pc-linux-gnu/libstdc++-v3/src/.libs/libstdc++.a -lm -lc -lgcc /tmp/gcc-9.1.0.build/./gcc/crtendS.o /usr/lib/../lib64/crtn.o  -static-libstdc++ -static-libgcc ../libiberty/pic/libiberty.a   -Wl,-soname -Wl,libcc1.so.0 -Wl,-retain-symbols-file -Wl,/home/src/gcc/gcc-9.1.0/libcc1/libcc1.sym -o .libs/libcc1.so.0.0.0
/usr/bin/ld: /tmp/gcc-9.1.0.build/x86_64-pc-linux-gnu/libstdc++-v3/src/.libs/libstdc++.a(class_type_info.o): relocation R_X86_64_32S against `_ZTVN10__cxxabiv117__class_type_infoE' can not be used when making a shared object; recompile with -fPIC
/tmp/gcc-9.1.0.build/x86_64-pc-linux-gnu/libstdc++-v3/src/.libs/libstdc++.a: could not read symbols: Bad value
collect2: error: ld returned 1 exit status
gmake[3]: *** [libcc1.la] Error 1
gmake[3]: Leaving directory `/tmp/gcc-9.1.0.build/libcc1'
gmake[2]: *** [all] Error 2
gmake[2]: Leaving directory `/tmp/gcc-9.1.0.build/libcc1'
gmake[1]: *** [all-libcc1] Error 2
gmake[1]: Leaving directory `/tmp/gcc-9.1.0.build'
gmake: *** [bootstrap-lean] Error 2

(This tree was configured with --disable-shared --enable-version-specific-runtime-libs --with-pic)

I have confirmed that Alec's workaround (in comment #11) still does the trick.
Comment 13 Andrew Pinski 2022-08-01 22:27:31 UTC
*** Bug 106501 has been marked as a duplicate of this bug. ***
Comment 14 Jonathan Wakely 2022-08-01 23:07:42 UTC
(In reply to Alec Ari from comment #11)
> This fix worked for me:
> 
> --- a/libstdc++-v3/configure.ac
> +++ b/libstdc++-v3/configure.ac
> @@ -121,8 +121,8 @@ if test "$enable_shared" = yes; then
>    glibcxx_compiler_shared_flag="-D_GLIBCXX_SHARED"
>  
>  else
> -  glibcxx_lt_pic_flag=
> -  glibcxx_compiler_pic_flag=
> +  glibcxx_lt_pic_flag="-prefer-pic"
> +  glibcxx_compiler_pic_flag="$lt_prog_compiler_pic_CXX"
>    glibcxx_compiler_shared_flag=
>  fi
> 
> (no elif / no else if)

But this means always PIC, doesn't it? Even if you build with --disable-shared and --without-pic. Surely that's not right? Why is this better than comment 9?