Linking Problems Due to Symbols with Abi::Cxx11

GCC undefined references with abi:cxx11

_GLIBCXX_USE_CXX11_ABI is a preprocessor macro that controls the behavior of the GNU C++ standard library implementation. It needs to be passed to the preprocessor, not CMake.

Use add_compile_definitions(_GLIBCXX_USE_CXX11_ABI=0) in your CMakeLists.txt or pass it via CMAKE_CXX_FLAGS on the command line:

cmake -DCMAKE_CXX_FLAGS='-D_GLIBCXX_USE_CXX11_ABI=0' path/to/your/project

Note that while this may get your program to build, it likely won't be enough to make everything work. Mixing object code compiled by different versions of GCC is fraught with issues.

Link problems with abi:cxx11 on small project

If you declare a static data member in a class, it's similar to declare a variable as extern. This code

class Foo {
static int data;
};

declares Foo::data. You need to define the variable as this

int Foo:data;

in the compilation unit.

Your data member Coordinator::stocks requires similar definition:

class Coordinator {
private:
typedef std::unordered_map<std::string, StockData> stocks_t;
static stocks_t stocks; // declaration
};

Coordinator::stocks_t Coordinator::stocks;// definition.

This will fix the error

undefined reference to `Coordinator::stocks'

I used the DRY (don't repeat yourself) pattern and introduced a typedef to avoid typing the STL map twice.

Edit:(To complete the answer, based on the comment given from OP).

The unresolved externals

undefined reference to `std::filesystem::...

can be resolved by linking the stdc++fs library. For this purpose stdc++fs should be added to the TARGET_LINK_LIBRARIES in the CMakeFile.

_GLIBCXX_USE_CXX11_ABI, GCC 4.8 and ABI compatibility

It's possible to use the C++11 ABI with gcc 4.8.2, but it's a dangerous hack; you would be far better off if at all possible to ask your vendors to ship libraries compiled with the C++03 ABI (-D_GLIBCXX_USE_CXX11_ABI=0) or to upgrade to GCC 5 or above.

You would need to download and install gcc 5 so that you can use its libstdc++ headers and libraries, then direct gcc 4.8 to use those in preference to its own. In addition, because gcc 4.8 is missing some intrinsics required by the libstdc++ shipped with gcc 5, you would need to hack out their usage.

For example, to compile a simple single-file application that includes <string>:

/usr/local/gcc-4.8.2/bin/g++ \
-std=c++11 \
-D_GLIBCXX_USE_CXX11_ABI=1 \
-D'__is_trivially_copyable(...)=0' \
-D'__is_trivially_constructible(...)=0' \
-D'__is_trivially_assignable(...)=0' \
-nostdinc++ \
-isystem /usr/local/gcc-5.4.0/include/c++/5.4.0/ \
-isystem /usr/local/gcc-5.4.0/include/c++/5.4.0/x86_64-unknown-linux-gnu \
-L /usr/local/gcc-5.4.0/lib64
a.cpp

This is dangerous because the gcc 5.4 libstdc++ is not designed to work with gcc 4.8, and redefining the intrinsics used (__is_trivially_copyable etc.) could change the layout of structures or otherwise cause binary incompatibility between your programs and the vendor's libraries.

In order to run the resulting executable, you would also need to ensure that the dynamic linker finds a compatible libstdc++, for example by adding /usr/local/gcc-5.4.0/lib64 to /etc/ld.so.conf, or using -Wl,-rpath /usr/local/gcc-5.4.0/lib64.

Undefined Symbol at Runtime

Turns out this was a third-party library issue.

As @Someprogrammerdude suggested, running CMake with VERBOSE=1 revealed that lib_b.so is linked with -D_GLIBCXX_USE_CXX11_ABI=0.

I changed it manually in B/CMakeFiles/B.dir/flags.cmake to -D_GLIBCXX_USE_CXX11_ABI=1. This time the previous error is gone.

This, however, gave another undefined symbol error with cxx11_abi regarding one of the third-party libraries that we use.

Updating the library to a version that's compiled with CXX11 ABI resolved the issue.

How do I force cxx11 ABI on Red Hat?

The libstdc++ C++11 ABI is not supported on Red Hat Enterprise Linux 7. You have two options:

  • Upgrade to Red Hat Enterprise Linux 8. Its system compiler defaults to the newer ABI.

  • Rebuild the application on Red Hat Enterprise Linux 7, using Developer Toolset. The hybrid linkage model ensures that the application will run on Red Hat Enterprise Linux 7. Only the old ABI is available, but this generally does not matter due to the rebuild because the result is internally consistent.

Boost Linking problems

Try compiling your code while defining macro _GLIBCXX_USE_CXX11_ABI=0, e.g.:

add_compile_definitions(_GLIBCXX_USE_CXX11_ABI=0)

https://gcc.gnu.org/onlinedocs/libstdc++/manual/using_dual_abi.html

If you get linker errors about undefined references to symbols that involve types in the std::__cxx11 namespace or the tag [abi:cxx11] then it probably indicates that you are trying to link together object files that were compiled with different values for the _GLIBCXX_USE_CXX11_ABI macro. This commonly happens when linking to a third-party library that was compiled with an older version of GCC. If the third-party library cannot be rebuilt with the new ABI then you will need to recompile your code with the old ABI.



Related Topics



Leave a reply



Submit