@@ -3278,11 +3278,19 @@ def build_and_install_one(ecdict, init_env):
32783278 start_time = time .time ()
32793279 try :
32803280 run_test_cases = not build_option ('skip_test_cases' ) and app .cfg ['tests' ]
3281+
32813282 if not dry_run :
32823283 # create our reproducability files before carrying out the easyblock steps
32833284 reprod_dir_root = os .path .dirname (app .logfile )
32843285 reprod_dir = reproduce_build (app , reprod_dir_root )
3286+
32853287 result = app .run_all_steps (run_test_cases = run_test_cases )
3288+
3289+ if not dry_run :
3290+ # also add any extension easyblocks used during the build for reproducability
3291+ if app .ext_instances :
3292+ copy_easyblocks_for_reprod (app .ext_instances , reprod_dir )
3293+
32863294 except EasyBuildError as err :
32873295 first_n = 300
32883296 errormsg = "build failed (first %d chars): %s" % (first_n , err .msg [:first_n ])
@@ -3416,6 +3424,24 @@ def build_and_install_one(ecdict, init_env):
34163424 return (success , application_log , errormsg )
34173425
34183426
3427+ def copy_easyblocks_for_reprod (easyblock_instances , reprod_dir ):
3428+ reprod_easyblock_dir = os .path .join (reprod_dir , 'easyblocks' )
3429+ easyblock_paths = set ()
3430+ for easyblock_instance in easyblock_instances :
3431+ for easyblock_class in inspect .getmro (type (easyblock_instance )):
3432+ easyblock_path = inspect .getsourcefile (easyblock_class )
3433+ # if we reach EasyBlock or ExtensionEasyBlock class, we are done
3434+ # (ExtensionEasyblock is hardcoded to avoid a cyclical import)
3435+ if easyblock_class .__name__ in [EasyBlock .__name__ , 'ExtensionEasyBlock' ]:
3436+ break
3437+ else :
3438+ easyblock_paths .add (easyblock_path )
3439+ for easyblock_path in easyblock_paths :
3440+ easyblock_basedir , easyblock_filename = os .path .split (easyblock_path )
3441+ copy_file (easyblock_path , os .path .join (reprod_easyblock_dir , easyblock_filename ))
3442+ _log .info ("Dumped easyblock %s required for reproduction to %s" , easyblock_filename , reprod_easyblock_dir )
3443+
3444+
34193445def reproduce_build (app , reprod_dir_root ):
34203446 """
34213447 Create reproducability files (processed easyconfig and easyblocks used) from class instance
@@ -3437,18 +3463,8 @@ def reproduce_build(app, reprod_dir_root):
34373463 except NotImplementedError as err :
34383464 _log .warning ("Unable to dump easyconfig instance to %s: %s" , reprod_spec , err )
34393465
3440- # also archive the relevant easyblocks
3441- reprod_easyblock_dir = os .path .join (reprod_dir , 'easyblocks' )
3442- for easyblock_class in inspect .getmro (type (app )):
3443- easyblock_path = inspect .getsourcefile (easyblock_class )
3444- easyblock_basedir , easyblock_filename = os .path .split (easyblock_path )
3445- # if we reach EasyBlock or ExtensionEasyBlock class, we are done
3446- # (ExtensionEasyblock is hardcoded to avoid a cyclical import)
3447- if easyblock_class .__name__ in [EasyBlock .__name__ , 'ExtensionEasyBlock' ]:
3448- break
3449- else :
3450- copy_file (easyblock_path , os .path .join (reprod_easyblock_dir , easyblock_filename ))
3451- _log .info ("Dumped easyblock %s required for reproduction to %s" , easyblock_filename , reprod_easyblock_dir )
3466+ # also archive all the relevant easyblocks (including any used by extensions)
3467+ copy_easyblocks_for_reprod ([app ], reprod_dir )
34523468
34533469 # if there is a hook file we should also archive it
34543470 hooks_path = build_option ('hooks' )
0 commit comments