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
Expansion with Variadic Templates
How to Make G++ Preprocessor Output a Newline in a MACro
How to Use Sfinae for Selecting Constructors
How to Test a String for Letters Only
Area of Rectangle-Rectangle Intersection
Is There a Portable Equivalent to Debugbreak()/_Debugbreak
Does Casting to an Int After Std::Floor Guarantee the Right Result
Handling Partial Return from Recv() Tcp in C
Creating a Zip File on Windows (Xp/2003) in C/C++
Reason Why Not to Have a Delete MACro for C++
Is There a 128 Bit Integer in C++
How to Append Text to Qplaintextedit Without Adding Newline, and Keep Scroll at the Bottom
Why Is a Char and a Bool the Same Size in C++
Why Is Nvidia Pascal Gpus Slow on Running Cuda Kernels When Using Cudamallocmanaged
Enumerating All Available Drive Letters in Windows
Why Does the Standard Differentiate Between Direct-List-Initialization and Copy-List-Initialization