简体   繁体   English

如何使用 C++/Qt/CMake 项目构建 Rust 代码?

[英]How can I build Rust code with a C++/Qt/CMake project?

I have an existing C++/Qt project built with CMake.我有一个使用 CMake 构建的现有 C++/Qt项目 I'd like to start adding Rust code which I can invoke from inside the main C++ codebase.我想开始添加可以从主 C++ 代码库中调用的 Rust 代码。

What's the right way to structure the project?构建项目的正确方法是什么?

Current project structure:当前项目结构:

./CMakeLists.txt
./subproject-foo/CMakeLists.txt
./subproject-foo/src/...
./subproject-bar/CmakeLists.txt
./subproject-bar/src/...
./common/CMakeLists.txt
./common/src/...

I'd like to add a common-rust/... directory with similar structure.我想添加一个结构相似的common-rust/...目录。

How can I incorporate this into the project?我怎样才能把它融入到项目中?

You can use the ExternalProject module for this. 您可以使用ExternalProject模块 It's designed to allow building of external dependencies - even ones which don't use CMake. 它旨在允许构建外部依赖项 - 甚至是那些不使用CMake的依赖项。 Here's a useful article on using it. 这是一篇关于使用它的有用文章

So say you have your "common-rust" subdirectory and its Cargo.toml contains: 所以说你有“common-rust”子目录,它的Cargo.toml包含:

[package]
name = "rust_example"
version = "0.1.0"

[lib]
name = "rust_example"
crate-type = ["staticlib"]

and it exposes a function add via its lib.rs: 它通过lib.rs公开一个函数add

#[no_mangle]
pub extern fn add(lhs: u32, rhs: u32) -> u32 {
    lhs + rhs
}

Then your top-level CMakeLists.txt could look something like this: 然后你的顶级CMakeLists.txt看起来像这样:

add_executable(Example cpp/main.cpp)

# Enable ExternalProject CMake module
include(ExternalProject)

# Set default ExternalProject root directory
set_directory_properties(PROPERTIES EP_PREFIX ${CMAKE_BINARY_DIR}/Rust)

# Add rust_example as a CMake target
ExternalProject_Add(
    rust_example
    DOWNLOAD_COMMAND ""
    CONFIGURE_COMMAND ""
    BUILD_COMMAND cargo build COMMAND cargo build --release
    BINARY_DIR "${CMAKE_SOURCE_DIR}/common-rust"
    INSTALL_COMMAND ""
    LOG_BUILD ON)

# Create dependency of Example on rust_example
add_dependencies(Example rust_example)

# Specify Example's link libraries
target_link_libraries(Example
    debug "${CMAKE_SOURCE_DIR}/common-rust/target/debug/librust_example.a"
    optimized "${CMAKE_SOURCE_DIR}/common-rust/target/release/librust_example.a"
    ws2_32 userenv advapi32)

set_target_properties(Example PROPERTIES CXX_STANDARD 11 CXX_STANDARD_REQUIRED ON)

When you build the Rust target as a staticlib it outputs which other libraries should be linked. 当您将Rust目标构建为staticlib它会输出应链接的其他库。 I've only tried this on Windows, hence ws2_32 , userenv , and advapi32 are linked. 我只在Windows上试过这个,因此ws2_32userenvadvapi32是相互关联的。 This won't be cross-platform obviously, but you can handle that easily enough (eg set a variable to the list of dependencies appropriate to each platform inside an if..else block and append that in the target_link_libraries call). 这显然不是跨平台的,但您可以轻松地处理(例如,将变量设置为适合于if..else块内每个平台的依赖项列表,并将其附加到target_link_libraries调用中)。

Also note that this depends on Cargo being available in the path. 另请注意,这取决于货物在路径中可用。

You should be good to go now. 你现在应该好好去。 The file "cpp/main.cpp" could contain something like: 文件“cpp / main.cpp”可能包含以下内容:

#include <cstdint>
#include <iostream>

extern "C" {
  uint32_t add(uint32_t lhs, uint32_t rhs);
}

int main() {
  std::cout << "1300 + 14 == " << add(1300, 14) << '\n';
  return 0;
}

Here's a link to a working example project . 这是一个工作示例项目的链接。

There is now a project that can be used to build: Corrosion https://github.com/corrosion-rs/corrosion现在有一个可以用来构建的项目:Corrosion https://github.com/corrosion-rs/corrosion

So your CMakeLists.txt would just have this:所以你的 CMakeLists.txt 会有这个:

# See the Corrosion README to find more ways to get Corrosion
find_package(Corrosion REQUIRED)

corrosion_import_crate(MANIFEST_PATH ${CMAKE_SOURCE_DIR}/common-rust)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM