Beispiel #1
0
 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)
Beispiel #2
0
    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
Beispiel #3
0
    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)
Beispiel #4
0
 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)]
Beispiel #5
0
    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()
Beispiel #6
0
    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)]
Beispiel #7
0
 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)]
Beispiel #8
0
    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")