tauri_plugin/build/
mod.rsuse std::path::{Path, PathBuf};
use anyhow::Result;
use tauri_utils::acl::{self, Error};
pub mod mobile;
use serde::de::DeserializeOwned;
use std::{env, io::Cursor};
const RESERVED_PLUGIN_NAMES: &[&str] = &["core", "tauri"];
pub fn plugin_config<T: DeserializeOwned>(name: &str) -> Option<T> {
let config_env_var_name = format!(
"TAURI_{}_PLUGIN_CONFIG",
name.to_uppercase().replace('-', "_")
);
if let Ok(config_str) = env::var(&config_env_var_name) {
println!("cargo:rerun-if-env-changed={config_env_var_name}");
serde_json::from_reader(Cursor::new(config_str))
.map(Some)
.expect("failed to parse configuration")
} else {
None
}
}
pub struct Builder<'a> {
commands: &'a [&'static str],
global_scope_schema: Option<schemars::schema::RootSchema>,
global_api_script_path: Option<PathBuf>,
android_path: Option<PathBuf>,
ios_path: Option<PathBuf>,
}
impl<'a> Builder<'a> {
pub fn new(commands: &'a [&'static str]) -> Self {
Self {
commands,
global_scope_schema: None,
global_api_script_path: None,
android_path: None,
ios_path: None,
}
}
pub fn global_scope_schema(mut self, schema: schemars::schema::RootSchema) -> Self {
self.global_scope_schema.replace(schema);
self
}
pub fn global_api_script_path<P: Into<PathBuf>>(mut self, path: P) -> Self {
self.global_api_script_path.replace(path.into());
self
}
pub fn android_path<P: Into<PathBuf>>(mut self, android_path: P) -> Self {
self.android_path.replace(android_path.into());
self
}
pub fn ios_path<P: Into<PathBuf>>(mut self, ios_path: P) -> Self {
self.ios_path.replace(ios_path.into());
self
}
pub fn build(self) {
if let Err(error) = self.try_build() {
println!("{}: {error:#}", env!("CARGO_PKG_NAME"));
std::process::exit(1);
}
}
pub fn try_build(self) -> Result<()> {
let name = build_var("CARGO_PKG_NAME")?;
if name.contains('_') {
anyhow::bail!("plugin names cannot contain underscores");
}
if RESERVED_PLUGIN_NAMES.contains(&name.as_str()) {
anyhow::bail!("plugin name `{name}` is reserved");
}
let out_dir = PathBuf::from(build_var("OUT_DIR")?);
let _links = std::env::var("CARGO_MANIFEST_LINKS").map_err(|_| Error::LinksMissing)?;
let autogenerated = Path::new("permissions").join(acl::build::AUTOGENERATED_FOLDER_NAME);
std::fs::create_dir_all(&autogenerated).expect("unable to create permissions dir");
let commands_dir = autogenerated.join("commands");
if !self.commands.is_empty() {
acl::build::autogenerate_command_permissions(&commands_dir, self.commands, "", true);
}
println!("cargo:rerun-if-changed=permissions");
let permissions =
acl::build::define_permissions("./permissions/**/*.*", &name, &out_dir, |_| true)?;
if permissions.is_empty() {
let _ = std::fs::remove_file(format!(
"./permissions/{}/{}",
acl::PERMISSION_SCHEMAS_FOLDER_NAME,
acl::PERMISSION_SCHEMA_FILE_NAME
));
let _ = std::fs::remove_file(autogenerated.join(acl::build::PERMISSION_DOCS_FILE_NAME));
} else {
acl::schema::generate_permissions_schema(&permissions, "./permissions")?;
acl::build::generate_docs(
&permissions,
&autogenerated,
name.strip_prefix("tauri-plugin-").unwrap_or(&name),
)?;
}
if let Some(global_scope_schema) = self.global_scope_schema {
acl::build::define_global_scope_schema(global_scope_schema, &name, &out_dir)?;
}
if let Some(path) = self.global_api_script_path {
tauri_utils::plugin::define_global_api_script_path(path);
}
mobile::setup(self.android_path, self.ios_path)?;
Ok(())
}
}
fn cfg_alias(alias: &str, has_feature: bool) {
println!("cargo:rustc-check-cfg=cfg({alias})");
if has_feature {
println!("cargo:rustc-cfg={alias}");
}
}
fn build_var(key: &'static str) -> Result<String, Error> {
std::env::var(key).map_err(|_| Error::BuildVar(key))
}