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.