#!/usr/bin/env python3 import os import common class BaremetalComponent(common.Component): def do_build(self, args): common.assert_crosstool_ng_supports_arch(kwargs['arch']) build_dir = self.get_build_dir(args) bootloader_obj = os.path.join(kwargs['baremetal_build_lib_dir'], 'bootloader{}'.format(kwargs['obj_ext'])) common_basename_noext = 'common' common_src = os.path.join(kwargs['root_dir'], common_basename_noext + kwargs['c_ext']) common_obj = os.path.join(kwargs['baremetal_build_lib_dir'], common_basename_noext + kwargs['obj_ext']) syscalls_basename_noext = 'syscalls' syscalls_src = os.path.join(kwargs['baremetal_src_lib_dir'], syscalls_basename_noext + kwargs['c_ext']) syscalls_obj = os.path.join(kwargs['baremetal_build_lib_dir'], syscalls_basename_noext + kwargs['obj_ext']) common_objs = [common_obj, syscalls_obj] cflags = [ '-I', kwargs['baremetal_src_lib_dir'], LF, '-I', kwargs['root_dir'], LF, '-O0', LF, '-ggdb3', LF, '-mcpu={}'.format(kwargs['mcpu']), LF, '-nostartfiles', LF, ] if kwargs['prebuilt']: gcc = 'arm-none-eabi-gcc' else: os.environ['PATH'] = kwargs['crosstool_ng_bin_dir'] + os.environ['PATH'] gcc = common.get_toolchain_tool('gcc', allowed_toolchains=['crosstool-ng']) if kwargs['emulator'] == 'gem5': if kwargs['machine'] == 'VExpress_GEM5_V1': entry_address = 0x80000000 uart_address = 0x1c090000 elif kwargs['machine'] == 'RealViewPBX': entry_address = 0x10000 uart_address = 0x10009000 else: raise Exception('unknown machine: ' + kwargs['machine']) cflags.extend(['-D', 'GEM5'.format(uart_address), LF]) else: entry_address = 0x40000000 uart_address = 0x09000000 os.makedirs(build_dir, exist_ok=True) os.makedirs(kwargs['baremetal_build_lib_dir'], exist_ok=True) src = os.path.join(kwargs['baremetal_src_lib_dir'], '{}{}'.format(kwargs['arch'], kwargs['asm_ext'])) if common.need_rebuild([src], bootloader_obj): self.sh.run_cmd( [gcc, LF] + cflags + [ '-c', LF, '-o', bootloader_obj, LF, src, LF, ] ) for src, obj in [ (common_src, common_obj), (syscalls_src, syscalls_obj), ]: if common.need_rebuild([src], obj): self.sh.run_cmd( [gcc, LF] + cflags + [ '-c', LF, '-D', 'UART0_ADDR={:#x}'.format(uart_address), LF, '-o', obj, LF, src, LF, ] ) self._build_dir( '', gcc=gcc, cflags=cflags, entry_address=entry_address, bootloader_obj=bootloader_obj, common_objs=common_objs, ) self._build_dir( 'interactive', gcc=gcc, cflags=cflags, entry_address=entry_address, bootloader_obj=bootloader_obj, common_objs=common_objs, ) arch_dir = os.path.join('arch', kwargs['arch']) if os.path.isdir(os.path.join(kwargs['baremetal_src_dir'], arch_dir)): self._build_dir( arch_dir, gcc=gcc, cflags=cflags, entry_address=entry_address, bootloader_obj=bootloader_obj, common_objs=common_objs, ) arch_dir = os.path.join('arch', kwargs['arch'], 'no_bootloader') if os.path.isdir(os.path.join(kwargs['baremetal_src_dir'], arch_dir)): self._build_dir( arch_dir, gcc=gcc, cflags=cflags, entry_address=entry_address, bootloader_obj=bootloader_obj, common_objs=common_objs, bootloader=False, ) def get_argparse_args(self): return { 'description': '''\ Build the baremetal examples with crosstool-NG. ''' } def get_build_dir(self, args): return kwargs['baremetal_build_dir'] def get_default_args(self): return {'baremetal': 'all'} def _build_dir( self, subpath, gcc, cflags, entry_address, bootloader_obj, common_objs, bootloader=True ): """ Build all .c and .S files in a given subpath of the baremetal source directory non recursively. Place outputs on the same subpath or the output directory. """ in_dir = os.path.join(kwargs['baremetal_src_dir'], subpath) out_dir = os.path.join(kwargs['baremetal_build_dir'], subpath) os.makedirs(out_dir, exist_ok=True) common_objs = common_objs.copy() if bootloader: common_objs.append(bootloader_obj) for in_basename in os.listdir(in_dir): in_path = os.path.join(in_dir, in_basename) if os.path.isfile(in_path) and os.path.splitext(in_basename)[1] in (kwargs['c_ext'], kwargs['asm_ext']): in_name = os.path.splitext(in_basename)[0] main_obj = os.path.join(kwargs['baremetal_build_dir'], subpath, '{}{}'.format(in_name, kwargs['obj_ext'])) src = os.path.join(kwargs['baremetal_src_dir'], in_path) if common.need_rebuild([src], main_obj): self.sh.run_cmd( [gcc, LF] + cflags + [ '-c', LF, '-o', main_obj, LF, src, LF, ] ) objs = common_objs + [main_obj] out = os.path.join(kwargs['baremetal_build_dir'], subpath, in_name + kwargs['baremetal_build_ext']) link_script = os.path.join(kwargs['baremetal_src_dir'], 'link.ld') if common.need_rebuild(objs + [link_script], out): self.sh.run_cmd( [gcc, LF] + cflags + [ '-Wl,--section-start=.text={:#x}'.format(entry_address), LF, '-o', out, LF, '-T', link_script, LF, ] + self.sh.add_newlines(objs) ) if __name__ == '__main__': BaremetalComponent().build()