mirror of
https://github.com/spacedriveapp/spacedrive.git
synced 2025-12-11 20:15:30 +01:00
227 lines
6.5 KiB
Rust
227 lines
6.5 KiB
Rust
#![allow(warnings)]
|
|
|
|
//! Native dependencies download and extraction
|
|
|
|
use anyhow::{Context, Result};
|
|
use std::fs;
|
|
use std::path::Path;
|
|
use xz2::read::XzDecoder;
|
|
|
|
const NATIVE_DEPS_URL: &str =
|
|
"https://github.com/spacedriveapp/native-deps/releases/latest/download";
|
|
|
|
/// Download native dependencies for the current platform
|
|
pub fn download_native_deps(filename: &str, dest_dir: &Path) -> Result<()> {
|
|
let url = format!("{}/{}", NATIVE_DEPS_URL, filename);
|
|
|
|
println!("Downloading native dependencies from:");
|
|
println!(" {}", url);
|
|
|
|
let response = reqwest::blocking::get(&url)
|
|
.context("Failed to download native dependencies")?
|
|
.error_for_status()
|
|
.context("Server returned error")?;
|
|
|
|
let total_size = response.content_length().unwrap_or(0);
|
|
let bytes = response.bytes().context("Failed to read response")?;
|
|
|
|
println!("Downloaded {} MB", total_size / 1_000_000);
|
|
|
|
// Extract the archive
|
|
extract_tar_xz(&bytes, dest_dir)?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Download iOS native dependencies
|
|
pub fn download_ios_deps(target: &str, dest_dir: &Path) -> Result<()> {
|
|
let filename = match target {
|
|
"aarch64-apple-ios" => "native-deps-aarch64-ios-apple.tar.xz",
|
|
"aarch64-apple-ios-sim" => "native-deps-aarch64-iossim-apple.tar.xz",
|
|
"x86_64-apple-ios" => "native-deps-x86_64-iossim-apple.tar.xz",
|
|
_ => anyhow::bail!("Unknown iOS target: {}", target),
|
|
};
|
|
|
|
let url = format!("{}/{}", NATIVE_DEPS_URL, filename);
|
|
|
|
println!("Downloading iOS dependencies for {}...", target);
|
|
println!(" {}", url);
|
|
|
|
let response = reqwest::blocking::get(&url)
|
|
.context("Failed to download iOS dependencies")?
|
|
.error_for_status()
|
|
.context("Server returned error")?;
|
|
|
|
let bytes = response.bytes().context("Failed to read response")?;
|
|
|
|
// Create target-specific directory
|
|
let target_dir = dest_dir.join(target);
|
|
fs::create_dir_all(&target_dir)?;
|
|
|
|
// Extract the archive
|
|
extract_tar_xz(&bytes, &target_dir)?;
|
|
|
|
println!(" ✓ Extracted to {}", target_dir.display());
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Extract a .tar.xz archive
|
|
fn extract_tar_xz(data: &[u8], dest: &Path) -> Result<()> {
|
|
println!("Extracting archive...");
|
|
|
|
// Decompress XZ
|
|
let xz_decoder = XzDecoder::new(data);
|
|
|
|
// Extract tar
|
|
let mut archive = tar::Archive::new(xz_decoder);
|
|
archive.unpack(dest).context("Failed to extract archive")?;
|
|
|
|
println!(" ✓ Extracted successfully");
|
|
Ok(())
|
|
}
|
|
|
|
/// Create symlinks for shared libraries on macOS
|
|
pub fn symlink_libs_macos(root: &Path, native_deps: &Path) -> Result<()> {
|
|
#[cfg(target_os = "macos")]
|
|
{
|
|
use std::os::unix::fs as unix_fs;
|
|
|
|
// Create Spacedrive.framework symlink for dylibs (matches v1 behavior)
|
|
let framework = native_deps.join("Spacedrive.framework");
|
|
if framework.exists() {
|
|
// Sign all dylibs in the framework (required for macOS 13+)
|
|
let libs_dir = framework.join("Libraries");
|
|
if libs_dir.exists() {
|
|
println!(" Signing framework libraries...");
|
|
for entry in fs::read_dir(&libs_dir)? {
|
|
let entry = entry?;
|
|
let path = entry.path();
|
|
if path.extension().and_then(|s| s.to_str()) == Some("dylib") {
|
|
// Remove signature first
|
|
let _ = std::process::Command::new("codesign")
|
|
.args(&["--remove-signature", path.to_str().unwrap()])
|
|
.output();
|
|
|
|
// Sign with ad-hoc signature (- means ad-hoc)
|
|
let status = std::process::Command::new("codesign")
|
|
.args(&["-s", "-", "-f", path.to_str().unwrap()])
|
|
.status()
|
|
.context("Failed to run codesign")?;
|
|
|
|
if !status.success() {
|
|
println!(" Warning: Failed to sign {}", path.display());
|
|
}
|
|
}
|
|
}
|
|
println!(" ✓ Signed framework libraries");
|
|
}
|
|
|
|
let target_frameworks = root.join("target").join("Frameworks");
|
|
fs::create_dir_all(&target_frameworks)?;
|
|
|
|
let framework_link = target_frameworks.join("Spacedrive.framework");
|
|
|
|
// Remove existing symlink if present
|
|
let _ = fs::remove_file(&framework_link);
|
|
|
|
unix_fs::symlink(&framework, &framework_link)
|
|
.context("Failed to symlink Spacedrive.framework")?;
|
|
|
|
println!(" ✓ Linked Spacedrive.framework (includes libheif)");
|
|
}
|
|
|
|
// Also symlink individual dylibs from lib/ to target/ for easier access
|
|
let lib_dir = native_deps.join("lib");
|
|
if lib_dir.exists() {
|
|
let target = root.join("target");
|
|
|
|
for entry in fs::read_dir(&lib_dir)? {
|
|
let entry = entry?;
|
|
let filename = entry.file_name();
|
|
let filename_str = filename.to_string_lossy();
|
|
|
|
// Only symlink dylibs
|
|
if filename_str.ends_with(".dylib") {
|
|
let src = entry.path();
|
|
let dst = target.join(&filename);
|
|
|
|
// Remove existing symlink if present
|
|
let _ = fs::remove_file(&dst);
|
|
|
|
unix_fs::symlink(&src, &dst)
|
|
.with_context(|| format!("Failed to symlink {}", filename_str))?;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Bundle libheif from Homebrew (macOS temporary solution)
|
|
///
|
|
/// This copies libheif from Homebrew to the target directory until it's included
|
|
/// in the native-deps package. On macOS, libheif is available via Homebrew and
|
|
/// we bundle it for development builds.
|
|
pub fn bundle_libheif_from_homebrew(root: &Path) -> Result<()> {
|
|
#[cfg(target_os = "macos")]
|
|
{
|
|
let homebrew_libheif = Path::new("/opt/homebrew/lib/libheif.1.dylib");
|
|
|
|
if !homebrew_libheif.exists() {
|
|
println!(" libheif not found in Homebrew. Install with: brew install libheif");
|
|
println!(" HEIC support will not be available.");
|
|
return Ok(());
|
|
}
|
|
|
|
let target_dir = root.join("target");
|
|
fs::create_dir_all(&target_dir)?;
|
|
|
|
let dest = target_dir.join("libheif.1.dylib");
|
|
fs::copy(homebrew_libheif, &dest)
|
|
.context("Failed to copy libheif from Homebrew")?;
|
|
|
|
println!(" ✓ Bundled libheif from Homebrew");
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Create symlinks for shared libraries on Linux
|
|
pub fn symlink_libs_linux(_root: &Path, _native_deps: &Path) -> Result<()> {
|
|
#[cfg(target_os = "linux")]
|
|
{
|
|
use std::os::unix::fs as unix_fs;
|
|
|
|
let lib_dir = native_deps.join("lib");
|
|
if !lib_dir.exists() {
|
|
return Ok(()); // No libs to symlink
|
|
}
|
|
|
|
// Create lib directory in root
|
|
let target_lib = root.join("target").join("lib").join("spacedrive");
|
|
fs::create_dir_all(&target_lib)?;
|
|
|
|
for entry in fs::read_dir(&lib_dir)? {
|
|
let entry = entry?;
|
|
let filename = entry.file_name();
|
|
let filename_str = filename.to_string_lossy();
|
|
|
|
// Only symlink .so files
|
|
if filename_str.contains(".so") {
|
|
let src = entry.path();
|
|
let dst = target_lib.join(&filename);
|
|
|
|
// Remove existing symlink if present
|
|
let _ = fs::remove_file(&dst);
|
|
|
|
unix_fs::symlink(&src, &dst)
|
|
.with_context(|| format!("Failed to symlink {}", filename_str))?;
|
|
}
|
|
}
|
|
}
|
|
|
|
Ok(())
|
|
}
|