Auxio/musikr/src/main/jni/build.rs
2025-02-15 15:37:54 -07:00

137 lines
4.5 KiB
Rust

use cxx_build;
use std::env;
use std::path::Path;
use std::process::Command;
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
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
let mut cmake_args = vec![
"-B".to_string(),
arch_build_dir.to_str().unwrap().to_string(),
"-DBUILD_SHARED_LIBS=OFF".to_string(),
"-DVISIBILITY_HIDDEN=ON".to_string(),
"-DBUILD_TESTING=OFF".to_string(),
"-DBUILD_EXAMPLES=OFF".to_string(),
"-DBUILD_BINDINGS=OFF".to_string(),
"-DWITH_ZLIB=OFF".to_string(),
"-DCMAKE_BUILD_TYPE=Release".to_string(),
"-DCMAKE_CXX_FLAGS=-fPIC".to_string(),
];
// Add Android-specific arguments if building for Android
if is_android {
// Get architecture
let arch = if target == "x86_64-linux-android" {
"x86_64"
} else if target.contains("i686-linux-android") {
"x86"
} else if target.contains("aarch64-linux-android") {
"arm64-v8a"
} else if target.contains("armv7-linux-androideabi") {
"armeabi-v7a"
} else {
panic!("Unsupported Android target: {}", target);
};
let clang_path = env::var("CLANG_PATH").expect("CLANG_PATH env var not set");
let toolchains_marker = "/toolchains";
let ndk_path = if let Some(pos) = clang_path.find(toolchains_marker) {
&clang_path[..pos]
} else {
panic!("CLANG_PATH does not contain '{}'", toolchains_marker);
};
let ndk_toolchain = working_dir.join("android.toolchain.cmake");
cmake_args.extend(vec![
format!("-DANDROID_NDK_PATH={}", ndk_path),
format!("-DCMAKE_TOOLCHAIN_FILE={}", ndk_toolchain.to_str().unwrap()),
format!("-DANDROID_ABI={}", arch),
]);
}
// Configure step
let status = Command::new("cmake")
.args(&cmake_args)
.current_dir(&taglib_src_dir)
.status()
.expect("Failed to run cmake configure");
if !status.success() {
panic!("cmake configure failed for target {}", target);
}
// Build step
let status = Command::new("cmake")
.arg("--build")
.arg(arch_build_dir.to_str().unwrap())
.arg("--config")
.arg("Release")
.arg(format!(
"-j{}",
std::thread::available_parallelism().unwrap().get()
))
.status()
.expect("Failed to run cmake build");
if !status.success() {
panic!("cmake build failed for target {}", target);
}
// Install step
let status = Command::new("cmake")
.arg("--install")
.arg(arch_build_dir.to_str().unwrap())
.arg("--config")
.arg("Release")
.arg("--prefix")
.arg(arch_pkg_dir.to_str().unwrap())
.arg("--strip")
.status()
.expect("Failed to run cmake install");
if !status.success() {
panic!("cmake install failed for arch {}", target);
}
println!(
"cargo:rustc-link-search=native={}/lib",
arch_pkg_dir.display()
);
println!("cargo:rustc-link-lib=static=tag");
// println!("cargo:rustc-link-lib=cc++_static");
// Build the shim and cxx bridge together
let mut builder = cxx_build::bridge("src/taglib/bridge.rs");
builder
.file("shim/iostream_shim.cpp")
.file("shim/file_shim.cpp")
.file("shim/tk_shim.cpp")
.file("shim/picture_shim.cpp")
.file("shim/xiph_shim.cpp")
.file("shim/id3_shim.cpp")
.include(format!("taglib/pkg/{}/include", target))
.include(".") // Add the current directory to include path
.flag_if_supported("-std=c++14");
if is_android {
builder.cpp_link_stdlib("c++_static"); // Use shared C++ runtime for Android compatibility
}
builder.compile("taglib_cxx_bindings");
// Rebuild if shim files change
println!("cargo:rerun-if-changed=shim/");
println!("cargo:rerun-if-changed=taglib/");
}