def test_dirs_exclusion_from_file_to_compile(self): """Test that dirs can be excluded from the build.""" files_to_compile = [ FileRef( name="platform/TARGET_CORTEX_M/TOOLCHAIN_ARM/except.S", path="./platform/TARGET_CORTEX_M/TOOLCHAIN_ARM/except.S", ), FileRef( name= "rtos/TARGET_CORTEX/rtx5/RTX/Source/TOOLCHAIN_ARM/TARGET_RTOS_M4_M7/targets_irq_cm4f.S", path= "./rtos/TARGET_CORTEX/rtx5/RTX/Source/TOOLCHAIN_ARM/TARGET_RTOS_M4_M7/targets_irq_cm4f.S", ), ] exclude_dirs = ["platform/", "drivers/", "targets/"] expected_compilation_queue = [ FileRef( name= "rtos/TARGET_CORTEX/rtx5/RTX/Source/TOOLCHAIN_ARM/TARGET_RTOS_M4_M7/targets_irq_cm4f.S", path= "./rtos/TARGET_CORTEX/rtx5/RTX/Source/TOOLCHAIN_ARM/TARGET_RTOS_M4_M7/targets_irq_cm4f.S", ) ] compilation_queue = mbedToolchain._exclude_files_from_build( files_to_compile, exclude_dirs) self.assertEqual(compilation_queue, expected_compilation_queue)
def get_link_command( self, output, objects, libraries, lib_dirs, scatter_file ): base, _ = splitext(output) map_file = base + ".map" args = ["-o", output, "--info=totals", "--map", "--list=%s" % map_file] args.extend(objects) args.extend(libraries) if lib_dirs: args.extend(["--userlibpath", ",".join(lib_dirs)]) if scatter_file: scatter_name = relpath(scatter_file) new_scatter = self.correct_scatter_shebang(FileRef(scatter_name, scatter_file)) args.extend(["--scatter", new_scatter.path]) cmd = self.ld + args if self.RESPONSE_FILES: cmd_linker = cmd[0] link_files = self.get_link_file(cmd[1:]) cmd = [cmd_linker, '--via', link_files] return cmd
def correct_scatter_shebang(self, sc_fileref, cur_dir_name=None): """Correct the shebang at the top of a scatter file. Positional arguments: sc_fileref -- FileRef object of the scatter file Keyword arguments: cur_dir_name -- the name (not path) of the directory containing the scatter file Return: The FileRef of the correct scatter file Side Effects: This method MAY write a new scatter file to disk """ with open(sc_fileref.path, "r") as input: lines = input.readlines() if (lines[0].startswith(self.SHEBANG) or not lines[0].startswith("#!")): return sc_fileref else: new_scatter = join(self.build_dir, ".link_script.sct") if cur_dir_name is None: cur_dir_name = dirname(sc_fileref.path) self.SHEBANG += " -I %s" % cur_dir_name if self.need_update(new_scatter, [sc_fileref.path]): with open(new_scatter, "w") as out: out.write(self.SHEBANG) out.write("\n") out.write("".join(lines[1:])) return FileRef(".link_script.sct", new_scatter)
def gen_file(self, template_file, data, target_file, **kwargs): """Generates a project file from a template using jinja""" target_text = self._gen_file_inner(template_file, data, target_file, **kwargs) target_path = self.gen_file_dest(target_file) mkdir(dirname(target_path)) logging.debug("Generating: %s", target_path) open(target_path, "w").write(target_text) self.generated_files += [FileRef(target_file, target_path)]
def __init__(self, target, export_dir, project_name, toolchain, zip, extra_symbols=None, resources=None): """Initialize an instance of class exporter Positional arguments: target - the target mcu/board for this project export_dir - the directory of the exported project files project_name - the name of the project toolchain - an instance of class toolchain zip - True if the exported project will be zipped Keyword arguments: extra_symbols - a list of extra macros for the toolchain resources - an instance of class Resources """ self.export_dir = export_dir self.target = target self.project_name = project_name self.toolchain = toolchain jinja_loader = FileSystemLoader( os.path.dirname(os.path.abspath(__file__))) self.jinja_environment = Environment(loader=jinja_loader) resources.win_to_unix() self.resources = resources self.zip = zip self.generated_files = [] getting_started_name = "GettingStarted.html" dot_mbed_name = ".mbed" self.static_files = ( FileRef(getting_started_name, join(self.TEMPLATE_DIR, getting_started_name)), FileRef(dot_mbed_name, join(self.TEMPLATE_DIR, dot_mbed_name)), ) self.builder_files_dict = {} self.add_config()
def _gen_file_inner(self, template_file, data, target_file, **kwargs): """Generates a project file from a template using jinja""" jinja_loader = FileSystemLoader( os.path.dirname(os.path.abspath(__file__))) jinja_environment = Environment(loader=jinja_loader, undefined=StrictUndefined, **kwargs) template = jinja_environment.get_template(template_file) target_text = template.render(data) return target_text target_path = join(self.export_dir, target_file) logging.debug("Generating: %s", target_path) open(target_path, "w").write(target_text) self.generated_files += [FileRef(target_file, target_path)]
def gen_file_nonoverwrite(self, template_file, data, target_file, **kwargs): """Generates or selectively appends a project file from a template""" target_text = self._gen_file_inner(template_file, data, target_file, **kwargs) target_path = self.gen_file_dest(target_file) if exists(target_path): with open(target_path) as fdin: old_lines_set = set(fdin.read().splitlines()) target_set = set(target_text.splitlines()) to_append = target_set - old_lines_set if len(to_append) > 0: with open(target_path, "a") as fdout: fdout.write("\n".join(to_append)) else: logging.debug("Generating: %s", target_path) open(target_path, "w").write(target_text) self.generated_files += [FileRef(template_file, target_path)]
def correct_scatter_shebang(self, sc_fileref, cur_dir_name=None): """Correct the shebang at the top of a scatter file. The shebang line is the line at the top of the file starting with '#!'. If this line is present then the linker will execute the command on that line on the content of the scatter file prior to consuming the content into the link. Typically the shebang line will contain an instruction to run the C-preprocessor (either 'armcc -E' or 'armclang -E') which allows for macro expansion, inclusion of headers etc. Other options are passed to the preprocessor to specify aspects of the system such as the processor architecture and cpu type. The build system (at this point) will have constructed what it considers to be a correct shebang line for this build. If this differs from the line in the scatter file then the scatter file will be rewritten by this function to contain the build-system-generated shebang line. Note that the rewritten file will be placed in the BUILD output directory. Include processing If the scatter file runs the preprocessor, and contains #include statements then the pre-processor include path specifies where the #include files are to be found. Typically, #include files are specified with a path relative to the location of the original scatter file. When the preprocessor runs, the system automatically passes the location of the scatter file into the include path through an implicit '-I' option to the preprocessor, and this works fine in the offline build system. Unfortunately this approach does not work in the online build, because the preprocessor command runs in a chroot. The true (non-chroot) path to the file as known by the build system looks something like this: /tmp/chroots/ch-eefd72fb-2bcb-4e99-9043-573d016618bb/extras/mbed-os.lib/... whereas the path known by the preprocessor will be: /extras/mbed-os.lib/... Consequently, the chroot path has to be explicitly passed to the preprocessor through an explicit -I/path/to/chroot/file option in the shebang line. *** THERE IS AN ASSUMPTION THAT THE CHROOT PATH IS THE REAL FILE PATH WITH THE FIRST *** THREE ELEMENTS REMOVED. THIS ONLY HOLDS TRUE UNTIL THE ONLINE BUILD SYSTEM CHANGES If the include path manipulation as described above does change, then any scatter file containing a #include statement is likely to fail on the online compiler. Positional arguments: sc_fileref -- FileRef object of the scatter file Keyword arguments: cur_dir_name -- the name (not path) of the directory containing the scatter file Return: The FileRef of the correct scatter file Side Effects: This method MAY write a new scatter file to disk """ with open(sc_fileref.path, "r") as input: lines = input.readlines() # If the existing scatter file has no shebang line, or the line that it does have # matches the desired line then the existing scatter file is used directly without rewriting. if (lines[0].startswith(self.SHEBANG) or not lines[0].startswith("#!")): return sc_fileref new_scatter = join(self.build_dir, ".link_script.sct") if cur_dir_name is None: cur_dir_name = dirname(sc_fileref.path) # For a chrooted system, adjust the path to the scatter file to be a valid # chroot location by removing the first three elements of the path. if cur_dir_name.startswith("/tmp/chroots"): cur_dir_name = sep + join(*(cur_dir_name.split(sep)[4:])) # Add the relocated scatter file path to the include path. self.SHEBANG += " -I%s" % cur_dir_name # Only rewrite if doing a full build... if self.need_update(new_scatter, [sc_fileref.path]): with open(new_scatter, "w") as out: # Write the new shebang line... out.write(self.SHEBANG + "\n") # ...followed by the unmolested remaining content from the original scatter file. out.write("".join(lines[1:])) return FileRef(".link_script.sct", new_scatter)
# Not really a duplicate continue print( "DUPLICATE found: File %s is not unique! It could be one of: %s" % (filename, " ".join(dupe_paths))) for dupe_path in dupe_paths: if os.path.commonpath( [os.path.dirname(dupe_path), custom_target_dir]): # The file comes from the custom_target_dir - let it be continue print("\t-> Filtering out %s" % dupe_path) _, file_ext = os.path.splitext(dupe_path) file_type = resources._EXT.get(file_ext.lower()) resources._file_refs[file_type].discard( FileRef(dupe_path, dupe_path)) profile_toolchain.RESPONSE_FILES = False profile_toolchains.append(profile_toolchain) # Profiles seem to only set flags, so for the remaining operations we can use any toolchain toolchain = profile_toolchains[0] print("Generated config header: " + toolchain.get_config_header()) print("Using settings from these JSON files:\n " + "\n ".join(resources.get_file_paths(FileType.JSON))) # Write target header # ------------------------------------------------------------------------- target_header_path = os.path.join(config_header_dir, "mbed_target_config.h")