Skip to content

Commit f6f9cc2

Browse files
author
Roland Peelen
authored
Merge pull request #6 from rolandpeelen/watch
Watch
2 parents 5aca737 + a08068d commit f6f9cc2

File tree

5 files changed

+294
-257
lines changed

5 files changed

+294
-257
lines changed

src/build.rs

Lines changed: 247 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,30 @@ use crate::helpers::get_package_path;
77
use crate::package_tree;
88
use crate::package_tree::Package;
99
use ahash::{AHashMap, AHashSet};
10+
use console::{style, Emoji};
11+
use indicatif::ProgressBar;
12+
use indicatif::ProgressStyle;
13+
use log::Level::Info;
1014
use log::{debug, error};
15+
use log::{info, log_enabled};
1116
use rayon::prelude::*;
1217
use std::fs;
1318
use std::fs::File;
19+
use std::io::stdout;
20+
use std::io::Write;
1421
use std::io::{self, BufRead};
1522
use std::path::{Path, PathBuf};
1623
use std::process::Command;
24+
use std::time::Instant;
25+
26+
static TREE: Emoji<'_, '_> = Emoji("🌴 ", "");
27+
static SWEEP: Emoji<'_, '_> = Emoji("🧹 ", "");
28+
static LOOKING_GLASS: Emoji<'_, '_> = Emoji("🔍 ", "");
29+
static CODE: Emoji<'_, '_> = Emoji("🟰 ", "");
30+
static SWORDS: Emoji<'_, '_> = Emoji("⚔️ ", "");
31+
static CHECKMARK: Emoji<'_, '_> = Emoji("️✅ ", "");
32+
static CROSS: Emoji<'_, '_> = Emoji("️🛑 ", "");
33+
static LINE_CLEAR: &str = "\x1b[2K";
1734

