def copy_include_dirs(tile): """Copy all include directories that this tile defines as products in build/output/include """ if 'products' not in tile.settings: return incdirs = tile.settings['products'].get('include_directories', []) incdirs = map(lambda x: os.path.normpath(utilities.join_path(x)), incdirs) incdirs = sorted(incdirs, key=lambda x: len(x)) seen_dirs = pygtrie.PrefixSet( factory=lambda: pygtrie.StringTrie(separator=os.path.sep)) env = Environment(tools=[]) # all include directories are relative to the firmware/src directory outputbase = os.path.join('build', 'output', 'include') inputbase = os.path.join('firmware', 'src') for inc in incdirs: if inc in seen_dirs: continue relinput = os.path.join(inputbase, inc) finaldir = os.path.join(outputbase, inc) for folder, subdirs, filenames in os.walk(relinput): relfolder = os.path.relpath(folder, relinput) for filename in filenames: if filename.endswith(".h"): infile = os.path.join(folder, filename) outfile = os.path.join(finaldir, relfolder, filename) env.Command([outfile], [infile], Copy("$TARGET", "$SOURCE")) seen_dirs.add(inc)
def build_program(tile, elfname, chip, patch=True): """ Build an ARM cortex executable """ dirs = chip.build_dirs() output_name = '%s_%s.elf' % ( elfname, chip.arch_name(), ) output_binname = '%s_%s.bin' % ( elfname, chip.arch_name(), ) patched_name = '%s_%s_patched.elf' % ( elfname, chip.arch_name(), ) patchfile_name = '%s_%s_patchcommand.txt' % ( elfname, chip.arch_name(), ) map_name = '%s_%s.map' % ( elfname, chip.arch_name(), ) VariantDir(dirs['build'], os.path.join('firmware', 'src'), duplicate=0) prog_env = setup_environment(chip) prog_env['OUTPUT'] = output_name prog_env['BUILD_DIR'] = dirs['build'] prog_env['OUTPUT_PATH'] = os.path.join(dirs['build'], output_name) prog_env['OUTPUTBIN'] = os.path.join(dirs['build'], output_binname) prog_env['PATCHED'] = os.path.join(dirs['build'], patched_name) prog_env['PATCH_FILE'] = os.path.join(dirs['build'], patchfile_name) prog_env['PATCH_FILENAME'] = patchfile_name prog_env['MODULE'] = elfname #Setup all of our dependencies and make sure our output depends on them being built tilebus_defs = setup_dependencies(tile, prog_env) #Setup specific linker flags for building a program ##Specify the linker script ###We can find a linker script in one of two places, either in a dependency or in an explicit 'linker' property ###First check for a linker script in our dependencies ldscripts = list( itertools.chain( *[x.linker_scripts() for x in prog_env['DEPENDENCIES']])) # Make sure we don't have multiple linker scripts coming in from dependencies if len(ldscripts) > 1: raise BuildError( "Multiple linker scripts included from dependencies, at most one may be included", linker_scripts=ldscripts) #Make sure we don't have a linker script from a dependency and explicity specified if len(ldscripts) == 1 and chip.property('linker', None) != None: raise BuildError( "Linker script specified in dependency and explicitly in module_settings", explicit_script=chip.property('linker'), dependency_script=ldscripts[0]) if len(ldscripts) == 1: ldscript = ldscripts[0] else: ldscript = utilities.join_path(chip.property('linker')) #Find the linker script directory in case it includes other linker scripts in the same directory lddir = os.path.abspath(os.path.dirname(ldscript)) prog_env['LIBPATH'] += [lddir] prog_env['LINKFLAGS'].append('-T"%s"' % ldscript) ##Specify the output map file prog_env['LINKFLAGS'].extend( ['-Xlinker', '-Map="%s"' % os.path.join(dirs['build'], map_name)]) Clean(os.path.join(dirs['build'], output_name), [os.path.join(dirs['build'], map_name)]) #Compile the TileBus command and config variable definitions #Try to use the modern 'tilebus' directory or the old 'cdb' directory tbname = os.path.join('firmware', 'src', 'tilebus', prog_env["MODULE"] + ".bus") if not os.path.exists(tbname): tbname = os.path.join('firmware', 'src', 'cdb', prog_env["MODULE"] + ".cdb") compile_tilebus(tilebus_defs + [tbname], prog_env) #Compile an elf for the firmware image objs = SConscript(os.path.join(dirs['build'], 'SConscript'), exports='prog_env') outfile = prog_env.Program(os.path.join(dirs['build'], prog_env['OUTPUT']), objs) if patch: #Create a patched ELF including a proper checksum ## First create a binary dump of the program flash outbin = prog_env.Command( prog_env['OUTPUTBIN'], os.path.join(dirs['build'], prog_env['OUTPUT']), "arm-none-eabi-objcopy -O binary $SOURCES $TARGET") ## Now create a command file containing the linker command needed to patch the elf outhex = prog_env.Command(prog_env['PATCH_FILE'], outbin, action=prog_env.Action( checksum_creation_action, "Generating checksum file")) ## Next relink a new version of the binary using that patch file to define the image checksum patch_env = prog_env.Clone() patch_env['LINKFLAGS'].append( ['-Xlinker', '@%s' % patch_env['PATCH_FILE']]) patched_file = patch_env.Program(prog_env['PATCHED'], objs) patch_env.Depends(patched_file, [ os.path.join(dirs['build'], output_name), patch_env['PATCH_FILE'] ]) prog_env.Depends(os.path.join(dirs['build'], output_name), [ldscript]) prog_env.InstallAs(os.path.join(dirs['output'], output_name), os.path.join(dirs['build'], patched_name)) else: prog_env.InstallAs(os.path.join(dirs['output'], output_name), outfile) prog_env.InstallAs(os.path.join(dirs['output'], map_name), os.path.join(dirs['build'], map_name)) return os.path.join(dirs['output'], output_name)