Как я могу собрать код Rust с проектом C ++ / Qt / CMake?

У меня есть C ++ / Qt проект построен с CMake. Я хотел бы начать добавлять код Rust, который я могу вызывать из основной кодовой базы C ++.

Как правильно структурировать проект?

Текущая структура проекта:

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

Я хотел бы добавить common-rust/... каталог с аналогичной структурой.

Как я могу включить это в проект?

26

Решение

Вы можете использовать ExternalProject модуль за это. Он предназначен для построения внешних зависимостей — даже тех, которые не используют CMake. Вот полезная статья на его использовании.

Допустим, у вас есть подкаталог «common-rust», а его Cargo.toml содержит:

[package]
name = "rust_example"version = "0.1.0"
[lib]
name = "rust_example"crate-type = ["staticlib"]

и это выставляет функцию add через его lib.rs:

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

Тогда ваш 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)

Когда вы строите цель Rust как staticlib он выводит, какие другие библиотеки должны быть связаны. Я только попробовал это на Windows, следовательно ws2_32, userenv, а также advapi32 связаны. Очевидно, это не будет кроссплатформенным, но вы можете справиться с этим достаточно легко (например, установите переменную в списке зависимостей, соответствующих каждой платформе внутри if..else заблокировать и добавить, что в target_link_libraries вызов).

Также обратите внимание, что это зависит от наличия груза на пути.

Тебе должно быть хорошо идти. Файл «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;
}

Вот ссылка на рабочий пример проекта.

37

Другие решения


По вопросам рекламы [email protected]