Skip to content
Snippets Groups Projects
compile_analyses.py 3.73 KiB
Newer Older
  • Learn to ignore specific revisions
  • #!/usr/bin/env python3
    
    """
    Compile all root analysis scripts under
    benchmarks/<BENCHMARK>/analysis/*.cxx
    
    Doing this step here rather than during the main benchmark script has
    multiple advantages:
        1. Get feedback on syntax errors early on, without wasting compute resources
        2. Avoid race conditions for large benchmarks run in parallel
        3. Make it easier to properly handle the root build directory, as
           this has to exist prior to our attempt to compile, else all will
           fail (this is probably an old bug in root...)
    
    Analysis scripts are expected to have extension 'cxx' and be located in the analysis
    subdirectory
    """
    
    ## Our analysis path and file extension for glob
    ANALYSIS_PATH=r'benchmarks/{}/analysis'
    ANALYSIS_EXT = r'cxx'
    
    import argparse
    import os
    from pathlib import Path
    
    ## Exceptions for this module
    class Error(Exception):
        '''Base class for exceptions in this module.'''
        pass
    
    class PathNotFoundError(Exception):
        '''Path does not exist.
    
        Attributes:
            path: the path name
            message: error message
        '''
        def __init__(self, path):
            self.file = file
            self.message = 'No such directory: {}'.format(file)
    class NoAnalysesFoundError(Exception):
        '''Did not find any analysis scripts to complile
    
        Attributes:
            path: the analysis path
            message: error message
        '''
        def __init__(self, path):
            self.file = file
            self.message = 'No analysis found (extension \'{}\' in path: {}'.format(file,
                    ANALYSIS_EXT)
    
    class CompilationError(Exception):
        '''Raised when we failed to compile an analysis script
    
        Attributes:
            file: analysis file name
            path: analysis path
            message: error message
        '''
        def __init__(self, file):
            self.file = file
            self.message = "Analysis '{}' failed to compile".format(file)
    
    parser = argparse.ArgumentParser()
    parser.add_argument(
            'benchmark',
            help='A benchmarks for which to compile the analysis scripts.')
    
    def compile_analyses(benchmark):
        '''Compile all analysis scripts for a benchmark.'''
        print("Compiling all analyis scripts for '{}'".format(benchmark))
    
        ## Ensure our build directory exists
        _init_build_dir(benchmark)
    
        ## Get a list of all analysis scripts
        _compile_all(benchmark)
    
        ## All done!
        print('All analyses for', benchmark, 'compiled successfully')
    
    def _init_build_dir(benchmark):
        '''Initialize our ROOT build directory (if using one).'''
        print(' --> Initializing ROOT build directory ...')
        build_prefix = os.getenv('ROOT_BUILD_DIR')
        if build_prefix is None:
            print('    --> ROOT_BUILD_DIR not set, no action needed.')
            return
        ## deduce the root build directory
        pwd = os.getenv('PWD')
        build_dir = '{}/{}/{}'.format(build_prefix, pwd, ANALYSIS_PATH.format(benchmark))
        print("    --> Ensuring directory '{}' exists".format(build_dir))
        os.system('mkdir -p {}'.format(build_dir))
    
    def _compile_all(benchmark):
        '''Compile all analysis for this benchmark.'''
        print(' --> Compiling analysis scripts')
        anadir = Path(ANALYSIS_PATH.format(benchmark))
        if not anadir.exists():
            raise PathNotFoundError(anadir)
        ana_list = []
        for file in anadir.glob('*.{}'.format(ANALYSIS_EXT)):
            ana_list.append(file)
            print('    --> Compiling:', file, flush=True)
            err = os.system(_compile_cmd(file))
            if err:
                raise CompilationError(file)
        if len(ana_list) == 0:
            raise NoAnalysesFoundError(anadir)
    
    def _compile_cmd(file):
        '''Return a one-line shell command to compile an analysis script.'''
        return r'bash -c "root -q -b -e \".L {}+\""'.format(file)
    
    if __name__ == "__main__":
        args = parser.parse_args()
        compile_analyses(args.benchmark)