Linking C++ on Rust: undefined reference to `operator delete(void*)' and `__gxx_personality_v0', libstdc++ missing?

I'm trying to build a cpp cmake project and link to my Rust project.

cmake_minimum_required(VERSION 3.0)
set (CMAKE_CXX_STANDARD 17)
project(ZLMediaKit_LIB CXX)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17")

set(ENABLE_TESTS OFF FORCE)
option(ENABLE_TESTS OFF)

set(ENABLE_OPENSSL FALSE FORCE)
option(ENABLE_OPENSSL OFF)

add_subdirectory(ZLMediaKit)

add_library(libzlmediakit_cpp_interface STATIC interface.cpp)
target_include_directories(libzlmediakit_cpp_interface PUBLIC 
. 
${CMAKE_CURRENT_SOURCE_DIR}/ZLMediaKit/src 
${CMAKE_CURRENT_SOURCE_DIR}/ZLMediaKit/3rdpart/ZLToolKit/src)
target_link_libraries(libzlmediakit_cpp_interface zlmediakit zltoolkit mpeg mov flv libstdc++)
install(TARGETS libzlmediakit_cpp_interface DESTINATION .)

Here's my build.rs:

extern crate cmake;
use cmake::Config;

fn main()
{
    let dst = Config::new("zlmediakit_lib").build();       

    println!("cargo:rustc-link-search=native={}", dst.display());
    println!("cargo:rustc-link-lib=static=libzlmediakit_cpp_interface");    
}

But I'm getting undefined reference errors:

ong)':
          /usr/include/c++/9/ext/new_allocator.h:128: undefined reference to `operator delete(void*)'
          /usr/bin/ld: /home/dev/orwell/liborwell_rust/zlmediakit_rust/target/debug/build/zlmediakit_rust-499cc82f14515635/out/liblibzlmediakit_cpp_interface.a(interface.cpp.o): in function `ZLRTSPClient::~ZLRTSPClient()':
          /home/dev/orwell/liborwell_rust/zlmediakit_rust/zlmediakit_lib/ZLRTSPClient.h:14: undefined reference to `std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string()'
          /usr/bin/ld: /home/dev/orwell/liborwell_rust/zlmediakit_rust/target/debug/build/zlmediakit_rust-499cc82f14515635/out/liblibzlmediakit_cpp_interface.a(interface.cpp.o): in function `std::default_delete<ZLRTSPClient>::operator()(ZLRTSPClient*) const':
          /usr/include/c++/9/bits/unique_ptr.h:81: undefined reference to `operator delete(void*, unsigned long)'
          /usr/bin/ld: /home/dev/orwell/liborwell_rust/zlmediakit_rust/target/debug/build/zlmediakit_rust-499cc82f14515635/out/liblibzlmediakit_cpp_interface.a(interface.cpp.o): in function `__static_initialization_and_destruction_0(int, int)':
          /usr/include/c++/9/iostream:74: undefined reference to `std::ios_base::Init::Init()'
          /usr/bin/ld: /usr/include/c++/9/iostream:74: undefined reference to `std::ios_base::Init::~Init()'
          /usr/bin/ld: /home/dev/orwell/liborwell_rust/zlmediakit_rust/target/debug/build/zlmediakit_rust-499cc82f14515635/out/liblibzlmediakit_cpp_interface.a(interface.cpp.o):(.data.rel.local.DW.ref.__gxx_personality_v0[DW.ref.__gxx_personality_v0]+0x0): undefined reference to `__gxx_personality_v0'
          collect2: error: ld returned 1 exit status

I've researched and found some answers (https://stackoverflow.com/questions/6045809/link-error-undefined-reference-to-gxx-personality-v0-and-g) that old me to link against libstdc++. As you see, I'm already doing that.

If I try to compile the CMake project alone, it links sucessfully. However then I compile everything from the Rust side, it gives this error.

Complete output of rust compilation: https://pastebin.com/Vza1dv3r

I think adding println!("cargo:rustc-link-lib=dylib=stdc++"); will fix it. target_link_libraries in your cmake file is only used when you are creating a dynamic library. On the rust side however you are linking to a static library. This means that the linker is never invoked when creating the library. Only rustc invokes a linker, so you need to tell rustc about all the necessary libraries to link to.

1 Like

Shouldn't it be c++ instead of cc here ?

I see that kind of error when I accidentally try to compile a C++ file with a C compiler. gcc instead of g++, clang instead of clang++.

According to https://www.geeksforgeeks.org/difference-between-gcc-and-g/ the difference between gcc and g++ is:

  • g++ always interprets source as C++
  • g++ adds the C++ standard library to the linker invocation (-lstdc++)
  • some differences in defined macros

The second step difference is the problem here. It only matters for the final linking step, which in this case is performed by rustc. You thus have to manually add stdc++ as required dynamic library using println!("cargo:rustc-link-lib=dylib=stdc++");.

how can I force it to compile with g++ from Rust? Running cmake . && make works but compiling from Rust will give that error

If by compiling from Rust you mean the cc crate, then set:

and