在 Rust 上链接 C++:对“operator delete(void*)”和“__gxx_personality_v0”的未定义引用,缺少 libstdc++?

Pap*_*ika 5 cmake rust

我正在尝试构建一个 cpp cmake 项目并链接到我的 Rust 项目。

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 .)
Run Code Online (Sandbox Code Playgroud)

这是我的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");    
}
Run Code Online (Sandbox Code Playgroud)

但我收到未定义的参考错误:

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
Run Code Online (Sandbox Code Playgroud)

我研究并找到了一些答案(链接错误“对`__gxx_personality_v0'的未定义引用”和g++),这些答案让我无法链接libstdc++。正如你所看到的,我已经在这样做了。

如果我尝试单独编译 CMake 项目,它会成功链接。然而,当我从 Rust 端编译所有内容时,它给出了这个错误。

Rust编译的完整输出

dae*_*tus 1

如果有人仍然对此感兴趣,似乎您可以通过执行以下操作来修复它:

  1. 您可以将其添加到Cargo.toml
[lib]
crate-type = ["staticlib"]
Run Code Online (Sandbox Code Playgroud)

然而,如果你这样做,你的库基本上无法作为正常的 Rust 依赖项使用,因为这只会生成一个静态 C 库(尽管你仍然可以运行测试:O)。但是,您不需要对bin板条箱执行此操作(可能?)。

如果您确实希望这是一个库,则必须以某种方式找到路径libstdc++.a并将其链接到build.rs文件中,方法是使用println!("cargo:rustc-link-search=native=PATH_TO_LIB");.

您可以通过运行来获取路径g++ --print-file-name=libstdc++.a,但当然您不能将其硬编码到其中,build.rs因为它在不同的系统上会有所不同。

  1. 然后,您有两个选择:
  • 添加println!("cargo:rustc-link-lib=static=stdc++");build.rs(最好在其他print语句之前)。
  • 将构建命令运行为RUSTFLAGS="-C link-args=-lstdc++" cargo build.

长话短说,cmake 生成的静态链接库实际上并不包含代码stdc++,因此我们必须明确告诉 Rust 去哪里寻找它。

如果有人对cmake和有更多的见解cargo,请随时插话并解释为什么这是必要的。对于我来说,我很高兴它有效。