Clone of official tools
Diff: toolchains/__init__.py
- Revision:
- 40:7d3fa6b99b2b
- Parent:
- 38:399953da035d
- Child:
- 41:2a77626a4c21
--- a/toolchains/__init__.py Wed Jul 19 16:44:30 2017 -0500 +++ b/toolchains/__init__.py Tue Oct 10 16:56:30 2017 -0500 @@ -26,7 +26,6 @@ from itertools import chain from inspect import getmro from copy import deepcopy -from tools.config import Config from abc import ABCMeta, abstractmethod from distutils.spawn import find_executable @@ -116,8 +115,9 @@ self.eager = {} class Resources: - def __init__(self, base_path=None): + def __init__(self, base_path=None, collect_ignores=False): self.base_path = base_path + self.collect_ignores = collect_ignores self.file_basepath = {} @@ -148,6 +148,7 @@ # Features self.features = LazyDict() + self.ignored_dirs = [] def __add__(self, resources): if resources is None: @@ -161,6 +162,10 @@ else: return self.add(resources) + def ignore_dir(self, directory): + if self.collect_ignores: + self.ignored_dirs.append(directory) + def add(self, resources): for f,p in resources.file_basepath.items(): self.file_basepath[f] = p @@ -190,6 +195,7 @@ self.json_files += resources.json_files self.features.update(resources.features) + self.ignored_dirs += resources.ignored_dirs return self @@ -295,11 +301,13 @@ 'LPC11U24', 'LPC1768', 'LPC2368', 'LPC4088', 'LPC812', 'KL25Z', 'ARM', 'uARM', 'IAR', 'GCC_ARM', 'GCC_CS', 'GCC_CR', 'GCC_CW', 'GCC_CW_EWL', 'GCC_CW_NEWLIB', + 'ARMC6' ]) LEGACY_TOOLCHAIN_NAMES = { 'ARM_STD':'ARM', 'ARM_MICRO': 'uARM', 'GCC_ARM': 'GCC_ARM', 'GCC_CR': 'GCC_CR', 'IAR': 'IAR', + 'ARMC6': 'ARMC6', } @@ -325,6 +333,10 @@ "Cortex-M7F" : ["__CORTEX_M7", "ARM_MATH_CM7", "__FPU_PRESENT=1", "__CMSIS_RTOS", "__MBED_CMSIS_RTOS_CM"], "Cortex-M7FD" : ["__CORTEX_M7", "ARM_MATH_CM7", "__FPU_PRESENT=1", "__CMSIS_RTOS", "__MBED_CMSIS_RTOS_CM"], "Cortex-A9" : ["__CORTEX_A9", "ARM_MATH_CA9", "__FPU_PRESENT", "__CMSIS_RTOS", "__EVAL", "__MBED_CMSIS_RTOS_CA9"], + "Cortex-M23-NS": ["__CORTEX_M23", "ARM_MATH_ARMV8MBL", "__DOMAIN_NS=1", "__CMSIS_RTOS", "__MBED_CMSIS_RTOS_CM"], + "Cortex-M23": ["__CORTEX_M23", "ARM_MATH_ARMV8MBL", "__CMSIS_RTOS", "__MBED_CMSIS_RTOS_CM"], + "Cortex-M33-NS": ["__CORTEX_M33", "ARM_MATH_ARMV8MML", "__DOMAIN_NS=1", "__FPU_PRESENT", "__CMSIS_RTOS", "__MBED_CMSIS_RTOS_CM"], + "Cortex-M33": ["__CORTEX_M33", "ARM_MATH_ARMV8MML", "__FPU_PRESENT", "__CMSIS_RTOS", "__MBED_CMSIS_RTOS_CM"], } MBED_CONFIG_FILE_NAME="mbed_config.h" @@ -409,7 +421,6 @@ # Print output buffer self.output = str() - self.map_outputs = list() # Place to store memmap scan results in JSON like data structures # uVisor spepcific rules if 'UVISOR' in self.target.features and 'UVISOR_SUPPORTED' in self.target.extra_labels: @@ -578,13 +589,13 @@ # information about the library paths. Safe option: assume an update if not d or not exists(d): return True - + if not self.stat_cache.has_key(d): self.stat_cache[d] = stat(d).st_mtime if self.stat_cache[d] >= target_mod_time: return True - + return False def is_ignored(self, file_path): @@ -612,10 +623,11 @@ # The parameter *base_path* is used to set the base_path attribute of the Resources # object and the parameter *exclude_paths* is used by the directory traversal to # exclude certain paths from the traversal. - def scan_resources(self, path, exclude_paths=None, base_path=None): + def scan_resources(self, path, exclude_paths=None, base_path=None, + collect_ignores=False): self.progress("scan", path) - resources = Resources(path) + resources = Resources(path, collect_ignores=collect_ignores) if not base_path: if isfile(path): base_path = dirname(path) @@ -656,8 +668,10 @@ self.add_ignore_patterns(root, base_path, lines) # Skip the whole folder if ignored, e.g. .mbedignore containing '*' - if (self.is_ignored(join(relpath(root, base_path),"")) or - self.build_dir == join(relpath(root, base_path))): + root_path =join(relpath(root, base_path)) + if (self.is_ignored(join(root_path,"")) or + self.build_dir == root_path): + resources.ignore_dir(root_path) dirs[:] = [] continue @@ -676,18 +690,22 @@ self.is_ignored(join(relpath(root, base_path), d,"")) or # Ignore TESTS dir (d == 'TESTS')): + resources.ignore_dir(dir_path) dirs.remove(d) elif d.startswith('FEATURE_'): # Recursively scan features but ignore them in the current scan. # These are dynamically added by the config system if the conditions are matched def closure (dir_path=dir_path, base_path=base_path): - return self.scan_resources(dir_path, base_path=base_path) + return self.scan_resources(dir_path, base_path=base_path, + collect_ignores=resources.collect_ignores) resources.features.add_lazy(d[8:], closure) + resources.ignore_dir(dir_path) dirs.remove(d) elif exclude_paths: for exclude_path in exclude_paths: rel_path = relpath(dir_path, exclude_path) if not (rel_path.startswith('..')): + resources.ignore_dir(dir_path) dirs.remove(d) break @@ -818,7 +836,7 @@ c = c.replace("\\", "/") if self.CHROOT: c = c.replace(self.CHROOT, '') - cmd_list.append('-I%s' % c) + cmd_list.append('"-I%s"' % c) string = " ".join(cmd_list) f.write(string) return include_file @@ -838,7 +856,7 @@ string = " ".join(cmd_list) f.write(string) return link_file - + # Generate response file for all objects when archiving. # ARM, GCC, IAR cross compatible def get_arch_file(self, objects): @@ -863,7 +881,10 @@ inc_paths = resources.inc_dirs if inc_dirs is not None: - inc_paths.extend(inc_dirs) + if isinstance(inc_dirs, list): + inc_paths.extend(inc_dirs) + else: + inc_paths.append(inc_dirs) # De-duplicate include paths inc_paths = set(inc_paths) # Sort include paths for consistency @@ -1012,7 +1033,6 @@ return None - @abstractmethod def parse_dependencies(self, dep_path): """Parse the dependency information generated by the compiler. @@ -1024,8 +1044,21 @@ Side effects: None + + Note: A default implementation is provided for make-like file formats """ - raise NotImplemented + dependencies = [] + buff = open(dep_path).readlines() + if buff: + buff[0] = re.sub('^(.*?)\: ', '', buff[0]) + for line in buff: + filename = line.replace('\\\n', '').strip() + if file: + filename = filename.replace('\\ ', '\a') + dependencies.extend(((self.CHROOT if self.CHROOT else '') + + f.replace('\a', ' ')) + for f in filename.split(" ")) + return list(filter(None, dependencies)) def is_not_supported_error(self, output): return "#error directive: [NOT_SUPPORTED]" in output @@ -1111,7 +1144,8 @@ self.progress("elf2bin", name) self.binary(r, elf, bin) - self.map_outputs = self.mem_stats(map) + # Initialize memap and process map file. This doesn't generate output. + self.mem_stats(map) self.var("compile_succeded", True) self.var("binary", filename) @@ -1176,8 +1210,7 @@ def mem_stats(self, map): """! Creates parser object @param map Path to linker map file to parse and decode - @return Memory summary structure with memory usage statistics - None if map file can't be opened and processed + @return None """ toolchain = self.__class__.__name__ @@ -1192,10 +1225,10 @@ # Store the memap instance for later use self.memap_instance = memap - # Here we return memory statistics structure (constructed after - # call to generate_output) which contains raw data in bytes - # about sections + summary - return memap.mem_report + # Note: memory statistics are not returned. + # Need call to generate_output later (depends on depth & output format) + + return None # Set the configuration data def set_config_data(self, config_data): @@ -1223,7 +1256,7 @@ else: prev_data = None # Get the current configuration data - crt_data = Config.config_to_header(self.config_data) if self.config_data else None + crt_data = self.config.config_to_header(self.config_data) if self.config_data else None # "changed" indicates if a configuration change was detected changed = False if prev_data is not None: # a previous mbed_config.h exists @@ -1327,6 +1360,25 @@ raise NotImplemented @abstractmethod + def get_compile_options(self, defines, includes, for_asm=False): + """Generate the compiler options from the defines and includes + + Positional arguments: + defines -- The preprocessor macros defined on the command line + includes -- The include file search paths + + Keyword arguments: + for_asm -- generate the assembler options instead of the compiler options + + Return value: + A list of the command line arguments that will force the inclusion the specified header + + Side effects: + None + """ + raise NotImplemented + + @abstractmethod def assemble(self, source, object, includes): """Generate the command line that assembles. @@ -1500,7 +1552,7 @@ # Return the list of macros geenrated by the build system def get_config_macros(self): - return Config.config_to_macros(self.config_data) if self.config_data else [] + return self.config.config_to_macros(self.config_data) if self.config_data else [] @property def report(self): @@ -1515,24 +1567,24 @@ to_ret.update(self.config.report) return to_ret -from tools.settings import ARM_PATH -from tools.settings import GCC_ARM_PATH -from tools.settings import IAR_PATH +from tools.settings import ARM_PATH, ARMC6_PATH, GCC_ARM_PATH, IAR_PATH TOOLCHAIN_PATHS = { 'ARM': ARM_PATH, 'uARM': ARM_PATH, + 'ARMC6': ARMC6_PATH, 'GCC_ARM': GCC_ARM_PATH, 'IAR': IAR_PATH } -from tools.toolchains.arm import ARM_STD, ARM_MICRO +from tools.toolchains.arm import ARM_STD, ARM_MICRO, ARMC6 from tools.toolchains.gcc import GCC_ARM from tools.toolchains.iar import IAR TOOLCHAIN_CLASSES = { 'ARM': ARM_STD, 'uARM': ARM_MICRO, + 'ARMC6': ARMC6, 'GCC_ARM': GCC_ARM, 'IAR': IAR }