Skip to content

Commit 6d337e0

Browse files
committed
Keep track of compiler info during build
1 parent 34cb6b8 commit 6d337e0

File tree

7 files changed

+231
-24
lines changed

7 files changed

+231
-24
lines changed

rewatch/src/build.rs

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
pub mod build_types;
22
pub mod clean;
33
pub mod compile;
4+
pub mod compiler_info;
45
pub mod deps;
56
pub mod logs;
67
pub mod namespaces;
@@ -10,6 +11,7 @@ pub mod read_compile_state;
1011

1112
use self::parse::parser_args;
1213
use crate::build::compile::{mark_modules_with_deleted_deps_dirty, mark_modules_with_expired_deps_dirty};
14+
use crate::build::compiler_info::{CompilerCheckResult, verify_compiler_info, write_compiler_info};
1315
use crate::helpers::emojis::*;
1416
use crate::helpers::{self};
1517
use crate::project_context::ProjectContext;
@@ -109,6 +111,20 @@ pub fn get_compiler_args(rescript_file_path: &Path) -> Result<String> {
109111
Ok(result)
110112
}
111113

114+
pub fn get_compiler_info(project_context: &ProjectContext) -> Result<CompilerInfo> {
115+
let bsc_path = helpers::get_bsc();
116+
let bsc_hash = helpers::compute_file_hash(&bsc_path).ok_or(anyhow!(
117+
"Failed to compute bsc hash for {}",
118+
bsc_path.to_string_lossy()
119+
))?;
120+
let runtime_path = compile::get_runtime_path(&project_context.current_config, project_context)?;
121+
Ok(CompilerInfo {
122+
bsc_path,
123+
bsc_hash,
124+
runtime_path,
125+
})
126+
}
127+
112128
pub fn initialize_build(
113129
default_timing: Option<Duration>,
114130
filter: &Option<regex::Regex>,
@@ -117,8 +133,8 @@ pub fn initialize_build(
117133
build_dev_deps: bool,
118134
snapshot_output: bool,
119135
) -> Result<BuildState> {
120-
let bsc_path = helpers::get_bsc();
121136
let project_context = ProjectContext::new(path)?;
137+
let compiler = get_compiler_info(&project_context)?;
122138

123139
if !snapshot_output && show_progress {
124140
print!("{} {}Building package tree...", style("[1/7]").bold().dim(), TREE);
@@ -129,6 +145,8 @@ pub fn initialize_build(
129145
let packages = packages::make(filter, &project_context, show_progress, build_dev_deps)?;
130146
let timing_package_tree_elapsed = timing_package_tree.elapsed();
131147

148+
let compiler_check = verify_compiler_info(&packages, &compiler);
149+
132150
if !snapshot_output && show_progress {
133151
println!(
134152
"{}{} {}Built package tree in {:.2}s",
@@ -139,6 +157,14 @@ pub fn initialize_build(
139157
.unwrap_or(timing_package_tree_elapsed)
140158
.as_secs_f64()
141159
);
160+
if let CompilerCheckResult::CleanedPackagesDueToCompiler = compiler_check {
161+
println!(
162+
"{}{} {}Cleaned previous build due to compiler update",
163+
LINE_CLEAR,
164+
style("[1/7]").bold().dim(),
165+
SWEEP
166+
);
167+
}
142168
}
143169

144170
if !packages::validate_packages_dependencies(&packages) {
@@ -156,7 +182,7 @@ pub fn initialize_build(
156182
let _ = stdout().flush();
157183
}
158184

159-
let mut build_state = BuildState::new(project_context, packages, bsc_path);
185+
let mut build_state = BuildState::new(project_context, packages, compiler);
160186
packages::parse_packages(&mut build_state);
161187
let timing_source_files_elapsed = timing_source_files.elapsed();
162188

@@ -448,6 +474,9 @@ pub fn incremental_build(
448474
log_deprecations(build_state);
449475
}
450476

477+
// Write per-package compiler metadata to `lib/bs/compiler-info.json` (idempotent)
478+
write_compiler_info(build_state);
479+
451480
Ok(())
452481
}
453482
}

rewatch/src/build/build_types.rs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use crate::build::packages::{Namespace, Package};
22
use crate::config::Config;
33
use crate::project_context::ProjectContext;
44
use ahash::{AHashMap, AHashSet};
5+
use blake3::Hash;
56
use std::{fmt::Display, path::PathBuf, time::SystemTime};
67

78
#[derive(Debug, Clone, PartialEq)]
@@ -96,10 +97,17 @@ pub struct BuildState {
9697
pub packages: AHashMap<String, Package>,
9798
pub module_names: AHashSet<String>,
9899
pub deleted_modules: AHashSet<String>,
99-
pub bsc_path: PathBuf,
100+
pub compiler_info: CompilerInfo,
100101
pub deps_initialized: bool,
101102
}
102103

104+
#[derive(Debug, Clone)]
105+
pub struct CompilerInfo {
106+
pub bsc_path: PathBuf,
107+
pub bsc_hash: Hash,
108+
pub runtime_path: PathBuf,
109+
}
110+
103111
impl BuildState {
104112
pub fn get_package(&self, package_name: &str) -> Option<&Package> {
105113
self.packages.get(package_name)
@@ -111,15 +119,15 @@ impl BuildState {
111119
pub fn new(
112120
project_context: ProjectContext,
113121
packages: AHashMap<String, Package>,
114-
bsc_path: PathBuf,
122+
compiler: CompilerInfo,
115123
) -> Self {
116124
Self {
117125
project_context,
118126
module_names: AHashSet::new(),
119127
modules: AHashMap::new(),
120128
packages,
121129
deleted_modules: AHashSet::new(),
122-
bsc_path,
130+
compiler_info: compiler,
123131
deps_initialized: false,
124132
}
125133
}

rewatch/src/build/clean.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use super::build_types::*;
22
use super::packages;
3+
use crate::build;
34
use crate::build::packages::Package;
45
use crate::config::Config;
56
use crate::helpers;
@@ -332,9 +333,8 @@ pub fn cleanup_after_build(build_state: &BuildState) {
332333

333334
pub fn clean(path: &Path, show_progress: bool, snapshot_output: bool, clean_dev_deps: bool) -> Result<()> {
334335
let project_context = ProjectContext::new(path)?;
335-
336+
let compiler_info = build::get_compiler_info(&project_context)?;
336337
let packages = packages::make(&None, &project_context, show_progress, clean_dev_deps)?;
337-
let bsc_path = helpers::get_bsc();
338338

339339
let timing_clean_compiler_assets = Instant::now();
340340
if !snapshot_output && show_progress {
@@ -364,7 +364,7 @@ pub fn clean(path: &Path, show_progress: bool, snapshot_output: bool, clean_dev_
364364
}
365365

366366
let timing_clean_mjs = Instant::now();
367-
let mut build_state = BuildState::new(project_context, packages, bsc_path);
367+
let mut build_state = BuildState::new(project_context, packages, compiler_info);
368368
packages::parse_packages(&mut build_state);
369369
let root_config = build_state.get_root_config();
370370
let suffix_for_print = if snapshot_output || !show_progress {
@@ -418,7 +418,7 @@ pub fn clean(path: &Path, show_progress: bool, snapshot_output: bool, clean_dev_
418418
Ok(())
419419
}
420420

421-
fn clean_package(show_progress: bool, snapshot_output: bool, package: &Package) {
421+
pub fn clean_package(show_progress: bool, snapshot_output: bool, package: &Package) {
422422
if show_progress {
423423
if snapshot_output {
424424
println!("Cleaning {}", package.name)
@@ -441,4 +441,7 @@ fn clean_package(show_progress: bool, snapshot_output: bool, package: &Package)
441441
let path_str = package.get_ocaml_build_path();
442442
let path = std::path::Path::new(&path_str);
443443
let _ = std::fs::remove_dir_all(path);
444+
445+
// remove the per-package compiler metadata file so that a subsequent build writes fresh metadata
446+
let _ = std::fs::remove_file(package.get_compiler_info_path());
444447
}

rewatch/src/build/compile.rs

Lines changed: 32 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@ use console::style;
1616
use log::{debug, trace};
1717
use rayon::prelude::*;
1818
use std::path::Path;
19+
use std::path::PathBuf;
1920
use std::process::Command;
21+
use std::sync::OnceLock;
2022
use std::time::SystemTime;
2123

2224
pub fn compile(
@@ -336,22 +338,36 @@ pub fn compile(
336338
Ok((compile_errors, compile_warnings, num_compiled_modules))
337339
}
338340

339-
pub fn get_runtime_path_args(
340-
package_config: &Config,
341-
project_context: &ProjectContext,
342-
) -> Result<Vec<String>> {
343-
match std::env::var("RESCRIPT_RUNTIME") {
344-
Ok(runtime_path) => Ok(vec!["-runtime-path".to_string(), runtime_path]),
341+
static RUNTIME_PATH_MEMO: OnceLock<PathBuf> = OnceLock::new();
342+
343+
pub fn get_runtime_path(package_config: &Config, project_context: &ProjectContext) -> Result<PathBuf> {
344+
if let Some(p) = RUNTIME_PATH_MEMO.get() {
345+
return Ok(p.clone());
346+
}
347+
348+
let resolved = match std::env::var("RESCRIPT_RUNTIME") {
349+
Ok(runtime_path) => Ok(PathBuf::from(runtime_path)),
345350
Err(_) => match helpers::try_package_path(package_config, project_context, "@rescript/runtime") {
346-
Ok(runtime_path) => Ok(vec![
347-
"-runtime-path".to_string(),
348-
runtime_path.to_string_lossy().to_string(),
349-
]),
351+
Ok(runtime_path) => Ok(runtime_path),
350352
Err(err) => Err(anyhow!(
351353
"The rescript runtime package could not be found.\nPlease set RESCRIPT_RUNTIME environment variable or make sure the runtime package is installed.\nError: {err}"
352354
)),
353355
},
354-
}
356+
}?;
357+
358+
let _ = RUNTIME_PATH_MEMO.set(resolved.clone());
359+
Ok(resolved)
360+
}
361+
362+
pub fn get_runtime_path_args(
363+
package_config: &Config,
364+
project_context: &ProjectContext,
365+
) -> Result<Vec<String>> {
366+
let runtime_path = get_runtime_path(package_config, project_context)?;
367+
Ok(vec![
368+
"-runtime-path".to_string(),
369+
runtime_path.to_string_lossy().to_string(),
370+
])
355371
}
356372

357373
pub fn compiler_args(
@@ -581,7 +597,7 @@ fn compile_file(
581597
let BuildState {
582598
packages,
583599
project_context,
584-
bsc_path,
600+
compiler_info,
585601
..
586602
} = build_state;
587603
let root_config = build_state.get_root_config();
@@ -612,7 +628,7 @@ fn compile_file(
612628
package.is_local_dep,
613629
)?;
614630

615-
let to_mjs = Command::new(bsc_path)
631+
let to_mjs = Command::new(&compiler_info.bsc_path)
616632
.current_dir(
617633
build_path_abs
618634
.canonicalize()
@@ -748,6 +764,9 @@ fn compile_file(
748764
}
749765
});
750766

767+
// TODO: Optionally record per-module successful compile timestamps if needed
768+
// for future metadata-based invalidation. Current metadata is per-package.
769+
751770
if helpers::contains_ascii_characters(&err) {
752771
if package.is_local_dep {
753772
// suppress warnings of external deps

0 commit comments

Comments
 (0)