1835
#[derive(Debug, Clone, PartialEq)]
1936
pub enum SourceType {
@@ -764,3 +781,233 @@ pub fn compile_file(
764781
}
765782
}
766783
}
784+
785+
pub fn clean(path: &str) {
786+
let project_root = helpers::get_abs_path(path);
787+
let packages = package_tree::make(&project_root);
788+
789+
packages.iter().for_each(|(_, package)| {
790+
println!("Cleaning {}...", package.name);
791+
let path = std::path::Path::new(&package.package_dir)
792+
.join("lib")
793+
.join("ocaml");
794+
let _ = std::fs::remove_dir_all(path);
795+
let path = std::path::Path::new(&package.package_dir)
796+
.join("lib")
797+
.join("bs");
798+
let _ = std::fs::remove_dir_all(path);
799+
})
800+
}
801+
802+
pub fn build(path: &str) -> AHashMap<std::string::String, Module> {
803+
let timing_total = Instant::now();
804+
let project_root = helpers::get_abs_path(path);
805+
let rescript_version = get_version(&project_root);
806+
807+
print!(
808+
"{} {} Building package tree...",
809+
style("[1/5]").bold().dim(),
810+
TREE
811+
);
812+
let _ = stdout().flush();
813+
let timing_package_tree = Instant::now();
814+
let packages = package_tree::make(&project_root);
815+
let timing_package_tree_elapsed = timing_package_tree.elapsed();
816+
println!(
817+
"{}\r{} {}Built package tree in {:.2}s",
818+
LINE_CLEAR,
819+
style("[1/5]").bold().dim(),
820+
CHECKMARK,
821+
timing_package_tree_elapsed.as_secs_f64()
822+
);
823+
824+
let timing_source_files = Instant::now();
825+
print!(
826+
"{} {} Finding source files...",
827+
style("[2/5]").bold().dim(),
828+
LOOKING_GLASS
829+
);
830+
let _ = stdout().flush();
831+
let (all_modules, modules) = parse(&project_root, packages.to_owned());
832+
let timing_source_files_elapsed = timing_source_files.elapsed();
833+
println!(
834+
"{}\r{} {}Found source files in {:.2}s",
835+
LINE_CLEAR,
836+
style("[2/5]").bold().dim(),
837+
CHECKMARK,
838+
timing_source_files_elapsed.as_secs_f64()
839+
);
840+
841+
print!(
842+
"{} {} Cleaning up previous build...",
843+
style("[3/5]").bold().dim(),
844+
SWEEP
845+
);
846+
let timing_cleanup = Instant::now();
847+
let (diff_cleanup, total_cleanup) = cleanup_previous_build(&packages, &modules, &project_root);
848+
let timing_cleanup_elapsed = timing_cleanup.elapsed();
849+
println!(
850+
"{}\r{} {}Cleaned {}/{} {:.2}s",
851+
LINE_CLEAR,
852+
style("[3/5]").bold().dim(),
853+
CHECKMARK,
854+
diff_cleanup,
855+
total_cleanup,
856+
timing_cleanup_elapsed.as_secs_f64()
857+
);
858+
859+
print!(
860+
"{} {} Parsing source files...",
861+
style("[4/5]").bold().dim(),
862+
CODE
863+
);
864+
let _ = stdout().flush();
865+
866+
let timing_ast = Instant::now();
867+
let modules = generate_asts(
868+
rescript_version.to_string(),
869+
&project_root,
870+
modules,
871+
all_modules,
872+
);
873+
let timing_ast_elapsed = timing_ast.elapsed();
874+
println!(
875+
"{}\r{} {}Parsed source files in {:.2}s",
876+
LINE_CLEAR,
877+
style("[4/5]").bold().dim(),
878+
CHECKMARK,
879+
timing_ast_elapsed.as_secs_f64()
880+
);
881+
882+
let pb = ProgressBar::new(modules.len().try_into().unwrap());
883+
pb.set_style(
884+
ProgressStyle::with_template(&format!(
885+
"{} {} Compiling... {{wide_bar}} {{pos}}/{{len}} {{msg}}",
886+
style("[5/5]").bold().dim(),
887+
SWORDS
888+
))
889+
.unwrap(),
890+
);
891+
let start_compiling = Instant::now();
892+
893+
let mut compiled_modules = AHashSet::<String>::new();
894+
895+
let mut loop_count = 0;
896+
let mut files_total_count = 0;
897+
let mut files_current_loop_count;
898+
let mut compile_errors = "".to_string();
899+
let total_modules = modules.len();
900+
901+
loop {
902+
files_current_loop_count = 0;
903+
loop_count += 1;
904+
905+
info!(
906+
"Compiled: {} out of {}. Compile loop: {}",
907+
files_total_count,
908+
modules.len(),
909+
loop_count,
910+
);
911+
912+
modules
913+
.par_iter()
914+
.map(|(module_name, module)| {
915+
let mut stderr = "".to_string();
916+
if module.deps.is_subset(&compiled_modules)
917+
&& !compiled_modules.contains(module_name)
918+
{
919+
match module.source_type.to_owned() {
920+
SourceType::MlMap => (Some(module_name.to_owned()), stderr),
921+
SourceType::SourceFile => {
922+
// compile interface first
923+
match module.asti_path.to_owned() {
924+
Some(asti_path) => {
925+
let result = compile_file(
926+
&module.package.name,
927+
&asti_path,
928+
module,
929+
&project_root,
930+
true,
931+
);
932+
match result {
933+
Err(err) => stderr.push_str(&err),
934+
Ok(()) => (),
935+
}
936+
}
937+
_ => (),
938+
}
939+
940+
let result = compile_file(
941+
&module.package.name,
942+
&module.ast_path.to_owned().unwrap(),
943+
module,
944+
&project_root,
945+
false,
946+
);
947+
948+
match result {
949+
Err(err) => stderr.push_str(&err),
950+
Ok(()) => (),
951+
}
952+
953+
(Some(module_name.to_owned()), stderr)
954+
}
955+
}
956+
} else {
957+
(None, stderr)
958+
}
959+
})
960+
.collect::<Vec<(Option<String>, String)>>()
961+
.iter()
962+
.for_each(|(module_name, stderr)| {
963+
module_name.iter().for_each(|name| {
964+
if !(log_enabled!(Info)) {
965+
pb.inc(1);
966+
}
967+
files_current_loop_count += 1;
968+
compiled_modules.insert(name.to_string());
969+
});
970+
971+
compile_errors.push_str(&stderr);
972+
// error!("Some error were generated compiling this round: \n {}", err);
973+
});
974+
975+
files_total_count += files_current_loop_count;
976+
977+
if files_total_count == total_modules {
978+
break;
979+
}
980+
if files_current_loop_count == 0 {
981+
// we probably want to find the cycle(s), and give a helpful error message here
982+
compile_errors.push_str("Can't continue... Dependency cycle\n")
983+
}
984+
if compile_errors.len() > 0 {
985+
break;
986+
};
987+
}
988+
let compile_duration = start_compiling.elapsed();
989+
990+
pb.finish();
991+
if compile_errors.len() > 0 {
992+
println!(
993+
"{}\r{} {}Compiled in {:.2}s",
994+
LINE_CLEAR,
995+
style("[5/5]").bold().dim(),
996+
CROSS,
997+
compile_duration.as_secs_f64()
998+
);
999+
println!("{}", &compile_errors);
1000+
std::process::exit(1);
1001+
}
1002+
println!(
1003+
"{}\r{} {}Compiled in {:.2}s",
1004+
LINE_CLEAR,
1005+
style("[5/5]").bold().dim(),
1006+
CHECKMARK,
1007+
compile_duration.as_secs_f64()
1008+
);
1009+
let timing_total_elapsed = timing_total.elapsed();
1010+
println!("Done in {:.2}s", timing_total_elapsed.as_secs_f64());
1011+
1012+
modules
1013+
}

src/helpers.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use std::ffi::OsString;
12
use std::fs;
23
use std::path::Component;
34
use std::path::Path;
@@ -119,3 +120,13 @@ pub fn create_build_path(build_path: &str) {
119120
pub fn get_bsc(root_path: &str) -> String {
120121
get_node_modules_path(root_path) + "/rescript/darwinarm64/bsc.exe"
121122
}
123+
124+
pub fn string_ends_with_any(s: &PathBuf, suffixes: &[&str]) -> bool {
125+
suffixes.iter().any(|&suffix| {
126+
s.extension()
127+
.unwrap_or(&OsString::new())
128+
.to_str()
129+
.unwrap_or("")
130+
== suffix
131+
})
132+
}

0 commit comments

Comments
 (0)