4

I have recently upgraded my dev machine to Ubuntu 16.04 (fresh install, wiped 14.04)

The default version of gcc is gcc-5.3.1.

A problem that I have is a vendor supplied library is only built using gcc-4.9, which is not compatible with gcc-5.

I have asked the vendor to provide a new version of the library, but it is unlikely that that will happen any time soon.

In the meantime I have installed gcc-4.9.3 from Ubuntu's package repos.

I now have both gcc-4.9 and gcc-5 installed:

ls -l /usr/bin/gcc*
lrwxrwxrwx 1 root root      5 May  9 11:49 /usr/bin/gcc -> gcc-5
-rwxr-xr-x 1 root root 838008 Apr 13 23:23 /usr/bin/gcc-4.9
-rwxr-xr-x 1 root root 915704 Apr 13 11:29 /usr/bin/gcc-5

I tried to build our source with gcc-4.9, but now I come up against the same ABI issues, but going the other way.

The problem I have is that we have a bunch of dependencies which we would typically install from the distro packages

sudo apt-get install \
    python-dev \
    libbz2-dev \
    libboost-all-dev \
    libprotobuf-dev \
    libgoogle-perftools-dev \
    postgresql \
    libpqxx-dev

Whilst I can configure my build to use gcc-4.9

mkdir build && cd build
CC=/usr/bin/gcc-4.9 CXX=/usr/bin/g++-4.9 cmake ..
make -j8

I now get linker errors when linking against libtcmalloc_minimal.a, libprotobuf.a etc.

So the next step that I tried was to remove all the dependencies installed from the distro repos and start building the dependencies from source.

CC=/usr/bin/gcc-4.9 CXX=/usr/bin/g++-4.9 ./configure
make -j8
sudo make install

The problem here is that I'm starting to head down a rabbit-hole. Each dependency has other dependencies, and I'm not sure where it's going to end.

The other option is to downgrade back to Ubuntu 14.04 or some version which ships with gcc-4.9 instead of gcc-5.

Before I try this thurmonuclear option, I was wondering if there's a better way to do this?

Maybe it's possible to install from repos built with gcc-4.9, or some other way?

  • Far to late now, but I was wondering if/how you solved your problem and if you have considered to use a c++ packet manager. – MikeMB Feb 15 '18 at 8:08
9

The problem you have is related to C++11 standard requiring a different implementation of C++ string (and list) type(s). For compatibility, g++5.2 and above compiles the new C++11 compliant type by default, (whether or not you specify -std=c++11), but you can set the macro

-D_GLIBCXX_USE_CXX11_ABI=0

to revert to the old C++ string type. New libstdc++ implementation contain both ABIs. So if you have binaries you have to link against with the old non-compliant ABI, you must set the macro above on your g++ compiles. This should produce binaries compatible with the old ABI.

Unfortunately if you are using libraries from the OS other than the C++ Standard Libraries, then unless these libraries are multi-arch in the sense of providing all functions which differ by ABI in both ABI's, then you're screwed because they'll probably only have the new ABI.

Having said that I have a problem on an old Ubuntu downloading an untrusted modern g++ which simply refuses to produce the new ABI. So it seems that backport from ppa:ubuntu-toolchain-r/test is in fact badly broken because it refuses to produce binaries according to the new ABI.

Anyhow the bottom line is when you link together everything must either be the old ABI or the new ABI. The following will tell which you are using:

g++ --version
echo '#include <string>' > test.cpp
echo 'void f(std::string s) {}' >> test.cpp
cat test.cpp
g++ -std=gnu++11 -c -o test.o test.cpp
nm test.o | c++filt

If that has

std::basic_string<char, ....

in it, its the old ABI. If it has

std::__cxx11::basic_string<char, ...

in it, its the new ABI.

0

Go to tty1 by pressing: CTRL+ALT+F1

Purge gcc-5.3.1 using this:

sudo apt-get purge gcc-5.3.1*

And install the gcc-4.9.3 using this:

sudo apt-get install gcc-4.9.3

Note: This requires Internet connection!

  • I don't believe this will work, for the same reason above - ABI incompatability between gcc-5 (which all the packages will have been built with) and gcc-4.9 (which I'm trying to build with) – Steve Lorimer May 10 '16 at 17:12
0

It is good to use -D_GLIBCXX_USE_CXX11_ABI=0 . but you can also use this option of g++, which can even be better

       -fabi-version=n
           Use version n of the C++ ABI.  The default is version 0.

           Version 0 refers to the version conforming most closely to the C++ ABI specification.  Therefore, the ABI obtained using version 0 will change in different versions of G++ as ABI bugs are
           fixed.

           Version 1 is the version of the C++ ABI that first appeared in G++ 3.2.

           Version 2 is the version of the C++ ABI that first appeared in G++ 3.4, and was the default through G++ 4.9.

           Version 3 corrects an error in mangling a constant address as a template argument.

           Version 4, which first appeared in G++ 4.5, implements a standard mangling for vector types.

           Version 5, which first appeared in G++ 4.6, corrects the mangling of attribute const/volatile on function pointer types, decltype of a plain decl, and use of a function parameter in the
           declaration of another parameter.

           Version 6, which first appeared in G++ 4.7, corrects the promotion behavior of C++11 scoped enums and the mangling of template argument packs, const/static_cast, prefix ++ and --, and a class
           scope function used as a template argument.

           Version 7, which first appeared in G++ 4.8, that treats nullptr_t as a builtin type and corrects the mangling of lambdas in default argument scope.

           Version 8, which first appeared in G++ 4.9, corrects the substitution behavior of function types with function-cv-qualifiers.

           Version 9, which first appeared in G++ 5.2, corrects the alignment of "nullptr_t".

           See also -Wabi.

       -fabi-compat-version=n
           On targets that support strong aliases, G++ works around mangling changes by creating an alias with the correct mangled name when defining a symbol with an incorrect mangled name.  This switch
           specifies which ABI version to use for the alias.

           With -fabi-version=0 (the default), this defaults to 2.  If another ABI version is explicitly selected, this defaults to 0.

           The compatibility version is also set by -Wabi=n.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.