def compile_file(f_root, srcdir, bindir, suffix='.c'):
    """Compile a single C or assembler file, with the given file root, "f_root",
       suffix "suffix", from the source directory, "srcdir", in to the bin
       directory, "bindir" using the general preprocessor and C compilation
       flags.

       Return True if the compilation success, False if it fails. Log
       everything in the event of failure

    """
    abs_src = os.path.join(f'{srcdir}', f'{f_root}{suffix}')
    abs_bin = os.path.join(f'{bindir}', f'{f_root}.o')

    # Construct the argument list
    arglist = [f'{gp["cc"]}']
    arglist.extend(gp['cflags'])
    arglist.extend(gp['cc_output_pattern'].format(f'{f_root}.o').split())
    arglist.extend(gp['cc_input_pattern'].format(abs_src).split())

    # Run the compilation, but only if the source file is newer than the
    # binary.
    succeeded = True
    res = None

    if not os.path.isfile(abs_bin) or (
            os.path.getmtime(abs_src) > os.path.getmtime(abs_bin)
    ):
        if gp['verbose']:
            log.debug(f'Compiling in directory {bindir}')
            log.debug(arglist_to_str(arglist))

        try:
            res = subprocess.run(
                arglist,
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE,
                cwd=bindir,
                timeout=gp['timeout'],
            )
            if res.returncode != 0:
                log.warning(
                    f'Warning: Compilation of {f_root}{suffix} from source ' +
                    f'directory {srcdir} to binary directory {bindir} failed'
                )
                succeeded = False
        except subprocess.TimeoutExpired:
            log.warning(
                f'Warning: Compilation of {f_root}{suffix} from source ' +
                f'directory {srcdir} to binary directory {bindir} timed out'
            )
            succeeded = False

    if not succeeded:
        log.debug('Command was:')
        log.debug(arglist_to_str(arglist))
        if res:
            log.debug(res.stdout.decode('utf-8'))
            log.debug(res.stderr.decode('utf-8'))

    return succeeded
Exemple #2
0
def compile_benchmark(bench):
    """Compile the benchmark, "bench".

       Return True if all files compile successfully, False otherwise."""
    abs_src_b = os.path.join(gp['benchdir'], bench)
    abs_bd_b = os.path.join(gp['bd_benchdir'], bench)
    succeeded = True

    if not os.path.isdir(abs_bd_b):
        try:
            os.makedirs(abs_bd_b)
        except PermissionError:
            log.warning(
                'Warning: Unable to create build directory for '
                + f'benchmark {bench}'
            )
            return False

    # Compile each file in the benchmark
    for filename in os.listdir(abs_src_b):
        f_root, ext = os.path.splitext(filename)
        if ext == '.c':
            succeeded &= compile_file(f_root, abs_src_b, abs_bd_b)

    return succeeded
def compile_support():
    """Compile all the support code.

       Return True if all files compile successfully, False otherwise."""
    succeeded = True

    # First the general support
    if not os.path.isdir(gp['bd_supportdir']):
        try:
            os.makedirs(gp['bd_supportdir'])
        except PermissionError:
            log.warning(
                'Warning: Unable to create support build directory '
                + f'{gp["bd_supportdir"]}'
            )
            return False

    # Compile each general support file in the benchmark
    succeeded &= compile_file('beebsc', gp['supportdir'], gp['bd_supportdir'])
    succeeded &= compile_file('main', gp['supportdir'], gp['bd_supportdir'])

    # Compile dummy files that are needed
    for dlib in gp['dummy_libs']:
        succeeded &= compile_file(
            'dummy-' + dlib, gp['supportdir'], gp['bd_supportdir']
        )

    # Compile architecture, chip and board specific files.  Note that we only
    # create the build directory if it is needed here.
    for dirtype in ['arch', 'chip', 'board']:
        # Support directory we are interested in
        dirname = gp[dirtype + 'dir']
        # List of files/subdirectories in that directory
        filelist = os.listdir(dirname)
        # Compile every C or assembler source file
        for filename in filelist:
            root, ext = os.path.splitext(filename)
            full_fn = os.path.join(dirname, filename)
            if (os.path.isfile(full_fn) and
                (ext == '.c' or ext == '.s' or ext == '.S')):
                # Create build directory
                builddir = gp['bd_' + dirtype + 'dir']
                if not os.path.isdir(builddir):
                    try:
                        os.makedirs(builddir)
                    except PermissionError:
                        log.warning(
                            'Warning: Unable to create build directory '
                            + f'for {dirname}, "{builddir}'
                        )
                        return False

                succeeded &= compile_file(root, dirname, builddir, suffix=ext)

    return succeeded
