diff --git a/crates/typst-cli/src/args.rs b/crates/typst-cli/src/args.rs index 7459be0f2..0192908bc 100644 --- a/crates/typst-cli/src/args.rs +++ b/crates/typst-cli/src/args.rs @@ -267,6 +267,10 @@ pub struct CompileArgs { #[clap(long = "make-deps", value_name = "PATH")] pub make_deps: Option, + /// File path to which a list of NUL-separated current compilation's dependencies will be written + #[clap(long, value_name = "PATH")] + pub deps0: Option, + /// Processing arguments. #[clap(flatten)] pub process: ProcessArgs, diff --git a/crates/typst-cli/src/compile.rs b/crates/typst-cli/src/compile.rs index 0db67b454..c4fa1362e 100644 --- a/crates/typst-cli/src/compile.rs +++ b/crates/typst-cli/src/compile.rs @@ -67,6 +67,8 @@ pub struct CompileConfig { pub pdf_standards: PdfStandards, /// A path to write a Makefile rule describing the current compilation. pub make_deps: Option, + /// A path to write a list of NUL-separated dependencies. + pub deps0: Option, /// The PPI (pixels per inch) to use for PNG export. pub ppi: f32, /// The export cache for images, used for caching output files in `typst @@ -152,6 +154,7 @@ impl CompileConfig { pdf_standards, creation_timestamp: args.world.creation_timestamp, make_deps: args.make_deps.clone(), + deps0: args.deps0.clone(), ppi: args.ppi, diagnostic_format: args.process.diagnostic_format, open: args.open.clone(), @@ -210,6 +213,8 @@ pub fn compile_once( } } + write_deps0(world, config)?; + Ok(()) } @@ -600,6 +605,38 @@ fn write_make_deps( }) } +fn write_deps0(world: &mut SystemWorld, config: &CompileConfig) -> StrResult<()> { + let Some(ref deps_path) = config.deps0 else { return Ok(()) }; + fn write( + deps_path: &Path, + root: PathBuf, + dependencies: impl Iterator, + ) -> io::Result<()> { + let mut file = File::create(deps_path)?; + let current_dir = std::env::current_dir()?; + let relative_root = diff_paths(&root, ¤t_dir).unwrap_or(root.clone()); + + dependencies + .into_iter() + .map(|dependency| { + dependency + .strip_prefix(&root) + .map_or_else(|_| dependency.clone(), |x| relative_root.join(x)) + .into_os_string() + .into_encoded_bytes() + .into_boxed_slice() + }) + .try_for_each(|ref dep| { + file.write_all(dep)?; + file.write_all(b"\0")?; + Ok(()) + }) + } + write(deps_path, world.root().to_owned(), world.dependencies()).map_err(|err| { + eco_format!("failed to create dependencies file due to IO error ({err})") + }) +} + /// Opens the output if desired. fn open_output(config: &mut CompileConfig) -> StrResult<()> { let Some(viewer) = config.open.take() else { return Ok(()) };