Clone of official tools
Diff: toolchains/__init__.py
- Revision:
- 36:96847d42f010
- Parent:
- 35:da9c89f8be7d
- Child:
- 38:399953da035d
--- a/toolchains/__init__.py Wed Feb 15 13:53:18 2017 -0600 +++ b/toolchains/__init__.py Thu Jun 22 11:12:28 2017 -0500 @@ -215,7 +215,7 @@ # standard labels for the "TARGET_" and "TOOLCHAIN_" specific directories, but # had the knowledge of a list of these directories to be ignored. LEGACY_IGNORE_DIRS = set([ - 'LPC11U24', 'LPC1768', 'LPC2368', 'LPC4088', 'LPC812', 'KL25Z', + 'LPC11U24', 'LPC1768', 'LPC4088', 'LPC812', 'KL25Z', 'ARM', 'uARM', 'IAR', 'GCC_ARM', 'GCC_CS', 'GCC_CR', 'GCC_CW', 'GCC_CW_EWL', 'GCC_CW_NEWLIB', ]) @@ -252,11 +252,14 @@ MBED_CONFIG_FILE_NAME="mbed_config.h" + PROFILE_FILE_NAME = ".profile" + __metaclass__ = ABCMeta profile_template = {'common':[], 'c':[], 'cxx':[], 'asm':[], 'ld':[]} - def __init__(self, target, notify=None, macros=None, silent=False, extra_verbose=False, build_profile=None): + def __init__(self, target, notify=None, macros=None, silent=False, + extra_verbose=False, build_profile=None, build_dir=None): self.target = target self.name = self.__class__.__name__ @@ -295,12 +298,9 @@ self.build_all = False # Build output dir - self.build_dir = None + self.build_dir = build_dir self.timestamp = time() - # Output build naming based on target+toolchain combo (mbed 2.0 builds) - self.obj_path = join("TARGET_"+target.name, "TOOLCHAIN_"+self.name) - # Number of concurrent build jobs. 0 means auto (based on host system cores) self.jobs = 0 @@ -476,7 +476,7 @@ # This is a policy decision and it should /really/ be in the config system # ATM it's here for backward compatibility if ((("-g" in self.flags['common'] or "-g3" in self.flags['common']) and - "-O0") in self.flags['common'] or + "-O0" in self.flags['common']) or ("-r" in self.flags['common'] and "-On" in self.flags['common'])): self.labels['TARGET'].append("DEBUG") @@ -580,7 +580,8 @@ 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),"")): + if (self.is_ignored(join(relpath(root, base_path),"")) or + self.build_dir == join(relpath(root, base_path))): dirs[:] = [] continue @@ -613,6 +614,7 @@ break # Add root to include paths + root = root.rstrip("/") resources.inc_dirs.append(root) resources.file_basepath[root] = base_path @@ -773,7 +775,7 @@ # THIS METHOD IS BEING CALLED BY THE MBED ONLINE BUILD SYSTEM # ANY CHANGE OF PARAMETERS OR RETURN VALUES WILL BREAK COMPATIBILITY - def compile_sources(self, resources, build_path, inc_dirs=None): + def compile_sources(self, resources, inc_dirs=None): # Web IDE progress bar for project build files_to_compile = resources.s_sources + resources.c_sources + resources.cpp_sources self.to_be_compiled = len(files_to_compile) @@ -790,8 +792,6 @@ inc_paths = sorted(set(inc_paths)) # Unique id of all include paths self.inc_md5 = md5(' '.join(inc_paths)).hexdigest() - # Where to store response files - self.build_dir = build_path objects = [] queue = [] @@ -800,11 +800,13 @@ # Generate configuration header (this will update self.build_all if needed) self.get_config_header() + self.dump_build_profile() # Sort compile queue for consistency files_to_compile.sort() for source in files_to_compile: - object = self.relative_object_path(build_path, resources.file_basepath[source], source) + object = self.relative_object_path( + self.build_dir, resources.file_basepath[source], source) # Queue mode (multiprocessing) commands = self.compile_command(source, object, inc_paths) @@ -910,6 +912,13 @@ deps = self.parse_dependencies(dep_path) if (exists(dep_path)) else [] except IOError, IndexError: deps = [] + config_file = ([self.config.app_config_location] + if self.config.app_config_location else []) + deps.extend(config_file) + if ext == '.cpp' or self.COMPILE_C_AS_CPP: + deps.append(join(self.build_dir, self.PROFILE_FILE_NAME + "-cxx")) + else: + deps.append(join(self.build_dir, self.PROFILE_FILE_NAME + "-c")) if len(deps) == 0 or self.need_update(object, deps): if ext == '.cpp' or self.COMPILE_C_AS_CPP: return self.compile_cpp(source, object, includes) @@ -917,6 +926,7 @@ return self.compile_c(source, object, includes) elif ext == '.s': deps = [source] + deps.append(join(self.build_dir, self.PROFILE_FILE_NAME + "-asm")) if self.need_update(object, deps): return self.assemble(source, object, includes) else: @@ -959,7 +969,7 @@ def compile_output(self, output=[]): _rc = output[0] - _stderr = output[1] + _stderr = output[1].decode("utf-8") command = output[2] # Parse output for Warnings and Errors @@ -1005,16 +1015,20 @@ filename = name+'.'+ext elf = join(tmp_path, name + '.elf') - bin = join(tmp_path, filename) + bin = None if ext is 'elf' else join(tmp_path, filename) map = join(tmp_path, name + '.map') r.objects = sorted(set(r.objects)) - if self.need_update(elf, r.objects + r.libraries + [r.linker_script]): + config_file = ([self.config.app_config_location] + if self.config.app_config_location else []) + dependencies = r.objects + r.libraries + [r.linker_script] + config_file + dependencies.append(join(self.build_dir, self.PROFILE_FILE_NAME + "-ld")) + if self.need_update(elf, dependencies): needed_update = True self.progress("link", name) self.link(elf, r.objects, r.libraries, r.lib_dirs, r.linker_script) - if self.need_update(bin, [elf]): + if bin and self.need_update(bin, [elf]): needed_update = True self.progress("elf2bin", name) self.binary(r, elf, bin) @@ -1157,6 +1171,22 @@ self.config_processed = True return self.config_file + def dump_build_profile(self): + """Dump the current build profile and macros into the `.profile` file + in the build directory""" + for key in ["cxx", "c", "asm", "ld"]: + to_dump = (str(self.flags[key]) + str(sorted(self.macros))) + if key in ["cxx", "c"]: + to_dump += str(self.flags['common']) + where = join(self.build_dir, self.PROFILE_FILE_NAME + "-" + key) + self._overwrite_when_not_equal(where, to_dump) + + @staticmethod + def _overwrite_when_not_equal(filename, content): + if not exists(filename) or content != open(filename).read(): + with open(filename, "wb") as out: + out.write(content) + @staticmethod def generic_check_executable(tool_key, executable_name, levels_up, nested_dir=None): @@ -1345,31 +1375,87 @@ """ raise NotImplemented + @staticmethod + @abstractmethod + def name_mangle(name): + """Mangle a name based on the conventional name mangling of this toolchain + + Positional arguments: + name -- the name to mangle + + Return: + the mangled name as a string + """ + raise NotImplemented + + @staticmethod + @abstractmethod + def make_ld_define(name, value): + """Create an argument to the linker that would define a symbol + + Positional arguments: + name -- the symbol to define + value -- the value to give the symbol + + Return: + The linker flag as a string + """ + raise NotImplemented + + @staticmethod + @abstractmethod + def redirect_symbol(source, sync, build_dir): + """Redirect a symbol at link time to point at somewhere else + + Positional arguments: + source -- the symbol doing the pointing + sync -- the symbol being pointed to + build_dir -- the directory to put "response files" if needed by the toolchain + + Side Effects: + Possibly create a file in the build directory + + Return: + The linker flag to redirect the symbol, as a string + """ + raise NotImplemented + # 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 [] + @property + def report(self): + to_ret = {} + to_ret['c_compiler'] = {'flags': copy(self.flags['c']), + 'symbols': self.get_symbols()} + to_ret['cxx_compiler'] = {'flags': copy(self.flags['cxx']), + 'symbols': self.get_symbols()} + to_ret['assembler'] = {'flags': copy(self.flags['asm']), + 'symbols': self.get_symbols(True)} + to_ret['linker'] = {'flags': copy(self.flags['ld'])} + to_ret.update(self.config.report) + return to_ret + from tools.settings import ARM_PATH -from tools.settings import GCC_ARM_PATH, GCC_CR_PATH +from tools.settings import GCC_ARM_PATH from tools.settings import IAR_PATH TOOLCHAIN_PATHS = { 'ARM': ARM_PATH, 'uARM': ARM_PATH, 'GCC_ARM': GCC_ARM_PATH, - 'GCC_CR': GCC_CR_PATH, 'IAR': IAR_PATH } from tools.toolchains.arm import ARM_STD, ARM_MICRO -from tools.toolchains.gcc import GCC_ARM, GCC_CR +from tools.toolchains.gcc import GCC_ARM from tools.toolchains.iar import IAR TOOLCHAIN_CLASSES = { 'ARM': ARM_STD, 'uARM': ARM_MICRO, 'GCC_ARM': GCC_ARM, - 'GCC_CR': GCC_CR, 'IAR': IAR }