def create_link_binlist(abs_bd):
    """
    Create a list of all the binaries to be linked, including those in the
    specified absolute directory, abs_bd.  The binaries in this directory can
    be specified as relative filenames.  All others will all be absolute
    addresses, since ultimately we will link in the abs_bd directory.  Return
    the result binlist, or an empty list on failure.

    There is a nasty gotcha here. The ordering of files matters, since that is
    the order they will get packed into the executable, which in turn may
    affect branch distances. We therefore explicitly order files.
    """

    # Find the object files in alphabetical order
    binlist = []
    for binf in sorted(os.listdir(abs_bd), key=lambda objf: objf):
        if binf.endswith('.o'):
            binlist.extend(gp['ld_input_pattern'].format(binf).split())

    # Add arch, chip and board binaries
    for dirtype in ['arch', 'chip', 'board']:
        # Build directory
        bindir = gp['bd_{dirtype}dir'.format(dirtype=dirtype)]
        # List of files in the build directory in alphabetical order
        filelist = sorted(os.listdir(bindir), key=lambda objf: objf)
        # Add every object file
        for filename in filelist:
            root, ext = os.path.splitext(filename)
            binf = os.path.join(bindir, filename)
            if (os.path.isfile(binf) and (ext == '.o')):
                binlist.extend(gp['ld_input_pattern'].format(binf).split())

    # Add generic support
    for supp in ['main.o', 'beebsc.o']:
        binf = os.path.join(gp['bd_supportdir'], supp)
        if os.path.isfile(binf):
            binlist.extend(gp['ld_input_pattern'].format(binf).split())
        else:
            log.warning(
                'Warning: Unable to find support library {binf}'.format(
                    binf=binf))
            return []

    # Add dummy binaries. These must be sorted in alphabetical order
    for dlib in sorted(gp['dummy_libs'], key=lambda lib: lib):
        binf = os.path.join(gp['bd_supportdir'],
                            'dummy-{dlib}.o'.format(dlib=dlib))
        if os.path.isfile(binf):
            binlist.extend(gp['ld_input_pattern'].format(binf).split())
        else:
            log.warning('Warning: Unable to find dummy library {binf}'.format(
                binf=binf))
            return []

    return binlist
Exemple #5
0
def compile_support():
    """Compile all the support code.

       Return True if all files compile successfully, False otherwise."""
    succeeded = True

    # First the general support
    if not os.path.isdir(gp['bd_supportdir']):
        try:
            os.makedirs(gp['bd_supportdir'])
        except PermissionError:
            log.warning(
                'Warning: Unable to create support build directory '
                + f'{gp["bd_supportdir"]}'
            )
            return False

    # Compile each general support file in the benchmark
    succeeded &= compile_file('beebsc', gp['supportdir'], gp['bd_supportdir'])
    succeeded &= compile_file('main', gp['supportdir'], gp['bd_supportdir'])

    # Compile dummy files that are needed
    for dlib in gp['dummy_libs']:
        succeeded &= compile_file(
            'dummy-' + dlib, gp['supportdir'], gp['bd_supportdir']
        )

    # Compile architecture, chip and board specific files.  Note that we only
    # create the build directory if it is needed here.
    for dirname in ['arch', 'chip', 'board']:
        filename = os.path.join(gp[dirname + 'dir'], dirname + 'support.c')
        if os.path.isfile(filename):
            # Create build directory
            builddir = gp['bd_' + dirname + 'dir']
            if not os.path.isdir(builddir):
                try:
                    os.makedirs(builddir)
                except PermissionError:
                    log.warning(
                        'Warning: Unable to create build directory '
                        + f'for {dirname}, "{builddir}'
                    )
                    return False

            succeeded &= compile_file(
                dirname + 'support',
                gp[dirname + 'dir'],
                gp['bd_' + dirname + 'dir'],
            )

    return succeeded
def create_link_binlist(abs_bd):
    """Create a list of all the binaries to be linked, including those in the
       specified absolute directory, abs_bd.  The binaries in this directory
       can be specified as relative filenames.  All others will all be
       absolute addresses, since ultimately we will link in the abs_bd
       directory.  Return the result binlist, or an empty list on failure."""
    binlist = []
    for binf in os.listdir(abs_bd):
        if binf.endswith('.o'):
            binlist.extend(gp['ld_input_pattern'].format(binf).split())

    # Add arch, chip and board binaries
    for dirtype in ['arch', 'chip', 'board']:
        # Build directory
        bindir = gp[f'bd_{dirtype}dir']
        # List of files in the build directory
        filelist = os.listdir(bindir)
        # Add every object file
        for filename in filelist:
            root, ext = os.path.splitext(filename)
            binf = os.path.join(bindir, filename)
            if (os.path.isfile(binf) and (ext == '.o')):
                binlist.extend(
                    gp['ld_input_pattern'].format(binf).split()
                )

    # Add generic support
    for supp in ['main.o', 'beebsc.o']:
        binf = os.path.join(gp['bd_supportdir'], supp)
        if os.path.isfile(binf):
            binlist.extend(gp['ld_input_pattern'].format(binf).split())
        else:
            log.warning(f'Warning: Unable to find support library {binf}')
            return []

    # Add dummy binaries
    for dlib in gp['dummy_libs']:
        binf = os.path.join(gp['bd_supportdir'], f'dummy-{dlib}.o')
        if os.path.isfile(binf):
            binlist.extend(gp['ld_input_pattern'].format(binf).split())
        else:
            log.warning(f'Warning: Unable to find dummy library {binf}')
            return []

    return binlist
