context.rs 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. use anyhow::{Context, Result};
  2. use std::{
  3. env::var,
  4. fs::{create_dir_all, File},
  5. io::{BufWriter, Write},
  6. path::PathBuf,
  7. };
  8. use tauri_codegen::{context_codegen, ContextData};
  9. /// A builder for generating a Tauri application context during compile time.
  10. ///
  11. /// Meant to be used with [`tauri::include_codegen_context!`] inside your application code.
  12. ///
  13. /// [`tauri::include_codegen_context!`]: https://docs.rs/tauri/0.12/tauri/macro.include_codegen_context.html
  14. #[cfg_attr(doc_cfg, doc(cfg(feature = "codegen")))]
  15. #[derive(Debug)]
  16. pub struct CodegenContext {
  17. dev: bool,
  18. config_path: PathBuf,
  19. out_file: PathBuf,
  20. }
  21. impl Default for CodegenContext {
  22. fn default() -> Self {
  23. Self {
  24. dev: false,
  25. config_path: PathBuf::from("tauri.conf.json"),
  26. out_file: PathBuf::from("tauri-build-context.rs"),
  27. }
  28. }
  29. }
  30. impl CodegenContext {
  31. /// Create a new [`CodegenContext`] builder that is already filled with the default options.
  32. pub fn new() -> Self {
  33. Self::default()
  34. }
  35. /// Set the path to the `tauri.conf.json` (relative to the package's directory).
  36. ///
  37. /// This defaults to a file called `tauri.conf.json` inside of the current working directory of
  38. /// the package compiling; does not need to be set manually if that config file is in the same
  39. /// directory as your `Cargo.toml`.
  40. pub fn config_path(mut self, config_path: impl Into<PathBuf>) -> Self {
  41. self.config_path = config_path.into();
  42. self
  43. }
  44. /// Sets the output file's path.
  45. ///
  46. /// **Note:** This path should be relative to the `OUT_DIR`.
  47. ///
  48. /// Don't set this if you are using [`tauri::include_codegen_context!`] as that helper macro
  49. /// expects the default value. This option can be useful if you are not using the helper and
  50. /// instead using [`std::include!`] on the generated code yourself.
  51. ///
  52. /// Defaults to `tauri-build-context.rs`.
  53. ///
  54. /// [`tauri::include_codegen_context!`]: https://docs.rs/tauri/0.12/tauri/macro.include_codegen_context.html
  55. pub fn out_file(mut self, filename: PathBuf) -> Self {
  56. self.out_file = filename;
  57. self
  58. }
  59. /// Run the codegen in a `dev` context, meaning that Tauri is using a dev server or local file for development purposes,
  60. /// usually with the `tauri dev` CLI command.
  61. pub fn dev(mut self) -> Self {
  62. self.dev = true;
  63. self
  64. }
  65. /// Generate the code and write it to the output file - returning the path it was saved to.
  66. ///
  67. /// Unless you are doing something special with this builder, you don't need to do anything with
  68. /// the returned output path.
  69. ///
  70. /// # Panics
  71. ///
  72. /// If any parts of the codegen fail, this will panic with the related error message. This is
  73. /// typically desirable when running inside a build script; see [`Self::try_build`] for no panics.
  74. pub fn build(self) -> PathBuf {
  75. match self.try_build() {
  76. Ok(out) => out,
  77. Err(error) => panic!("Error found during Codegen::build: {}", error),
  78. }
  79. }
  80. /// Non-panicking [`Self::build`]
  81. pub fn try_build(self) -> Result<PathBuf> {
  82. let (config, config_parent) = tauri_codegen::get_config(&self.config_path)?;
  83. let code = context_codegen(ContextData {
  84. dev: self.dev,
  85. config,
  86. config_parent,
  87. // it's very hard to have a build script for unit tests, so assume this is always called from
  88. // outside the tauri crate, making the ::tauri root valid.
  89. context_path: quote::quote!(::tauri::Context),
  90. })?;
  91. // get the full output file path
  92. let out = var("OUT_DIR")
  93. .map(PathBuf::from)
  94. .map(|path| path.join(&self.out_file))
  95. .with_context(|| "unable to find OUT_DIR during tauri-build")?;
  96. // make sure any nested directories in OUT_DIR are created
  97. let parent = out.parent().with_context(|| {
  98. "`Codegen` could not find the parent to `out_file` while creating the file"
  99. })?;
  100. create_dir_all(parent)?;
  101. let mut file = File::create(&out).map(BufWriter::new).with_context(|| {
  102. format!(
  103. "Unable to create output file during tauri-build {}",
  104. out.display()
  105. )
  106. })?;
  107. writeln!(&mut file, "{}", code).with_context(|| {
  108. format!(
  109. "Unable to write tokenstream to out file during tauri-build {}",
  110. out.display()
  111. )
  112. })?;
  113. Ok(out)
  114. }
  115. }