c++gcclddynamic-linkingdevtoolset

How does g++/gcc determine which library to link having more than 1 version to choose from?


I have installed devtoolset-3 on RHEL6 machine and I am confused by how gcc/g++ determines which library to link with a binary.

Standard setup on RHEL6:

$ g++ -v
Using built-in specs.
Target: x86_64-redhat-linux
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-bootstrap --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-languages=c,c++,objc,obj-c++,java,fortran,ada --enable-java-awt=gtk --disable-dssi --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-1.5.0.0/jre --enable-libgcj-multifile --enable-java-maintainer-mode --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --disable-libjava-multilib --with-ppl --with-cloog --with-tune=generic --with-arch_32=i686 --build=x86_64-redhat-linux
Thread model: posix
gcc version 4.4.7 20120313 (Red Hat 4.4.7-11) (GCC) 

After I compile a simple, nearly empty C++ binary I get:

$ g++ main.cpp -o main_old && ldd main_old
        linux-vdso.so.1 =>  (0x00007fffe6dfe000)
        libstdc++.so.6 => /usr/lib64/libstdc++.so.6 (0x00000039b4800000)
        libm.so.6 => /lib64/libm.so.6 (0x00000039aa800000)
        libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00000039b4400000)
        libc.so.6 => /lib64/libc.so.6 (0x00000039aa400000)
        /lib64/ld-linux-x86-64.so.2 (0x00000039aa000000)
$ echo $PATH
/usr/local/bin:/usr/bin:/usr/sbin/:/bin/:/sbin
$ echo $LD_LIBRARY_PATH

Then I would install devtoolset-3 (from here https://www.softwarecollections.org/en/scls/rhscl/devtoolset-3/)

and then

$ scl enable devtoolset-3 bash
$ g++ -v
Using built-in specs.
COLLECT_GCC=g++
COLLECT_LTO_WRAPPER=/opt/rh/devtoolset-3/root/usr/libexec/gcc/x86_64-redhat-linux/4.9.1/lto-wrapper
Target: x86_64-redhat-linux
Configured with: ../configure --prefix=/opt/rh/devtoolset-3/root/usr --mandir=/opt/rh/devtoolset-3/root/usr/share/man --infodir=/opt/rh/devtoolset-3/root/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-bootstrap --enable-shared --enable-threads=posix --enable-checking=release --enable-multilib --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-linker-build-id --enable-languages=c,c++,fortran,lto --enable-plugin --with-linker-hash-style=gnu --enable-initfini-array --disable-libgcj --with-isl=/builddir/build/BUILD/gcc-4.9.1-20140922/obj-x86_64-redhat-linux/isl-install --with-cloog=/builddir/build/BUILD/gcc-4.9.1-20140922/obj-x86_64-redhat-linux/cloog-install --with-mpc=/builddir/build/BUILD/gcc-4.9.1-20140922/obj-x86_64-redhat-linux/mpc-install --with-tune=generic --with-arch_32=i686 --build=x86_64-redhat-linux
Thread model: posix
gcc version 4.9.1 20140922 (Red Hat 4.9.1-10) (GCC)
$ g++ main.cpp -o main_new && ldd main_new
       linux-vdso.so.1 =>  (0x00007fffe18ae000)
        libstdc++.so.6 => /usr/lib64/libstdc++.so.6 (0x00000039b4800000)
        libm.so.6 => /lib64/libm.so.6 (0x00000039aa800000)
        libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00000039b4400000)
        libc.so.6 => /lib64/libc.so.6 (0x00000039aa400000)
        /lib64/ld-linux-x86-64.so.2 (0x00000039aa000000)
$ echo $PATH
/usr/lib64/qt-3.3/bin:/opt/rh/devtoolset-3/root/usr/bin/:/opt/rh/devtoolset-3/root/usr/bin:/usr/local/bin:/usr/bin:/usr/sbin/:/bin/:/sbin
$ echo $LD_LIBRARY_PATH
/opt/rh/devtoolset-3/root/usr/lib64:/opt/rh/devtoolset-3/root/usr/lib

I get the same...


Solution

  • GCC does not choose, per se. While GCC (actually ld) will find and examine dynamic libraries when linking (by its own path search order), it merely adds a DT_NEEDED entry for the library's SONAME. Take a look at the DYNAMIC section with readelf.

    At runtime, ld.so chooses which library to link against. The particular library which ld.so selects is determined by its configured path search order. See the man page for ld.so.