Exemple #7
0
def benchmark_speed(bench, target_args):
    """Time the benchmark.  "target_args" is a namespace of arguments
       specific to the target.  Result is a time in milliseconds, or zero on
       failure.

       For the parallel option, this method must be thread-safe."""
    succeeded = True
    appdir = os.path.join(gp['bd_benchdir'], bench)
    appexe = os.path.join(appdir, bench)

    if os.path.isfile(appexe):
        arglist = build_benchmark_cmd(bench, target_args)
        try:
            res = subprocess.run(
                arglist,
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE,
                cwd=appdir,
                timeout=gp['timeout'],
            )
            if res.returncode != 0:
                log.warning(f'Warning: Run of {bench} failed.')
                succeeded = False
        except subprocess.TimeoutExpired:
            log.warning(f'Warning: Run of {bench} timed out.')
            succeeded = False
    else:
        log.warning(f'Warning: {bench} executable not found.')
        succeeded = False

    # Process results
    if succeeded:
        exec_time = decode_results(res.stdout.decode('utf-8'),
                                   res.stderr.decode('utf-8'))
        succeeded = exec_time > 0

    if succeeded:
        return exec_time
    else:
        for arg in arglist:
            if arg == arglist[0]:
                comm = arg
            elif arg == '-ex':
                comm += ' ' + arg
            else:
                comm += " '" + arg + "'"

        log.debug('Args to subprocess:')
        log.debug(f'{comm}')
        if 'res' in locals():
            log.debug(res.stdout.decode('utf-8'))
            log.debug(res.stderr.decode('utf-8'))
        return 0.0
def link_benchmark(bench):
    """Link the benchmark, "bench".

       Return True if link is successful, False otherwise."""
    abs_bd_b = os.path.join(gp['bd_benchdir'], bench)

    if not os.path.isdir(abs_bd_b):
        log.warning(
            'Warning: Unable to find build directory for benchmark {bench}'.
            format(bench=bench))
        return False

    # Use a flag to track warnings, but keep going through warnings.
    succeeded = True

    # Create the argument list
    binlist = create_link_binlist(abs_bd_b)
    if not binlist:
        succeeded = False
    arglist = create_link_arglist(bench, binlist)

    # Run the link
    if gp['verbose']:
        log.debug('Linking in directory {abs_bd_b}'.format(abs_bd_b=abs_bd_b))
        log.debug(arglist_to_str(arglist))

    try:
        res = subprocess.run(
            arglist,
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
            cwd=abs_bd_b,
            timeout=gp['timeout'],
        )
        if res.returncode != 0:
            log.warning('Warning: Link of benchmark "{bench}" failed'.format(
                bench=bench))
            succeeded = False

        log.debug(res.stdout.decode('utf-8'))
        log.debug(res.stderr.decode('utf-8'))

    except subprocess.TimeoutExpired:
        log.warning('Warning: link of benchmark "{bench}" timed out'.format(
            bench=bench))
        succeeded = False

    if not succeeded:
        log.debug('In directory "' + abs_bd_b + '"')
        log.debug('Command was:')
        log.debug(arglist_to_str(arglist))

    return succeeded
Exemple #9
0
def link_benchmark(bench):
    """Link the benchmark, "bench".

       Return True if link is successful, False otherwise."""
    abs_bd_b = os.path.join(gp['bd_benchdir'], bench)

    if not os.path.isdir(abs_bd_b):
        log.warning(
            'Warning: Unable to find build directory for '
            + f'benchmark {bench}'
        )
        return False

    # Use a flag to track warnings, but keep going through warnings.
    succeeded = True

    # Create the argument list
    binlist = create_link_binlist(abs_bd_b)
    if not binlist:
        succeeded = False
    arglist = create_link_arglist(bench, binlist)

    # Run the link
    try:
        res = subprocess.run(
            arglist,
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
            cwd=abs_bd_b,
            timeout=300,
        )
        if res.returncode != 0:
            log.warning(f'Warning: Link of benchmark "{bench}" failed')
            succeeded = False
    except subprocess.TimeoutExpired:
        log.warning(f'Warning: link of benchmark "{bench}" timed out')
        succeeded = False

    if not succeeded:
        log.debug('Args to subprocess:')
        log.debug(f'{arglist}')
        log.debug(res.stdout.decode('utf-8'))
        log.debug(res.stderr.decode('utf-8'))

    return succeeded