Найти тему
Один Rust не п...Rust

CMake в Rust

t.me/oneRustnoqRust Ежедневная рассылка

Для чего нужна данная статья? :

Научиться использовать CMake в Rust в разных сценариях, при работе с системами сборки, которые требуют интеграции с C или C++ кодом, а также при построении кросс-платформенных проектов.

Зачем Вам это уметь? :

1. Использование CMake в build.rs

Если проект на Rust зависит от C/C++ кода, то в файле build.rs (скрипт сборки для Cargo) можно вызывать CMake для сборки сторонних C/C++ библиотек:

Добавление CMake в зависимостях:

В Cargo.toml нужно добавить зависимость на cmake crate:
[build-dependencies] cmake = "0.1"

Пример использования cmake crate в build.rs:
extern crate cmake;

use cmake::Config;

fn main() {
let dst = Config::new("путь_к_проекту_C").build();


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


println!("cargo:rustc-link-lib=static=имя_библиотеки");
}

2. Сборка C/C++ библиотеки с помощью CMake и последующая её интеграция через FFI

Сначала необходимо настроить CMake для сборки C/C++ библиотеки.

В Rust с помощью FFI можно подключить и использовать скомпилированную библиотеку:

Использование библиотеки через FFI:
#[link(name = "имя_библиотеки")] extern "C" {
// объявление функций, которые импортируются из C/C++ fn c_function(x: i32) -> i32;
}

fn main() {
unsafe {
let result = c_function(10);
println!("Result from C: {}", result);
}
}

3. Встраивание Rust в проекты на C/C++ с помощью CMake

В некоторых случаях может быть обратная задача: вы хотите встроить код на Rust в существующий CMake-проект на C/C++. Для этого создаются CMake-скрипты, которые вызывают Cargo для компиляции кода на Rust, а затем подключают скомпилированную библиотеку:

Использование Cargo в CMake:
find_package(Cargo REQUIRED)

add_custom_target(
RustLib ALL
COMMAND cargo build --release
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/rust_code
COMMENT "Building Rust code"
)

add_library(my_rust_lib STATIC IMPORTED)
set_target_properties(my_rust_lib PROPERTIES
IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/rust_code/target/release/librust_code.a
)

add_dependencies(my_rust_lib RustLib)

4. Cross-compilation

В некоторых случаях можно использовать CMake для кросс-компиляции проектов на C/C++, которые затем связываются с Rust. Для этого настраиваются соответствующие конфигурации CMake и сборка через build.rs в зависимости от таргета, на который компилируется Rust.

5. Использование Bindgen для автогенерации FFI

Иногда нужно автоматически генерировать привязки (bindings) для C/C++ библиотек. Для этого используется crate bindgen, но для генерации некоторых привязок может потребоваться предварительная сборка C/C++ кода с помощью CMake.