Сборка vozduxan через CMake¶
vozduxan — это статическая библиотека C++ (libvozduxan.a), оборачивающая libtorrent-rasterbar. Она находится в Git-субмодуле vozduxan/ и собирается из Rust build.rs через крейт cmake.
Источники: vozduxan/CMakeLists.txt, src-tauri/build.rs
Структура CMakeLists.txt¶
project(vozduxan VERSION 1.0.8 LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.15") # минимальная версия macOS
Обнаружение libtorrent: трёхуровневая стратегия¶
1. find_package(LibtorrentRasterbar CONFIG) # установленный CMake-пакет
│
└─ не найден ──▶
2. pkg_check_modules(LIBTORRENT libtorrent-rasterbar) # pkg-config
│
└─ не найден ──▶
3. FetchContent: github.com/arvidn/libtorrent v2.0.10 # сборка из исходников
BUILD_SHARED_LIBS = OFF
OPENSSL_USE_STATIC_LIBS = ON
install(TARGETS torrent-rasterbar ARCHIVE DESTINATION lib)
Вызов install() в пути FetchContent критически важен: он помещает libtorrent-rasterbar.a в <cmake_dst>/lib/, откуда build.rs может найти его через cargo:rustc-link-search.
Цель библиотеки vozduxan¶
add_library(vozduxan STATIC
src/session.cpp
src/api.cpp
)
target_link_libraries(vozduxan PRIVATE ${LT_TARGET})
install(TARGETS vozduxan ARCHIVE DESTINATION lib)
install(DIRECTORY include/ DESTINATION include)
Библиотека устанавливается в <cmake_dst>/lib/libvozduxan.a. build.rs линкует её как cargo:rustc-link-lib=static=vozduxan.
Интеграция с build.rs¶
fn build_vozduxan() {
let vozduxan_dir = manifest_dir.parent().unwrap().join("vozduxan");
let dst = cmake::Config::new(&vozduxan_dir)
.profile("Release")
.define("CMAKE_BUILD_TYPE", "Release")
.define("CMAKE_POSITION_INDEPENDENT_CODE", "ON")
.define("OPENSSL_USE_STATIC_LIBS", "ON") // только macOS
.build();
println!("cargo:rustc-link-search=native={}", dst.join("lib").display());
println!("cargo:rustc-link-lib=static=vozduxan");
// ...
}
cmake::Config::build() запускает CMake configure + build + install в директории, управляемой build-скриптом, внутри target/. Результирующий <dst>/lib/ добавляется в путь поиска линкера.
Платформо-зависимое линкование¶
После libvozduxan.a build.rs линкует её зависимости:
macOS:
cargo:rustc-link-lib=static=torrent-rasterbar (статическая FetchContent)
OR
cargo:rustc-link-lib=static=torrent-rasterbar (Homebrew /opt/homebrew/lib)
OR
cargo:rustc-link-lib=dylib=torrent-rasterbar (Homebrew динамическая, запасной вариант)
cargo:rustc-link-lib=static=ssl
cargo:rustc-link-lib=static=crypto ← Homebrew OpenSSL (предпочитает статическую .a)
cargo:rustc-link-lib=framework=SystemConfiguration
cargo:rustc-link-lib=framework=CoreFoundation
cargo:rustc-link-lib=framework=IOKit
OpenSSL предпочтительно линкуется как статический .a, чтобы избежать ошибок Library not loaded: .../libssl.dylib на машинах без Homebrew или с другими путями OpenSSL.
Linux:
cargo:rustc-link-lib=dylib=torrent-rasterbar (или через pkg-config)
cargo:rustc-link-lib=dylib=ssl
cargo:rustc-link-lib=dylib=crypto
cargo:rustc-link-lib=dylib=pthread
Windows:
cargo:rustc-link-lib=static=torrent-rasterbar
cargo:rustc-link-lib=dylib=ws2_32
cargo:rustc-link-lib=dylib=iphlpapi
Стандартная библиотека C++ (link_cxx_stdlib) линкуется до libtorrent в порядке линкования, чтобы линкер разрешал символы C++ из libvozduxan.a перед обработкой символов libtorrent.
rerun-if-changed — ошибка с mtime директорий на macOS¶
rerun-if-changed Cargo на директорию реагирует только при изменении mtime директории. macOS (APFS) не обновляет mtime родительской директории при изменении файла внутри неё. Поэтому изменение vozduxan/src/session.cpp не вызвало бы пересборку.
build.rs перечисляет отдельные файлы C++ вместо этого:
for entry in std::fs::read_dir(vozduxan_dir.join("src")).flatten().flatten() {
println!("cargo:rerun-if-changed={}", entry.path().display());
}
for entry in std::fs::read_dir(vozduxan_dir.join("include")).flatten().flatten() {
println!("cargo:rerun-if-changed={}", entry.path().display());
}
println!("cargo:rerun-if-changed={}", vozduxan_dir.join("CMakeLists.txt").display());
Это гарантирует, что cargo tauri dev (режим наблюдения) корректно обнаруживает изменения в исходниках C++ на macOS.
Стандартная библиотека C++¶
fn link_cxx_stdlib() {
#[cfg(target_os = "macos")]
println!("cargo:rustc-link-lib=dylib=c++"); // libc++ (системная)
#[cfg(target_os = "linux")]
println!("cargo:rustc-link-lib=dylib=stdc++"); // libstdc++
// Windows: MSVC CRT линкуется автоматически
}
Должна идти до libtorrent в порядке линкования.