mod.rs 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. // Copyright 2019-2023 Tauri Programme within The Commons Conservancy
  2. // SPDX-License-Identifier: Apache-2.0
  3. // SPDX-License-Identifier: MIT
  4. use std::path::{Path, PathBuf};
  5. use anyhow::Result;
  6. use tauri_utils::acl::{self, Error};
  7. pub mod mobile;
  8. use serde::de::DeserializeOwned;
  9. use std::{env::var, io::Cursor};
  10. pub fn plugin_config<T: DeserializeOwned>(name: &str) -> Option<T> {
  11. let config_env_var_name = format!(
  12. "TAURI_{}_PLUGIN_CONFIG",
  13. name.to_uppercase().replace('-', "_")
  14. );
  15. if let Ok(config_str) = var(&config_env_var_name) {
  16. println!("cargo:rerun-if-env-changed={config_env_var_name}");
  17. serde_json::from_reader(Cursor::new(config_str))
  18. .map(Some)
  19. .expect("failed to parse configuration")
  20. } else {
  21. None
  22. }
  23. }
  24. pub struct Builder<'a> {
  25. commands: &'a [&'static str],
  26. global_scope_schema: Option<schemars::schema::RootSchema>,
  27. android_path: Option<PathBuf>,
  28. ios_path: Option<PathBuf>,
  29. }
  30. impl<'a> Builder<'a> {
  31. pub fn new(commands: &'a [&'static str]) -> Self {
  32. Self {
  33. commands,
  34. global_scope_schema: None,
  35. android_path: None,
  36. ios_path: None,
  37. }
  38. }
  39. /// Sets the global scope JSON schema.
  40. pub fn global_scope_schema(mut self, schema: schemars::schema::RootSchema) -> Self {
  41. self.global_scope_schema.replace(schema);
  42. self
  43. }
  44. /// Sets the Android project path.
  45. pub fn android_path<P: Into<PathBuf>>(mut self, android_path: P) -> Self {
  46. self.android_path.replace(android_path.into());
  47. self
  48. }
  49. /// Sets the iOS project path.
  50. pub fn ios_path<P: Into<PathBuf>>(mut self, ios_path: P) -> Self {
  51. self.ios_path.replace(ios_path.into());
  52. self
  53. }
  54. /// [`Self::try_build`] but will exit automatically if an error is found.
  55. pub fn build(self) {
  56. if let Err(error) = self.try_build() {
  57. println!("{}: {error:#}", env!("CARGO_PKG_NAME"));
  58. std::process::exit(1);
  59. }
  60. }
  61. /// Ensure this crate is properly configured to be a Tauri plugin.
  62. ///
  63. /// # Errors
  64. ///
  65. /// Errors will occur if environmental variables expected to be set inside of [build scripts]
  66. /// are not found, or if the crate violates Tauri plugin conventions.
  67. pub fn try_build(self) -> Result<()> {
  68. // convention: plugin names should not use underscores
  69. let name = build_var("CARGO_PKG_NAME")?;
  70. if name.contains('_') {
  71. anyhow::bail!("plugin names cannot contain underscores");
  72. }
  73. let out_dir = PathBuf::from(build_var("OUT_DIR")?);
  74. // requirement: links MUST be set and MUST match the name
  75. let _links = build_var("CARGO_MANIFEST_LINKS")?;
  76. let autogenerated = Path::new("permissions").join(acl::build::AUTOGENERATED_FOLDER_NAME);
  77. let commands_dir = autogenerated.join("commands");
  78. std::fs::create_dir_all(&autogenerated).expect("unable to create permissions dir");
  79. if !self.commands.is_empty() {
  80. acl::build::autogenerate_command_permissions(&commands_dir, self.commands, "");
  81. }
  82. println!("cargo:rerun-if-changed=permissions");
  83. let permissions = acl::build::define_permissions("./permissions/**/*.*", &name, &out_dir)?;
  84. if permissions.is_empty() {
  85. let _ = std::fs::remove_file(format!(
  86. "./permissions/{}/{}",
  87. acl::build::PERMISSION_SCHEMAS_FOLDER_NAME,
  88. acl::build::PERMISSION_SCHEMA_FILE_NAME
  89. ));
  90. let _ = std::fs::remove_file(autogenerated.join(acl::build::PERMISSION_DOCS_FILE_NAME));
  91. } else {
  92. acl::build::generate_schema(&permissions, "./permissions")?;
  93. acl::build::generate_docs(&permissions, &autogenerated)?;
  94. }
  95. if let Some(global_scope_schema) = self.global_scope_schema {
  96. acl::build::define_global_scope_schema(global_scope_schema, &name, &out_dir)?;
  97. }
  98. mobile::setup(self.android_path, self.ios_path)?;
  99. Ok(())
  100. }
  101. }
  102. fn cfg_alias(alias: &str, has_feature: bool) {
  103. if has_feature {
  104. println!("cargo:rustc-cfg={alias}");
  105. }
  106. }
  107. /// Grab an env var that is expected to be set inside of build scripts.
  108. fn build_var(key: &'static str) -> Result<String, Error> {
  109. std::env::var(key).map_err(|_| Error::BuildVar(key))
  110. }