use anyhow::{Context, Result};
use std::{
env::var,
fs::{create_dir_all, File},
io::{BufWriter, Write},
path::{Path, PathBuf},
};
use tauri_codegen::{context_codegen, ContextData};
use tauri_utils::config::FrontendDist;
#[cfg_attr(docsrs, doc(cfg(feature = "codegen")))]
#[derive(Debug)]
pub struct CodegenContext {
config_path: PathBuf,
out_file: PathBuf,
capabilities: Option<Vec<PathBuf>>,
}
impl Default for CodegenContext {
fn default() -> Self {
Self {
config_path: PathBuf::from("tauri.conf.json"),
out_file: PathBuf::from("tauri-build-context.rs"),
capabilities: None,
}
}
}
impl CodegenContext {
pub fn new() -> Self {
Self::default()
}
#[must_use]
pub fn config_path(mut self, config_path: impl Into<PathBuf>) -> Self {
self.config_path = config_path.into();
self
}
#[must_use]
pub fn out_file(mut self, filename: PathBuf) -> Self {
self.out_file = filename;
self
}
#[must_use]
pub fn capability<P: AsRef<Path>>(mut self, path: P) -> Self {
self
.capabilities
.get_or_insert_with(Default::default)
.push(path.as_ref().to_path_buf());
self
}
pub(crate) fn try_build(self) -> Result<PathBuf> {
let (config, config_parent) = tauri_codegen::get_config(&self.config_path)?;
match &config.build.frontend_dist {
Some(FrontendDist::Directory(p)) => {
let dist_path = config_parent.join(p);
if dist_path.exists() {
println!("cargo:rerun-if-changed={}", dist_path.display());
}
}
Some(FrontendDist::Files(files)) => {
for path in files {
println!(
"cargo:rerun-if-changed={}",
config_parent.join(path).display()
);
}
}
_ => (),
}
for icon in &config.bundle.icon {
println!(
"cargo:rerun-if-changed={}",
config_parent.join(icon).display()
);
}
if let Some(tray_icon) = config.app.tray_icon.as_ref().map(|t| &t.icon_path) {
println!(
"cargo:rerun-if-changed={}",
config_parent.join(tray_icon).display()
);
}
#[cfg(target_os = "macos")]
{
let info_plist_path = config_parent.join("Info.plist");
if info_plist_path.exists() {
println!("cargo:rerun-if-changed={}", info_plist_path.display());
}
if let Some(plist_path) = &config.bundle.macos.info_plist {
let info_plist_path = config_parent.join(plist_path);
if info_plist_path.exists() {
println!("cargo:rerun-if-changed={}", info_plist_path.display());
}
}
}
let code = context_codegen(ContextData {
dev: crate::is_dev(),
config,
config_parent,
root: quote::quote!(::tauri),
capabilities: self.capabilities,
assets: None,
test: false,
})?;
let out = var("OUT_DIR")
.map(PathBuf::from)
.map(|path| path.join(&self.out_file))
.with_context(|| "unable to find OUT_DIR during tauri-build")?;
let parent = out.parent().with_context(|| {
"`Codegen` could not find the parent to `out_file` while creating the file"
})?;
create_dir_all(parent)?;
let mut file = File::create(&out).map(BufWriter::new).with_context(|| {
format!(
"Unable to create output file during tauri-build {}",
out.display()
)
})?;
writeln!(file, "{code}").with_context(|| {
format!(
"Unable to write tokenstream to out file during tauri-build {}",
out.display()
)
})?;
Ok(out)
}
}