From 89ab6ee336e6b115143ca13fb3784f76fd9cec4a Mon Sep 17 00:00:00 2001 From: Alexander Capehart Date: Wed, 19 Feb 2025 12:44:58 -0700 Subject: [PATCH] musikr: clean up buildscript --- musikr/src/main/jni/build.rs | 97 ++++++++++++++++++++---------------- 1 file changed, 55 insertions(+), 42 deletions(-) diff --git a/musikr/src/main/jni/build.rs b/musikr/src/main/jni/build.rs index c9a6bc84f..456db5555 100644 --- a/musikr/src/main/jni/build.rs +++ b/musikr/src/main/jni/build.rs @@ -1,25 +1,22 @@ use cxx_build; use std::env; -use std::path::Path; +use std::path::{Path, PathBuf}; use std::process::Command; +use std::error::Error; -fn main() { - let working_dir = env::current_dir().expect("Failed to get current working directory"); - let target = env::var("TARGET").expect("TARGET env var not set"); - let working_dir = Path::new(&working_dir); - - // Define directories +fn build_taglib(target: &str, working_dir: &Path) -> Result> { let taglib_src_dir = working_dir.join("taglib"); let taglib_build_dir = taglib_src_dir.join("build"); let taglib_pkg_dir = taglib_src_dir.join("pkg"); - - // Determine if building for Android - let is_android = target.contains("android"); - let arch_build_dir = taglib_build_dir.join(&target); let arch_pkg_dir = taglib_pkg_dir.join(&target); - // Prepare cmake command + // If lib/libtag.a exists, we don't need to build it + if arch_pkg_dir.join("lib/libtag.a").exists() { + return Ok(arch_pkg_dir); + } + + // Prepare basic cmake arguments let mut cmake_args = vec![ "-B".to_string(), arch_build_dir.to_str().unwrap().to_string(), @@ -33,9 +30,8 @@ fn main() { "-DCMAKE_CXX_FLAGS=-fPIC".to_string(), ]; - // Add Android-specific arguments if building for Android - if is_android { - // Get architecture + if target.contains("android") { + // Android target, we need to tack on the NDK toolchain file/args let arch = if target == "x86_64-linux-android" { "x86_64" } else if target.contains("i686-linux-android") { @@ -45,7 +41,8 @@ fn main() { } else if target.contains("armv7-linux-androideabi") { "armeabi-v7a" } else { - panic!("Unsupported Android target: {}", target); + // should never happen + return Err(format!("Unsupported Android target: {}", target).into()); }; let clang_path = env::var("CLANG_PATH").expect("CLANG_PATH env var not set"); @@ -53,7 +50,7 @@ fn main() { let ndk_path = if let Some(pos) = clang_path.find(toolchains_marker) { &clang_path[..pos] } else { - panic!("CLANG_PATH does not contain '{}'", toolchains_marker); + return Err(format!("CLANG_PATH does not contain '{}'", toolchains_marker).into()); }; let ndk_toolchain = working_dir.join("android.toolchain.cmake"); @@ -69,10 +66,9 @@ fn main() { let status = Command::new("cmake") .args(&cmake_args) .current_dir(&taglib_src_dir) - .status() - .expect("Failed to run cmake configure"); + .status()?; if !status.success() { - panic!("cmake configure failed for target {}", target); + return Err(format!("cmake configure failed for target {}", target).into()); } // Build step @@ -85,10 +81,9 @@ fn main() { "-j{}", std::thread::available_parallelism().unwrap().get() )) - .status() - .expect("Failed to run cmake build"); + .status()?; if !status.success() { - panic!("cmake build failed for target {}", target); + return Err(format!("cmake build failed for target {}", target).into()); } // Install step @@ -100,22 +95,15 @@ fn main() { .arg("--prefix") .arg(arch_pkg_dir.to_str().unwrap()) .arg("--strip") - .status() - .expect("Failed to run cmake install"); + .status()?; if !status.success() { - panic!("cmake install failed for arch {}", target); + return Err(format!("cmake install failed for arch {}", target).into()); } - println!( - "cargo:rustc-link-search=native={}/lib", - arch_pkg_dir.display() - ); - println!("cargo:rustc-link-lib=static=tag"); - println!("cargo:rustc-link-lib=static=c++_static"); - println!("cargo:rustc-link-lib=static=c++abi"); - println!("cargo:rustc-link-lib=unwind"); + Ok(arch_pkg_dir) +} - // Build the shim and cxx bridge together +fn configure_cxx_bridge(target: &str) -> Result<(), Box> { let mut builder = cxx_build::bridge("src/taglib/bridge.rs"); builder .file("shim/iostream_shim.cpp") @@ -127,19 +115,44 @@ fn main() { .file("shim/id3v2_shim.cpp") .file("shim/mp4_shim.cpp") .include(format!("taglib/pkg/{}/include", target)) - .include(".") // Add the current directory to include path + .include(".") .flag_if_supported("-std=c++14"); - if is_android { + if target.contains("android") { builder .cpp_link_stdlib("c++_static") - .flag("-static-libstdc++") + // Magic linker flags that statically link exception handling symbols + // to the library. .flag("-fexceptions") - .flag("-funwind-tables"); // Use shared C++ runtime for Android compatibility + .flag("-funwind-tables"); } builder.compile("taglib_cxx_bindings"); - // Rebuild if shim files change - println!("cargo:rerun-if-changed=shim/"); - println!("cargo:rerun-if-changed=taglib/"); + Ok(()) +} + +fn main() -> Result<(), Box> { + let working_dir = env::current_dir()?; + let target = env::var("TARGET")?; + let working_dir = Path::new(&working_dir); + + let arch_pkg_dir = build_taglib(&target, &working_dir)?; + println!( + "cargo:rustc-link-search=native={}/lib", + arch_pkg_dir.display() + ); + println!("cargo:rustc-link-lib=static=tag"); + println!("cargo:rerun-if-changed=taglib/"); + + configure_cxx_bridge(&target)?; + if target.contains("android") { + // Magic linker flags that statically link the C++ runtime + // and exception handling to the library. + println!("cargo:rustc-link-lib=static=c++_static"); + println!("cargo:rustc-link-lib=static=c++abi"); + println!("cargo:rustc-link-lib=unwind"); + } + println!("cargo:rerun-if-changed=shim/"); + + Ok(()) }