Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 31 additions & 2 deletions rewatch/src/build.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
pub mod build_types;
pub mod clean;
pub mod compile;
pub mod compiler_info;
pub mod deps;
pub mod logs;
pub mod namespaces;
Expand All @@ -10,6 +11,7 @@ pub mod read_compile_state;

use self::parse::parser_args;
use crate::build::compile::{mark_modules_with_deleted_deps_dirty, mark_modules_with_expired_deps_dirty};
use crate::build::compiler_info::{CompilerCheckResult, verify_compiler_info, write_compiler_info};
use crate::helpers::emojis::*;
use crate::helpers::{self};
use crate::project_context::ProjectContext;
Expand Down Expand Up @@ -109,6 +111,20 @@ pub fn get_compiler_args(rescript_file_path: &Path) -> Result<String> {
Ok(result)
}

pub fn get_compiler_info(project_context: &ProjectContext) -> Result<CompilerInfo> {
let bsc_path = helpers::get_bsc();
let bsc_hash = helpers::compute_file_hash(&bsc_path).ok_or(anyhow!(
"Failed to compute bsc hash for {}",
bsc_path.to_string_lossy()
))?;
let runtime_path = compile::get_runtime_path(&project_context.current_config, project_context)?;
Ok(CompilerInfo {
bsc_path,
bsc_hash,
runtime_path,
})
}

