@@ -7,13 +7,30 @@ use crate::helpers::get_package_path;
7
7
use crate :: package_tree;
8
8
use crate :: package_tree:: Package ;
9
9
use ahash:: { AHashMap , AHashSet } ;
10
+ use console:: { style, Emoji } ;
11
+ use indicatif:: ProgressBar ;
12
+ use indicatif:: ProgressStyle ;
13
+ use log:: Level :: Info ;
10
14
use log:: { debug, error} ;
15
+ use log:: { info, log_enabled} ;
11
16
use rayon:: prelude:: * ;
12
17
use std:: fs;
13
18
use std:: fs:: File ;
19
+ use std:: io:: stdout;
20
+ use std:: io:: Write ;
14
21
use std:: io:: { self , BufRead } ;
15
22
use std:: path:: { Path , PathBuf } ;
16
23
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" ;
17
34
18
35
#[ derive( Debug , Clone , PartialEq ) ]
19
36
pub enum SourceType {
@@ -764,3 +781,233 @@ pub fn compile_file(
764
781
}
765
782
}
766
783
}
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
+ }
0 commit comments