@@ -14,8 +14,10 @@ use std::path::{Path, PathBuf};
1414use std:: sync:: OnceLock ;
1515use std:: { env, fs} ;
1616
17+ use build_helper:: exit;
1718use build_helper:: git:: PathFreshness ;
1819
20+ use crate :: core:: build_steps:: llvm;
1921use crate :: core:: builder:: { Builder , RunConfig , ShouldRun , Step , StepMetadata } ;
2022use crate :: core:: config:: { Config , TargetSelection } ;
2123use crate :: utils:: build_stamp:: { BuildStamp , generate_smart_stamp_hash} ;
@@ -896,13 +898,28 @@ fn get_var(var_base: &str, host: &str, target: &str) -> Option<OsString> {
896898 . or_else ( || env:: var_os ( var_base) )
897899}
898900
901+ #[ derive( Clone ) ]
902+ pub struct BuiltEnzyme {
903+ /// Path to the libEnzyme dylib.
904+ enzyme : PathBuf ,
905+ }
906+
907+ impl BuiltEnzyme {
908+ pub fn enzyme_path ( & self ) -> PathBuf {
909+ self . enzyme . clone ( )
910+ }
911+ pub fn enzyme_filename ( & self ) -> String {
912+ self . enzyme . file_name ( ) . unwrap ( ) . to_str ( ) . unwrap ( ) . to_owned ( )
913+ }
914+ }
915+
899916#[ derive( Debug , Copy , Clone , Hash , PartialEq , Eq ) ]
900917pub struct Enzyme {
901918 pub target : TargetSelection ,
902919}
903920
904921impl Step for Enzyme {
905- type Output = PathBuf ;
922+ type Output = BuiltEnzyme ;
906923 const IS_HOST : bool = true ;
907924
908925 fn should_run ( run : ShouldRun < ' _ > ) -> ShouldRun < ' _ > {
@@ -914,16 +931,16 @@ impl Step for Enzyme {
914931 }
915932
916933 /// Compile Enzyme for `target`.
917- fn run ( self , builder : & Builder < ' _ > ) -> PathBuf {
934+ fn run ( self , builder : & Builder < ' _ > ) -> Self :: Output {
918935 builder. require_submodule (
919936 "src/tools/enzyme" ,
920937 Some ( "The Enzyme sources are required for autodiff." ) ,
921938 ) ;
939+ let target = self . target ;
940+
922941 if builder. config . dry_run ( ) {
923- let out_dir = builder. enzyme_out ( self . target ) ;
924- return out_dir;
942+ return BuiltEnzyme { enzyme : builder. config . tempdir ( ) . join ( "enzyme-dryrun" ) } ;
925943 }
926- let target = self . target ;
927944
928945 let LlvmResult { host_llvm_config, .. } = builder. ensure ( Llvm { target : self . target } ) ;
929946
@@ -939,6 +956,12 @@ impl Step for Enzyme {
939956 let out_dir = builder. enzyme_out ( target) ;
940957 let stamp = BuildStamp :: new ( & out_dir) . with_prefix ( "enzyme" ) . add_stamp ( smart_stamp_hash) ;
941958
959+ let llvm_version_major = llvm:: get_llvm_version_major ( builder, & host_llvm_config) ;
960+ let lib_ext = std:: env:: consts:: DLL_EXTENSION ;
961+ let libenzyme = format ! ( "libEnzyme-{llvm_version_major}" ) ;
962+ let build_dir = out_dir. join ( "lib" ) ;
963+ let dylib = build_dir. join ( & libenzyme) . with_extension ( lib_ext) ;
964+
942965 trace ! ( "checking build stamp to see if we need to rebuild enzyme artifacts" ) ;
943966 if stamp. is_up_to_date ( ) {
944967 trace ! ( ?out_dir, "enzyme build artifacts are up to date" ) ;
@@ -952,7 +975,15 @@ impl Step for Enzyme {
952975 stamp. path( ) . display( )
953976 ) ) ;
954977 }
955- return out_dir;
978+ return BuiltEnzyme { enzyme : dylib } ;
979+ }
980+
981+ let llvm_cmake_dir = builder. llvm_out ( target) . join ( "lib/cmake/llvm" ) ;
982+ if !builder. config . dry_run ( ) && !llvm_cmake_dir. is_dir ( ) {
983+ builder. info ( & format ! (
984+ "WARNING: {} does not exist, Enzyme build will likely fail" ,
985+ llvm_cmake_dir. display( )
986+ ) ) ;
956987 }
957988
958989 trace ! ( ?target, "(re)building enzyme artifacts" ) ;
@@ -961,9 +992,6 @@ impl Step for Enzyme {
961992 let _time = helpers:: timeit ( builder) ;
962993 t ! ( fs:: create_dir_all( & out_dir) ) ;
963994
964- builder
965- . config
966- . update_submodule ( Path :: new ( "src" ) . join ( "tools" ) . join ( "enzyme" ) . to_str ( ) . unwrap ( ) ) ;
967995 let mut cfg = cmake:: Config :: new ( builder. src . join ( "src/tools/enzyme/enzyme/" ) ) ;
968996 configure_cmake ( builder, target, & mut cfg, true , LdFlags :: default ( ) , & [ ] ) ;
969997
@@ -983,12 +1011,22 @@ impl Step for Enzyme {
9831011 . define ( "LLVM_ENABLE_ASSERTIONS" , "ON" )
9841012 . define ( "ENZYME_EXTERNAL_SHARED_LIB" , "ON" )
9851013 . define ( "ENZYME_BC_LOADER" , "OFF" )
986- . define ( "LLVM_DIR" , builder . llvm_out ( target ) ) ;
1014+ . define ( "LLVM_DIR" , llvm_cmake_dir ) ;
9871015
9881016 cfg. build ( ) ;
9891017
1018+ // At this point, `out_dir` should contain the built libEnzyme-<LLVM-version>.<dylib-ext>
1019+ // file.
1020+ if !dylib. exists ( ) {
1021+ eprintln ! (
1022+ "`{libenzyme}` not found in `{}`. Either the build has failed or Enzyme was built with a wrong version of LLVM" ,
1023+ build_dir. display( )
1024+ ) ;
1025+ exit ! ( 1 ) ;
1026+ }
1027+
9901028 t ! ( stamp. write( ) ) ;
991- out_dir
1029+ BuiltEnzyme { enzyme : dylib }
9921030 }
9931031}
9941032
0 commit comments