mirror of
https://github.com/typst/typst
synced 2025-05-14 04:56:26 +08:00
--make-deps fixes (#5873)
This commit is contained in:
parent
de16a2ced1
commit
0a534f2c0e
@ -6,8 +6,9 @@ use std::path::{Path, PathBuf};
|
|||||||
use chrono::{DateTime, Datelike, Timelike, Utc};
|
use chrono::{DateTime, Datelike, Timelike, Utc};
|
||||||
use codespan_reporting::diagnostic::{Diagnostic, Label};
|
use codespan_reporting::diagnostic::{Diagnostic, Label};
|
||||||
use codespan_reporting::term;
|
use codespan_reporting::term;
|
||||||
use ecow::{eco_format, EcoString};
|
use ecow::eco_format;
|
||||||
use parking_lot::RwLock;
|
use parking_lot::RwLock;
|
||||||
|
use pathdiff::diff_paths;
|
||||||
use rayon::iter::{IntoParallelRefIterator, ParallelIterator};
|
use rayon::iter::{IntoParallelRefIterator, ParallelIterator};
|
||||||
use typst::diag::{
|
use typst::diag::{
|
||||||
bail, At, Severity, SourceDiagnostic, SourceResult, StrResult, Warned,
|
bail, At, Severity, SourceDiagnostic, SourceResult, StrResult, Warned,
|
||||||
@ -188,7 +189,7 @@ pub fn compile_once(
|
|||||||
|
|
||||||
match output {
|
match output {
|
||||||
// Export the PDF / PNG.
|
// Export the PDF / PNG.
|
||||||
Ok(()) => {
|
Ok(outputs) => {
|
||||||
let duration = start.elapsed();
|
let duration = start.elapsed();
|
||||||
|
|
||||||
if config.watching {
|
if config.watching {
|
||||||
@ -202,7 +203,7 @@ pub fn compile_once(
|
|||||||
print_diagnostics(world, &[], &warnings, config.diagnostic_format)
|
print_diagnostics(world, &[], &warnings, config.diagnostic_format)
|
||||||
.map_err(|err| eco_format!("failed to print diagnostics ({err})"))?;
|
.map_err(|err| eco_format!("failed to print diagnostics ({err})"))?;
|
||||||
|
|
||||||
write_make_deps(world, config)?;
|
write_make_deps(world, config, outputs)?;
|
||||||
open_output(config)?;
|
open_output(config)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -226,12 +227,15 @@ pub fn compile_once(
|
|||||||
fn compile_and_export(
|
fn compile_and_export(
|
||||||
world: &mut SystemWorld,
|
world: &mut SystemWorld,
|
||||||
config: &mut CompileConfig,
|
config: &mut CompileConfig,
|
||||||
) -> Warned<SourceResult<()>> {
|
) -> Warned<SourceResult<Vec<Output>>> {
|
||||||
match config.output_format {
|
match config.output_format {
|
||||||
OutputFormat::Html => {
|
OutputFormat::Html => {
|
||||||
let Warned { output, warnings } = typst::compile::<HtmlDocument>(world);
|
let Warned { output, warnings } = typst::compile::<HtmlDocument>(world);
|
||||||
let result = output.and_then(|document| export_html(&document, config));
|
let result = output.and_then(|document| export_html(&document, config));
|
||||||
Warned { output: result, warnings }
|
Warned {
|
||||||
|
output: result.map(|()| vec![config.output.clone()]),
|
||||||
|
warnings,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
let Warned { output, warnings } = typst::compile::<PagedDocument>(world);
|
let Warned { output, warnings } = typst::compile::<PagedDocument>(world);
|
||||||
@ -257,9 +261,14 @@ fn export_html(document: &HtmlDocument, config: &CompileConfig) -> SourceResult<
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Export to a paged target format.
|
/// Export to a paged target format.
|
||||||
fn export_paged(document: &PagedDocument, config: &CompileConfig) -> SourceResult<()> {
|
fn export_paged(
|
||||||
|
document: &PagedDocument,
|
||||||
|
config: &CompileConfig,
|
||||||
|
) -> SourceResult<Vec<Output>> {
|
||||||
match config.output_format {
|
match config.output_format {
|
||||||
OutputFormat::Pdf => export_pdf(document, config),
|
OutputFormat::Pdf => {
|
||||||
|
export_pdf(document, config).map(|()| vec![config.output.clone()])
|
||||||
|
}
|
||||||
OutputFormat::Png => {
|
OutputFormat::Png => {
|
||||||
export_image(document, config, ImageExportFormat::Png).at(Span::detached())
|
export_image(document, config, ImageExportFormat::Png).at(Span::detached())
|
||||||
}
|
}
|
||||||
@ -327,7 +336,7 @@ fn export_image(
|
|||||||
document: &PagedDocument,
|
document: &PagedDocument,
|
||||||
config: &CompileConfig,
|
config: &CompileConfig,
|
||||||
fmt: ImageExportFormat,
|
fmt: ImageExportFormat,
|
||||||
) -> StrResult<()> {
|
) -> StrResult<Vec<Output>> {
|
||||||
// Determine whether we have indexable templates in output
|
// Determine whether we have indexable templates in output
|
||||||
let can_handle_multiple = match config.output {
|
let can_handle_multiple = match config.output {
|
||||||
Output::Stdout => false,
|
Output::Stdout => false,
|
||||||
@ -383,7 +392,7 @@ fn export_image(
|
|||||||
&& config.export_cache.is_cached(*i, &page.frame)
|
&& config.export_cache.is_cached(*i, &page.frame)
|
||||||
&& path.exists()
|
&& path.exists()
|
||||||
{
|
{
|
||||||
return Ok(());
|
return Ok(Output::Path(path.to_path_buf()));
|
||||||
}
|
}
|
||||||
|
|
||||||
Output::Path(path.to_owned())
|
Output::Path(path.to_owned())
|
||||||
@ -392,11 +401,9 @@ fn export_image(
|
|||||||
};
|
};
|
||||||
|
|
||||||
export_image_page(config, page, &output, fmt)?;
|
export_image_page(config, page, &output, fmt)?;
|
||||||
Ok(())
|
Ok(output)
|
||||||
})
|
})
|
||||||
.collect::<Result<Vec<()>, EcoString>>()?;
|
.collect::<StrResult<Vec<Output>>>()
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mod output_template {
|
mod output_template {
|
||||||
@ -501,14 +508,25 @@ impl ExportCache {
|
|||||||
/// Writes a Makefile rule describing the relationship between the output and
|
/// Writes a Makefile rule describing the relationship between the output and
|
||||||
/// its dependencies to the path specified by the --make-deps argument, if it
|
/// its dependencies to the path specified by the --make-deps argument, if it
|
||||||
/// was provided.
|
/// was provided.
|
||||||
fn write_make_deps(world: &mut SystemWorld, config: &CompileConfig) -> StrResult<()> {
|
fn write_make_deps(
|
||||||
|
world: &mut SystemWorld,
|
||||||
|
config: &CompileConfig,
|
||||||
|
outputs: Vec<Output>,
|
||||||
|
) -> StrResult<()> {
|
||||||
let Some(ref make_deps_path) = config.make_deps else { return Ok(()) };
|
let Some(ref make_deps_path) = config.make_deps else { return Ok(()) };
|
||||||
let Output::Path(output_path) = &config.output else {
|
let Ok(output_paths) = outputs
|
||||||
bail!("failed to create make dependencies file because output was stdout")
|
.into_iter()
|
||||||
};
|
.filter_map(|o| match o {
|
||||||
let Some(output_path) = output_path.as_os_str().to_str() else {
|
Output::Path(path) => Some(path.into_os_string().into_string()),
|
||||||
|
Output::Stdout => None,
|
||||||
|
})
|
||||||
|
.collect::<Result<Vec<_>, _>>()
|
||||||
|
else {
|
||||||
bail!("failed to create make dependencies file because output path was not valid unicode")
|
bail!("failed to create make dependencies file because output path was not valid unicode")
|
||||||
};
|
};
|
||||||
|
if output_paths.is_empty() {
|
||||||
|
bail!("failed to create make dependencies file because output was stdout")
|
||||||
|
}
|
||||||
|
|
||||||
// Based on `munge` in libcpp/mkdeps.cc from the GCC source code. This isn't
|
// Based on `munge` in libcpp/mkdeps.cc from the GCC source code. This isn't
|
||||||
// perfect as some special characters can't be escaped.
|
// perfect as some special characters can't be escaped.
|
||||||
@ -522,6 +540,10 @@ fn write_make_deps(world: &mut SystemWorld, config: &CompileConfig) -> StrResult
|
|||||||
res.push('$');
|
res.push('$');
|
||||||
slashes = 0;
|
slashes = 0;
|
||||||
}
|
}
|
||||||
|
':' => {
|
||||||
|
res.push('\\');
|
||||||
|
slashes = 0;
|
||||||
|
}
|
||||||
' ' | '\t' => {
|
' ' | '\t' => {
|
||||||
// `munge`'s source contains a comment here that says: "A
|
// `munge`'s source contains a comment here that says: "A
|
||||||
// space or tab preceded by 2N+1 backslashes represents N
|
// space or tab preceded by 2N+1 backslashes represents N
|
||||||
@ -544,18 +566,29 @@ fn write_make_deps(world: &mut SystemWorld, config: &CompileConfig) -> StrResult
|
|||||||
|
|
||||||
fn write(
|
fn write(
|
||||||
make_deps_path: &Path,
|
make_deps_path: &Path,
|
||||||
output_path: &str,
|
output_paths: Vec<String>,
|
||||||
root: PathBuf,
|
root: PathBuf,
|
||||||
dependencies: impl Iterator<Item = PathBuf>,
|
dependencies: impl Iterator<Item = PathBuf>,
|
||||||
) -> io::Result<()> {
|
) -> io::Result<()> {
|
||||||
let mut file = File::create(make_deps_path)?;
|
let mut file = File::create(make_deps_path)?;
|
||||||
|
let current_dir = std::env::current_dir()?;
|
||||||
|
let relative_root = diff_paths(&root, ¤t_dir).unwrap_or(root.clone());
|
||||||
|
|
||||||
file.write_all(munge(output_path).as_bytes())?;
|
for (i, output_path) in output_paths.into_iter().enumerate() {
|
||||||
|
if i != 0 {
|
||||||
|
file.write_all(b" ")?;
|
||||||
|
}
|
||||||
|
file.write_all(munge(&output_path).as_bytes())?;
|
||||||
|
}
|
||||||
file.write_all(b":")?;
|
file.write_all(b":")?;
|
||||||
for dependency in dependencies {
|
for dependency in dependencies {
|
||||||
let Some(dependency) =
|
let relative_dependency = match dependency.strip_prefix(&root) {
|
||||||
dependency.strip_prefix(&root).unwrap_or(&dependency).to_str()
|
Ok(root_relative_dependency) => {
|
||||||
else {
|
relative_root.join(root_relative_dependency)
|
||||||
|
}
|
||||||
|
Err(_) => dependency,
|
||||||
|
};
|
||||||
|
let Some(relative_dependency) = relative_dependency.to_str() else {
|
||||||
// Silently skip paths that aren't valid unicode so we still
|
// Silently skip paths that aren't valid unicode so we still
|
||||||
// produce a rule that will work for the other paths that can be
|
// produce a rule that will work for the other paths that can be
|
||||||
// processed.
|
// processed.
|
||||||
@ -563,14 +596,14 @@ fn write_make_deps(world: &mut SystemWorld, config: &CompileConfig) -> StrResult
|
|||||||
};
|
};
|
||||||
|
|
||||||
file.write_all(b" ")?;
|
file.write_all(b" ")?;
|
||||||
file.write_all(munge(dependency).as_bytes())?;
|
file.write_all(munge(relative_dependency).as_bytes())?;
|
||||||
}
|
}
|
||||||
file.write_all(b"\n")?;
|
file.write_all(b"\n")?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
write(make_deps_path, output_path, world.root().to_owned(), world.dependencies())
|
write(make_deps_path, output_paths, world.root().to_owned(), world.dependencies())
|
||||||
.map_err(|err| {
|
.map_err(|err| {
|
||||||
eco_format!("failed to create make dependencies file due to IO error ({err})")
|
eco_format!("failed to create make dependencies file due to IO error ({err})")
|
||||||
})
|
})
|
||||||
|
Loading…
x
Reference in New Issue
Block a user