@@ -529,6 +529,7 @@ impl Step for Llvm {
529
529
}
530
530
} ;
531
531
532
+ // FIXME(ZuseZ4): Do we need that for Enzyme too?
532
533
// When building LLVM with LLVM_LINK_LLVM_DYLIB for macOS, an unversioned
533
534
// libLLVM.dylib will be built. However, llvm-config will still look
534
535
// for a versioned path like libLLVM-14.dylib. Manually create a symbolic
@@ -849,6 +850,100 @@ fn get_var(var_base: &str, host: &str, target: &str) -> Option<OsString> {
849
850
. or_else ( || env:: var_os ( var_base) )
850
851
}
851
852
853
+ #[ derive( Debug , Copy , Clone , Hash , PartialEq , Eq ) ]
854
+ pub struct Enzyme {
855
+ pub target : TargetSelection ,
856
+ }
857
+
858
+ impl Step for Enzyme {
859
+ type Output = PathBuf ;
860
+ const ONLY_HOSTS : bool = true ;
861
+
862
+ fn should_run ( run : ShouldRun < ' _ > ) -> ShouldRun < ' _ > {
863
+ run. path ( "src/tools/enzyme/enzyme" )
864
+ }
865
+
866
+ fn make_run ( run : RunConfig < ' _ > ) {
867
+ run. builder . ensure ( Enzyme { target : run. target } ) ;
868
+ }
869
+
870
+ /// Compile Enzyme for `target`.
871
+ fn run ( self , builder : & Builder < ' _ > ) -> PathBuf {
872
+ builder. require_submodule (
873
+ "src/tools/enzyme" ,
874
+ Some ( "The Enzyme sources are required for autodiff." ) ,
875
+ ) ;
876
+ if builder. config . dry_run ( ) {
877
+ let out_dir = builder. enzyme_out ( self . target ) ;
878
+ return out_dir;
879
+ }
880
+ let target = self . target ;
881
+
882
+ let LlvmResult { llvm_config, .. } = builder. ensure ( Llvm { target : self . target } ) ;
883
+
884
+ static STAMP_HASH_MEMO : OnceLock < String > = OnceLock :: new ( ) ;
885
+ let smart_stamp_hash = STAMP_HASH_MEMO . get_or_init ( || {
886
+ generate_smart_stamp_hash (
887
+ builder,
888
+ & builder. config . src . join ( "src/tools/enzyme" ) ,
889
+ builder. enzyme_info . sha ( ) . unwrap_or_default ( ) ,
890
+ )
891
+ } ) ;
892
+
893
+ let out_dir = builder. enzyme_out ( target) ;
894
+ let stamp = out_dir. join ( "enzyme-finished-building" ) ;
895
+ let stamp = HashStamp :: new ( stamp, Some ( smart_stamp_hash) ) ;
896
+
897
+ if stamp. is_done ( ) {
898
+ if stamp. hash . is_none ( ) {
899
+ builder. info (
900
+ "Could not determine the Enzyme submodule commit hash. \
901
+ Assuming that an Enzyme rebuild is not necessary.",
902
+ ) ;
903
+ builder. info ( & format ! (
904
+ "To force Enzyme to rebuild, remove the file `{}`" ,
905
+ stamp. path. display( )
906
+ ) ) ;
907
+ }
908
+ return out_dir;
909
+ }
910
+
911
+ builder. info ( & format ! ( "Building Enzyme for {}" , target) ) ;
912
+ t ! ( stamp. remove( ) ) ;
913
+ let _time = helpers:: timeit ( builder) ;
914
+ t ! ( fs:: create_dir_all( & out_dir) ) ;
915
+
916
+ builder
917
+ . config
918
+ . update_submodule ( Path :: new ( "src" ) . join ( "tools" ) . join ( "enzyme" ) . to_str ( ) . unwrap ( ) ) ;
919
+ let mut cfg = cmake:: Config :: new ( builder. src . join ( "src/tools/enzyme/enzyme/" ) ) ;
920
+ // FIXME(ZuseZ4): Find a nicer way to use Enzyme Debug builds
921
+ //cfg.profile("Debug");
922
+ //cfg.define("CMAKE_BUILD_TYPE", "Debug");
923
+ configure_cmake ( builder, target, & mut cfg, true , LdFlags :: default ( ) , & [ ] ) ;
924
+
925
+ // Re-use the same flags as llvm to control the level of debug information
926
+ // generated for lld.
927
+ let profile = match ( builder. config . llvm_optimize , builder. config . llvm_release_debuginfo ) {
928
+ ( false , _) => "Debug" ,
929
+ ( true , false ) => "Release" ,
930
+ ( true , true ) => "RelWithDebInfo" ,
931
+ } ;
932
+
933
+ cfg. out_dir ( & out_dir)
934
+ . profile ( profile)
935
+ . env ( "LLVM_CONFIG_REAL" , & llvm_config)
936
+ . define ( "LLVM_ENABLE_ASSERTIONS" , "ON" )
937
+ . define ( "ENZYME_EXTERNAL_SHARED_LIB" , "ON" )
938
+ . define ( "LLVM_DIR" , builder. llvm_out ( target) ) ;
939
+
940
+ cfg. build ( ) ;
941
+
942
+ t ! ( stamp. write( ) ) ;
943
+ out_dir
944
+ }
945
+ }
946
+
852
947
#[ derive( Debug , Clone , Hash , PartialEq , Eq ) ]
853
948
pub struct Lld {
854
949
pub target : TargetSelection ,
0 commit comments