use std::{env, fs}; use std::fmt::{Display, Formatter}; use std::path::{PathBuf}; use cfg_if::cfg_if; #[derive(Copy, Clone, PartialOrd, PartialEq)] #[allow(unused)] enum NApiVersion{ NApi9, NApi10, } #[derive(Copy, Clone,Debug)] #[allow(unused)] enum Target{ Ohos, Android, Ios, } impl Display for NApiVersion { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { let s = match self { NApiVersion::NApi9 => {"9"} NApiVersion::NApi10 => {"10"} }; write!(f, "{}", s) } } fn main() { let mut version_set = None; cfg_if!{ if #[cfg(feature = "napi-10")] { version_set = Some(NApiVersion::NApi10) ; } else if #[cfg(feature = "napi-9")]{ version_set = Some(NApiVersion::NApi9); } } #[allow(unused_assignments)] let mut is_enable_ark_ui_x = false; #[cfg(feature = "ark-ui-x")] { match version_set { None => { version_set = Some(NApiVersion::NApi10); } Some(version) => { if version < NApiVersion::NApi10 { panic!("ArkUiX 最小支持api 10,当前为:{}", version); } } } is_enable_ark_ui_x=true; } let version = version_set.unwrap_or(NApiVersion::NApi9); println!("cargo:warning=Harmony NApi: {}", version); let oh_dir = find_oh_sdk_path(version); println!("OH Sdk path: {}", oh_dir.display()); let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap(); let target_env = env::var("CARGO_CFG_TARGET_ENV").unwrap(); let target_arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap(); let target = if target_env.as_str() == "ohos" { Target::Ohos }else if target_os.as_str() == "android"{ Target::Android }else if target_os.as_str() == "ios"{ Target::Ios }else { un_support_platform(); println!("cargo:warning=[{}] 暂不支持", target_os); return; }; if !is_enable_ark_ui_x{ match target { Target::Ohos => {} _ => { panic!("只有开启 arc-ui-x 才支持:{:?}",target); } } } #[allow(unused_assignments)] let mut include = oh_dir.join("include"); #[cfg(feature = "ark-ui-x")] let ark_ui_x_dir = find_ark_ui_x_sdk_path(version); #[cfg(feature = "ark-ui-x")] { include = ark_ui_x_dir.join("include"); println!("ArkUI-X Sdk path: {}", ark_ui_x_dir.display()); } let mut include_ext: Option = None; match target { Target::Ohos => { let dir_name = format!("{}-linux-ohos", target_arch); let lib_dir = oh_dir.join("lib").join(&dir_name); println!("cargo:rustc-link-search={}", lib_dir.display()); println!("cargo:rustc-link-lib=ace_napi.z"); include_ext = Some(include.join(dir_name)) } _ =>{ #[cfg(feature = "ark-ui-x")] set_android(&ark_ui_x_dir) } } let header = include.join("napi").join("native_api.h"); // The bindgen::Builder is the main entry point // to bindgen, and lets you build up options for // the resulting bindings. let mut cfg = bindgen::Builder::default() // The input header we would like to generate // bindings for. .header(header.display().to_string()) .clang_arg(format!("-I{}", include.display())); match include_ext { None => {} Some(i) => { cfg = cfg.clang_arg(format!("-I{}", i.display())); } } let bindings = cfg // Finish the builder and generate the bindings. .generate() // Unwrap the Result and panic on failure. .expect("Unable to generate bindings"); // Write the bindings to the $OUT_DIR/bindings.rs file. let out_path = PathBuf::from(env::var("OUT_DIR").unwrap()); bindings .write_to_file(out_path.join("bindings.rs")) .expect("Couldn't write bindings!"); } fn find_oh_sdk_path_base(base: PathBuf, version: NApiVersion) -> Option{ let mut api_dir = match version { NApiVersion::NApi9 => { base.join("9") } NApiVersion::NApi10 => { base.join("10") } }; api_dir = api_dir.join("native") .join("sysroot") .join("usr"); if api_dir.exists() { Some(api_dir) }else { None } } fn find_oh_sdk_path(version: NApiVersion) -> PathBuf { let base_dirs = directories::BaseDirs::new().unwrap(); let data_local_dir = base_dirs.data_local_dir(); match find_oh_sdk_path_base(data_local_dir.join("Huawei").join("Sdk").join("openharmony"), version) { None => { match find_oh_sdk_path_base(data_local_dir.join("OpenHarmony").join("Sdk"), version) { None => { let oh_dir = PathBuf::from(env::var("OpenHarmony_HOME").expect("请设置{OpenHarmony_HOME}环境变量指向Sdk文件夹")); match find_oh_sdk_path_base(oh_dir.clone(), version) { None => { panic!("OpenHarmony_HOME: {}\n不存在", oh_dir.display()); } Some(p) => { return p; } } } Some(p) => { return p; } } } Some(p) => { return p; } } } fn find_ark_ui_x_sdk_path_base(base: PathBuf, version: NApiVersion) -> Option{ let mut api_dir = match version { NApiVersion::NApi9 => { base.join("9") } NApiVersion::NApi10 => { base.join("10") } }; api_dir = api_dir.join("arkui-x") .join("engine") .join("lib"); if api_dir.exists() { Some(api_dir) }else { None } } fn find_ark_ui_x_sdk_path(version: NApiVersion) -> PathBuf { let base_dirs = directories::BaseDirs::new().unwrap(); let data_local_dir = base_dirs.data_local_dir(); match find_ark_ui_x_sdk_path_base(data_local_dir.join("ArkUI-X").join("Sdk"), version) { None => { let oh_dir = PathBuf::from(env::var("ArkUI_X_HOME").expect("请设置{ArkUI_X_HOME}环境变量指向Sdk文件夹")); match find_ark_ui_x_sdk_path_base(oh_dir.clone(), version) { None => { panic!("ArkUI_X_HOME: {}\n不存在", oh_dir.display()); } Some(p) => { return p; } } } Some(p) => { return p; } } } fn set_android(ark_ui_dir: &PathBuf){ let target_arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap(); let dir_name = match target_arch.as_str() { "aarch64"=> "android-arm64-release", "arm"=> "android-arm-release", "x86_64"=> "android-x86_64", _=> panic!("{} 不支持", target_arch), }; let lib_dir = ark_ui_dir.join("arkui").join(dir_name); println!("cargo:rustc-link-search={}", lib_dir.display()); println!("cargo:rustc-link-lib=arkui_android"); } fn un_support_platform(){ let out_path = PathBuf::from(env::var("OUT_DIR").unwrap()); fs::File::create(out_path.join("bindings.rs")).unwrap(); }