pub fn initialize_build(
default_timing: Option<Duration>,
filter: &Option<regex::Regex>,
Expand All @@ -117,8 +133,8 @@ pub fn initialize_build(
build_dev_deps: bool,
snapshot_output: bool,
) -> Result<BuildState> {
let bsc_path = helpers::get_bsc();
let project_context = ProjectContext::new(path)?;
let compiler = get_compiler_info(&project_context)?;

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

let compiler_check = verify_compiler_info(&packages, &compiler);

if !snapshot_output && show_progress {
println!(
"{}{} {}Built package tree in {:.2}s",
Expand All @@ -139,6 +157,14 @@ pub fn initialize_build(
.unwrap_or(timing_package_tree_elapsed)
.as_secs_f64()
);
if let CompilerCheckResult::CleanedPackagesDueToCompiler = compiler_check {
println!(
"{}{} {}Cleaned previous build due to compiler update",
LINE_CLEAR,
style("[1/7]").bold().dim(),
SWEEP
);
}
}

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

let mut build_state = BuildState::new(project_context, packages, bsc_path);
let mut build_state = BuildState::new(project_context, packages, compiler);
packages::parse_packages(&mut build_state);
let timing_source_files_elapsed = timing_source_files.elapsed();

Expand Down Expand Up @@ -448,6 +474,9 @@ pub fn incremental_build(
log_deprecations(build_state);
}

// Write per-package compiler metadata to `lib/bs/compiler-info.json` (idempotent)
write_compiler_info(build_state);

Ok(())
}
}
Expand Down
14 changes: 11 additions & 3 deletions rewatch/src/build/build_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use crate::build::packages::{Namespace, Package};
use crate::config::Config;
use crate::project_context::ProjectContext;
use ahash::{AHashMap, AHashSet};
use blake3::Hash;
use std::{fmt::Display, path::PathBuf, time::SystemTime};

#[derive(Debug, Clone, PartialEq)]
Expand Down Expand Up @@ -96,10 +97,17 @@ pub struct BuildState {
pub packages: AHashMap<String, Package>,
pub module_names: AHashSet<String>,
pub deleted_modules: AHashSet<String>,
pub bsc_path: PathBuf,
pub compiler_info: CompilerInfo,
pub deps_initialized: bool,
}

#[derive(Debug, Clone)]
pub struct CompilerInfo {
pub bsc_path: PathBuf,
pub bsc_hash: Hash,
pub runtime_path: PathBuf,
}

impl BuildState {
pub fn get_package(&self, package_name: &str) -> Option<&Package> {
self.packages.get(package_name)
Expand All @@ -111,15 +119,15 @@ impl BuildState {
pub fn new(
project_context: ProjectContext,
packages: AHashMap<String, Package>,
bsc_path: PathBuf,
compiler: CompilerInfo,
) -> Self {
Self {
project_context,
module_names: AHashSet::new(),
modules: AHashMap::new(),
packages,
deleted_modules: AHashSet::new(),
bsc_path,
compiler_info: compiler,
deps_initialized: false,
}
}
Expand Down
11 changes: 7 additions & 4 deletions rewatch/src/build/clean.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use super::build_types::*;
use super::packages;
use crate::build;
use crate::build::packages::Package;
use crate::config::Config;
use crate::helpers;
Expand Down Expand Up @@ -332,9 +333,8 @@ pub fn cleanup_after_build(build_state: &BuildState) {

pub fn clean(path: &Path, show_progress: bool, snapshot_output: bool, clean_dev_deps: bool) -> Result<()> {
let project_context = ProjectContext::new(path)?;

let compiler_info = build::get_compiler_info(&project_context)?;
let packages = packages::make(&None, &project_context, show_progress, clean_dev_deps)?;
let bsc_path = helpers::get_bsc();

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

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

fn clean_package(show_progress: bool, snapshot_output: bool, package: &Package) {
pub fn clean_package(show_progress: bool, snapshot_output: bool, package: &Package) {
if show_progress {
if snapshot_output {
println!("Cleaning {}", package.name)
Expand All @@ -441,4 +441,7 @@ fn clean_package(show_progress: bool, snapshot_output: bool, package: &Package)
let path_str = package.get_ocaml_build_path();
let path = std::path::Path::new(&path_str);
let _ = std::fs::remove_dir_all(path);

// remove the per-package compiler metadata file so that a subsequent build writes fresh metadata
let _ = std::fs::remove_file(package.get_compiler_info_path());
}
45 changes: 32 additions & 13 deletions rewatch/src/build/compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ use console::style;
use log::{debug, trace};
use rayon::prelude::*;
use std::path::Path;
use std::path::PathBuf;
use std::process::Command;
use std::sync::OnceLock;
use std::time::SystemTime;

pub fn compile(
Expand Down Expand Up @@ -336,22 +338,36 @@ pub fn compile(
Ok((compile_errors, compile_warnings, num_compiled_modules))
}

pub fn get_runtime_path_args(
package_config: &Config,
project_context: &ProjectContext,
) -> Result<Vec<String>> {
match std::env::var("RESCRIPT_RUNTIME") {
Ok(runtime_path) => Ok(vec!["-runtime-path".to_string(), runtime_path]),
static RUNTIME_PATH_MEMO: OnceLock<PathBuf> = OnceLock::new();

pub fn get_runtime_path(package_config: &Config, project_context: &ProjectContext) -> Result<PathBuf> {
if let Some(p) = RUNTIME_PATH_MEMO.get() {
return Ok(p.clone());
}

let resolved = match std::env::var("RESCRIPT_RUNTIME") {
Ok(runtime_path) => Ok(PathBuf::from(runtime_path)),
Err(_) => match helpers::try_package_path(package_config, project_context, "@rescript/runtime") {
Ok(runtime_path) => Ok(vec![
"-runtime-path".to_string(),
runtime_path.to_string_lossy().to_string(),
]),
Ok(runtime_path) => Ok(runtime_path),
Err(err) => Err(anyhow!(
"The rescript runtime package could not be found.\nPlease set RESCRIPT_RUNTIME environment variable or make sure the runtime package is installed.\nError: {err}"
)),
},
}
}?;

let _ = RUNTIME_PATH_MEMO.set(resolved.clone());
Ok(resolved)
}

pub fn get_runtime_path_args(
package_config: &Config,
project_context: &ProjectContext,
) -> Result<Vec<String>> {
let runtime_path = get_runtime_path(package_config, project_context)?;
Ok(vec![
"-runtime-path".to_string(),
runtime_path.to_string_lossy().to_string(),
])
}

pub fn compiler_args(
Expand Down Expand Up @@ -581,7 +597,7 @@ fn compile_file(
let BuildState {
packages,
project_context,
bsc_path,
compiler_info,
..
} = build_state;
let root_config = build_state.get_root_config();
Expand Down Expand Up @@ -612,7 +628,7 @@ fn compile_file(
package.is_local_dep,
)?;

let to_mjs = Command::new(bsc_path)
let to_mjs = Command::new(&compiler_info.bsc_path)
.current_dir(
build_path_abs
.canonicalize()
Expand Down Expand Up @@ -748,6 +764,9 @@ fn compile_file(
}
});

// TODO: Optionally record per-module successful compile timestamps if needed
// for future metadata-based invalidation. Current metadata is per-package.

if helpers::contains_ascii_characters(&err) {
if package.is_local_dep {
// suppress warnings of external deps
Expand Down
Loading
Loading