Clone of official tools

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
 }