use bindgen::Builder;
use std::{env, path::PathBuf};
const SUPPORTED_TARGETS: &[&str] = &["aarch64-unknown-linux-ohos"];
fn main() {
let target = env::var("TARGET").expect("TARGET environment variable not set");
if !SUPPORTED_TARGETS.contains(&target.as_str()) {
println!(
"cargo:warning=Skipping bindgen generation on unsupported target: {}",
target
);
return;
}
let home = env::var("OHOS_NATIVE_HOME").expect("OHOS_NATIVE_HOME environment variable not set");
let bin_path = env::var("PATH").unwrap_or_default();
env::set_var("PATH", format!("{}/llvm/bin:{}", home, bin_path));
let builder = bindgen::Builder::default()
.clang_arg("-x")
.clang_arg("c++")
.clang_arg(format!("--target={}", target))
.rust_target(bindgen::RustTarget::Stable_1_68)
.default_enum_style(bindgen::EnumVariation::ModuleConsts);
generate_egl(&builder);
generate_drawing(&builder);
generate_log(&builder);
generate_napi(&builder);
generate_vsync(&builder);
generate_window(&builder);
generate_xcomponent(&builder);
generate_rdb(&builder);
generate_hidebug(&builder);
generate_bundle(&builder);
generate_input(&builder);
generate_account(&builder);
generate_hitrace(&builder);
generate_asset(&builder);
generate_hiappevent(&builder);
generate_web(&builder);
}
fn generate_hiappevent(builder: &Builder) {
generate(
"hiappevent",
&[
"hiappevent/hiappevent.h",
"hiappevent/hiappevent_cfg.h",
"hiappevent/hiappevent_event.h",
"hiappevent/hiappevent_param.h",
],
&["hiappevent_ndk.z"],
|| {
builder
.clone()
.allowlist_item("(OH_.*)|(EVENT.*)|(HiAppEvent.*)|(DOMAIN_.*)")
},
);
}
fn generate_asset(builder: &Builder) {
generate(
"asset",
&["asset/asset_api.h", "asset/asset_type.h"],
&["asset_ndk.z"],
|| builder.clone().allowlist_item("(OH.*)|(Asset_.*)"),
);
}
fn generate_hitrace(builder: &Builder) {
generate("hitrace", &["hitrace/trace.h"], &["hitrace_ndk.z"], || {
builder.clone().allowlist_item("OH_.*")
});
}
fn generate_account(builder: &Builder) {
generate(
"account",
&[
"BasicServicesKit/os_account.h",
"BasicServicesKit/os_account_common.h",
],
&["os_account_ndk"],
|| builder.clone().allowlist_item("OH_.*"),
);
}
fn generate_input(builder: &Builder) {
generate(
"input",
&[
"multimodalinput/o_input_manager.h",
"multimodalinput/oh_key_code.h",
],
&["ohinput"],
|| {
builder
.clone()
.allowlist_item("OH_.*")
.allowlist_item("Input_.*")
},
);
}
fn generate_bundle(builder: &Builder) {
generate(
"bundle",
&["bundle/native_interface_bundle.h"],
&["bundle_ndk.z"],
|| builder.clone().allowlist_item("OH_.*"),
);
}
fn generate_hidebug(builder: &Builder) {
generate(
"hidebug",
&["hidebug/hidebug.h", "hidebug/hidebug_type.h"],
&["ohhidebug"],
|| builder.clone().allowlist_item("OH_.*"),
);
}
fn generate_rdb(builder: &Builder) {
generate(
"rdb",
&[
"database/rdb/oh_cursor.h",
"database/rdb/oh_predicates.h",
"database/rdb/oh_value_object.h",
"database/rdb/oh_value_bucket.h",
"database/rdb/relational_store.h",
"database/rdb/relational_store_error_code.h",
"database/data/data_asset.h",
],
&["native_rdb_ndk.z"],
|| builder.clone().allowlist_item("OH_.*"),
);
}
fn generate_xcomponent(builder: &Builder) {
generate(
"xcomponent",
&["ace/xcomponent/native_interface_xcomponent.h"],
&["ace_ndk.z"],
|| builder.clone().allowlist_item("OH_.*"),
);
}
fn generate_window(builder: &Builder) {
generate(
"window",
&[
"native_window/external_window.h",
"native_image/native_image.h",
],
&["native_window", "native_image"],
|| builder.clone().allowlist_function("OH_.*"),
);
}
fn generate_vsync(builder: &Builder) {
generate(
"vsync",
&["native_vsync/native_vsync.h"],
&["native_vsync"],
|| builder.clone().allowlist_function("OH_NativeVSync.*"),
);
}
fn generate_egl(builder: &Builder) {
generate(
"egl",
&["EGL/egl.h", "EGL/eglext.h", "EGL/eglplatform.h"],
&["EGL", "GLESv3"],
|| builder.clone(),
);
}
fn generate_drawing(builder: &Builder) {
generate(
"drawing",
&[
"native_drawing/drawing_bitmap.h",
"native_drawing/drawing_brush.h",
"native_drawing/drawing_canvas.h",
"native_drawing/drawing_color.h",
"native_drawing/drawing_font_collection.h",
"native_drawing/drawing_gpu_context.h",
"native_drawing/drawing_matrix.h",
"native_drawing/drawing_path.h",
"native_drawing/drawing_pen.h",
"native_drawing/drawing_point.h",
"native_drawing/drawing_rect.h",
"native_drawing/drawing_register_font.h",
"native_drawing/drawing_sampling_options.h",
"native_drawing/drawing_shader_effect.h",
"native_drawing/drawing_surface.h",
"native_drawing/drawing_text_declaration.h",
"native_drawing/drawing_text_typography.h",
"native_drawing/drawing_types.h",
],
&["native_drawing"],
|| {
builder
.clone()
.allowlist_type("OH_Drawing_.*")
.allowlist_function("OH_Drawing_.*")
},
);
}
fn generate_napi(builder: &Builder) {
generate("napi", &["napi/native_api.h"], &["ace_napi.z"], || {
builder.clone().allowlist_function("napi_.*")
});
}
fn generate_log(builder: &Builder) {
generate("log", &["hilog/log.h"], &["hilog_ndk.z"], || {
builder.clone().allowlist_function("OH_LOG_.*")
})
}
fn generate_web(builder: &Builder) {
generate(
"web",
&[
"web/arkweb_error_code.h",
"web/arkweb_interface.h",
"web/arkweb_net_error_list.h",
"web/arkweb_scheme_handler.h",
"web/arkweb_type.h",
"web/native_interface_arkweb.h",
],
&["ohweb"],
|| {
builder
.clone()
.allowlist_type("ArkWeb_.*")
.allowlist_function("OH_ArkWeb_.*")
},
);
}
fn generate(
feature: &str,
headers: &[&str],
libs: &[&str],
factory: impl FnOnce() -> bindgen::Builder,
) {
let key = format!("CARGO_FEATURE_{}", feature.to_ascii_uppercase());
let name = format!("wrapper_{}.hpp", feature);
if env::var(&key).is_err() {
return;
}
for lib in libs {
println!("cargo:rustc-link-lib={}", lib);
}
println!("cargo:rerun-if-changed={}", name);
let content = headers
.iter()
.map(|h| format!("#include <{}>", h))
.collect::<Vec<_>>()
.join("\n");
let bindings = factory()
.header_contents(&name, &content)
.generate()
.unwrap_or_else(|_| panic!("Unable to generate bindings for {}", feature));
let out_path = PathBuf::from(env::var("OUT_DIR").unwrap_or_default());
bindings
.write_to_file(out_path.join(format!("{feature}_sys.rs")))
.unwrap_or_else(|_| panic!("Unable to write bindings for {}", feature));
}