Skip to content

Commit

Permalink
feat: use lockfiles to dedup recompilation
Browse files Browse the repository at this point in the history
  • Loading branch information
amaanq committed Feb 7, 2024
1 parent 4f3a3de commit beac5c6
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 1 deletion.
1 change: 1 addition & 0 deletions cli/loader/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ wasm = ["tree-sitter/wasm"]
anyhow = "1.0"
cc = "^1.0.58"
dirs = "3.0"
fs4 = "0.7.0"
libloading = "0.7"
once_cell = "1.7"
regex = "1"
Expand Down
43 changes: 42 additions & 1 deletion cli/loader/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#![doc = include_str!("../README.md")]

use anyhow::{anyhow, Context, Error, Result};
use fs4::FileExt;
use libloading::{Library, Symbol};
use once_cell::unsync::OnceCell;
use regex::{Regex, RegexBuilder};
Expand Down Expand Up @@ -371,9 +372,27 @@ impl Loader {
library_path.set_extension("wasm");
}

let recompile = needs_recompile(&library_path, &parser_path, scanner_path.as_deref())
let mut recompile = needs_recompile(&library_path, &parser_path, scanner_path.as_deref())
.with_context(|| "Failed to compare source and binary timestamps")?;

let lock_path = if env::var("CROSS_RUNNER").is_ok() {
PathBuf::from("/tmp")
.join("tree-sitter")
.join("lock")
.join(format!("{name}.lock"))
} else {
dirs::cache_dir()
.ok_or(anyhow!("Cannot determine cache directory"))?
.join("tree-sitter")
.join("lock")
.join(format!("{name}.lock"))
};

if let Ok(lock_file) = fs::OpenOptions::new().write(true).open(&lock_path) {
recompile = false;
lock_file.lock_exclusive()?;
}

#[cfg(feature = "wasm")]
if let Some(wasm_store) = self.wasm_store.lock().unwrap().as_mut() {
if recompile {
Expand All @@ -394,11 +413,26 @@ impl Loader {

{
if recompile {
fs::create_dir_all(lock_path.parent().unwrap()).with_context(|| {
format!(
"Failed to create directory {:?}",
lock_path.parent().unwrap()
)
})?;
let lock_file = fs::OpenOptions::new()
.create(true)
.truncate(true)
.write(true)
.open(&lock_path)?;
lock_file.lock_exclusive()?;

self.compile_parser_to_dylib(
header_paths,
&parser_path,
&scanner_path,
&library_path,
&lock_file,
&lock_path,
)?;
}

Expand All @@ -421,6 +455,8 @@ impl Loader {
parser_path: &Path,
scanner_path: &Option<PathBuf>,
library_path: &PathBuf,
lock_file: &fs::File,
lock_path: &Path,
) -> Result<(), Error> {
let mut config = cc::Build::new();
config
Expand Down Expand Up @@ -494,6 +530,10 @@ impl Loader {
let output = command
.output()
.with_context(|| "Failed to execute C compiler")?;

lock_file.unlock()?;
fs::remove_file(lock_path)?;

if !output.status.success() {
return Err(anyhow!(
"Parser compilation failed.\nStdout: {}\nStderr: {}",
Expand Down Expand Up @@ -687,6 +727,7 @@ impl Loader {

fs::rename(src_path.join(output_name), output_path)
.context("failed to rename wasm output file")?;

Ok(())
}

Expand Down

0 comments on commit beac5c6

Please sign in to comment.