Merge pull request #9738 from theotherjimmy/reorder-bl-hooks

Tools: Reoder post-build hooks and bl merging
pull/9956/head
Martin Kojtal 2019-03-06 13:02:45 +01:00 committed by GitHub
commit 9d72a5cf79
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 1733 additions and 1705 deletions

View File

@ -27,7 +27,6 @@ from os.path import join, exists, dirname, basename, abspath, normpath, splitext
from os.path import relpath
from os import linesep, remove, makedirs
from time import time
from intelhex import IntelHex
from json import load, dump
from jinja2 import FileSystemLoader
from jinja2.environment import Environment
@ -35,7 +34,7 @@ from jinja2.environment import Environment
from .arm_pack_manager import Cache
from .utils import (mkdir, run_cmd, run_cmd_ext, NotSupportedException,
ToolException, InvalidReleaseTargetException,
intelhex_offset, integer, generate_update_filename, copy_when_different)
copy_when_different)
from .paths import (MBED_CMSIS_PATH, MBED_TARGETS_PATH, MBED_LIBRARIES,
MBED_HEADER, MBED_DRIVERS, MBED_PLATFORM, MBED_HAL,
MBED_CONFIG_FILE, MBED_LIBRARIES_DRIVERS,
@ -393,124 +392,6 @@ def prepare_toolchain(src_paths, build_dir, target, toolchain_name,
return toolchain
def _printihex(ihex):
import pprint
pprint.PrettyPrinter().pprint(ihex.todict())
def _real_region_size(region):
try:
part = intelhex_offset(region.filename, offset=region.start)
return (part.maxaddr() - part.minaddr()) + 1
except AttributeError:
return region.size
def _fill_header(region_list, current_region):
"""Fill an application header region
This is done it three steps:
* Fill the whole region with zeros
* Fill const, timestamp and size entries with their data
* Fill the digests using this header as the header region
"""
region_dict = {r.name: r for r in region_list}
header = IntelHex()
header.puts(current_region.start, b'\x00' * current_region.size)
start = current_region.start
for member in current_region.filename:
_, type, subtype, data = member
member_size = Config.header_member_size(member)
if type == "const":
fmt = {
"8le": ">B", "16le": "<H", "32le": "<L", "64le": "<Q",
"8be": "<B", "16be": ">H", "32be": ">L", "64be": ">Q"
}[subtype]
header.puts(start, struct.pack(fmt, integer(data, 0)))
elif type == "timestamp":
fmt = {"32le": "<L", "64le": "<Q",
"32be": ">L", "64be": ">Q"}[subtype]
header.puts(start, struct.pack(fmt, int(time())))
elif type == "size":
fmt = {"32le": "<L", "64le": "<Q",
"32be": ">L", "64be": ">Q"}[subtype]
size = sum(_real_region_size(region_dict[r]) for r in data)
header.puts(start, struct.pack(fmt, size))
elif type == "digest":
if data == "header":
ih = header[:start]
else:
ih = intelhex_offset(region_dict[data].filename, offset=region_dict[data].start)
if subtype.startswith("CRCITT32"):
fmt = {"CRCITT32be": ">L", "CRCITT32le": "<L"}[subtype]
crc_val = zlib.crc32(ih.tobinarray()) & 0xffffffff
header.puts(start, struct.pack(fmt, crc_val))
elif subtype.startswith("SHA"):
if subtype == "SHA256":
hash = hashlib.sha256()
elif subtype == "SHA512":
hash = hashlib.sha512()
hash.update(ih.tobinarray())
header.puts(start, hash.digest())
start += Config.header_member_size(member)
return header
def merge_region_list(region_list, destination, notify, config, padding=b'\xFF'):
"""Merge the region_list into a single image
Positional Arguments:
region_list - list of regions, which should contain filenames
destination - file name to write all regions to
padding - bytes to fill gaps with
"""
merged = IntelHex()
_, format = splitext(destination)
notify.info("Merging Regions")
# Merged file list: Keep track of binary/hex files that we have already
# merged. e.g In some cases, bootloader may be split into multiple parts, but
# all internally referring to the same bootloader file.
merged_list = []
for region in region_list:
if region.active and not region.filename:
raise ToolException("Active region has no contents: No file found.")
if isinstance(region.filename, list):
header_basename, _ = splitext(destination)
header_filename = header_basename + "_header.hex"
_fill_header(region_list, region).tofile(header_filename, format='hex')
region = region._replace(filename=header_filename)
if region.filename and (region.filename not in merged_list):
notify.info(" Filling region %s with %s" % (region.name, region.filename))
part = intelhex_offset(region.filename, offset=region.start)
part.start_addr = None
# Normally, we assume that part.maxddr() can be beyond
# end of rom. However, if the size is restricted with config, do check.
if config.target.restrict_size is not None:
part_size = (part.maxaddr() - part.minaddr()) + 1
if part_size > region.size:
raise ToolException("Contents of region %s does not fit"
% region.name)
merged_list.append(region.filename)
merged.merge(part)
elif region.filename in merged_list:
notify.info(" Skipping %s as it is merged previously" % (region.name))
# Hex file can have gaps, so no padding needed. While other formats may
# need padding. Iterate through segments and pad the gaps.
if format != ".hex":
# begin patching from the end of the first segment
_, begin = merged.segments()[0]
for start, stop in merged.segments()[1:]:
pad_size = start - begin
merged.puts(begin, padding * pad_size)
begin = stop + 1
if not exists(dirname(destination)):
makedirs(dirname(destination))
notify.info("Space used after regions merged: 0x%x" %
(merged.maxaddr() - merged.minaddr() + 1))
merged.tofile(destination, format=format.strip("."))
UPDATE_WHITELIST = (
"application",
@ -605,27 +486,7 @@ def build_project(src_paths, build_path, target, toolchain_name,
objects = toolchain.compile_sources(resources, sorted(resources.get_file_paths(FileType.INC_DIR)))
resources.add_files_to_type(FileType.OBJECT, objects)
# Link Program
if toolchain.config.has_regions:
binary, _ = toolchain.link_program(resources, build_path, name + "_application")
region_list = list(toolchain.config.regions)
region_list = [r._replace(filename=binary) if r.active else r
for r in region_list]
res = "%s.%s" % (join(build_path, name),
getattr(toolchain.target, "OUTPUT_EXT", "bin"))
merge_region_list(region_list, res, notify, toolchain.config)
update_regions = [
r for r in region_list if r.name in UPDATE_WHITELIST
]
if update_regions:
update_res = join(build_path, generate_update_filename(name, toolchain.target))
merge_region_list(update_regions, update_res, notify, toolchain.config)
res = (res, update_res)
else:
res = (res, None)
else:
res, _ = toolchain.link_program(resources, build_path, name)
res = (res, None)
res = toolchain.link_program(resources, build_path, name)
into_dir, extra_artifacts = toolchain.config.deliver_into()
if into_dir:

View File

@ -1,214 +0,0 @@
""" Configurable hooks in the build system. Can be used by various platforms
to customize the build process.
"""
################################################################################
# Hooks for the various parts of the build process
# Internal mapping of hooks per tool
_HOOKS = {}
# Internal mapping of running hooks
_RUNNING_HOOKS = {}
# Available hook types
_HOOK_TYPES = ["binary", "compile", "link", "assemble"]
# Available hook steps
_HOOK_STEPS = ["pre", "replace", "post"]
# Hook the given function. Use this function as a decorator
def hook_tool(function):
"""Decorate a function as a tool that may be hooked"""
tool = function.__name__
tool_flag = "_" + tool + "_done"
def wrapper(t_self, *args, **kwargs):
"""The hooked function itself"""
# if a hook for this tool is already running, it's most likely
# coming from a derived class, so don't hook the super class version
if _RUNNING_HOOKS.get(tool, False):
return function(t_self, *args, **kwargs)
_RUNNING_HOOKS[tool] = True
# If this tool isn't hooked, return original function
if tool not in _HOOKS:
res = function(t_self, *args, **kwargs)
_RUNNING_HOOKS[tool] = False
return res
tooldesc = _HOOKS[tool]
setattr(t_self, tool_flag, False)
# If there is a replace hook, execute the replacement instead
if "replace" in tooldesc:
res = tooldesc["replace"](t_self, *args, **kwargs)
# If the replacement has set the "done" flag, exit now
# Otherwise continue as usual
if getattr(t_self, tool_flag, False):
_RUNNING_HOOKS[tool] = False
return res
# Execute pre-function before main function if specified
if "pre" in tooldesc:
tooldesc["pre"](t_self, *args, **kwargs)
# Execute the main function now
res = function(t_self, *args, **kwargs)
# Execute post-function after main function if specified
if "post" in tooldesc:
post_res = tooldesc["post"](t_self, *args, **kwargs)
_RUNNING_HOOKS[tool] = False
return post_res or res
else:
_RUNNING_HOOKS[tool] = False
return res
return wrapper
class Hook(object):
"""A compiler class that may be hooked"""
def __init__(self, target, toolchain):
_HOOKS.clear()
self._cmdline_hooks = {}
self.toolchain = toolchain
target.init_hooks(self, toolchain)
# Hook various functions directly
@staticmethod
def _hook_add(hook_type, hook_step, function):
"""Add a hook to a compile function
Positional arguments:
hook_type - one of the _HOOK_TYPES
hook_step - one of the _HOOK_STEPS
function - the function to add to the list of hooks
"""
if hook_type not in _HOOK_TYPES or hook_step not in _HOOK_STEPS:
return False
if hook_type not in _HOOKS:
_HOOKS[hook_type] = {}
_HOOKS[hook_type][hook_step] = function
return True
def hook_add_compiler(self, hook_step, function):
"""Add a hook to the compiler
Positional Arguments:
hook_step - one of the _HOOK_STEPS
function - the function to add to the list of hooks
"""
return self._hook_add("compile", hook_step, function)
def hook_add_linker(self, hook_step, function):
"""Add a hook to the linker
Positional Arguments:
hook_step - one of the _HOOK_STEPS
function - the function to add to the list of hooks
"""
return self._hook_add("link", hook_step, function)
def hook_add_assembler(self, hook_step, function):
"""Add a hook to the assemble
Positional Arguments:
hook_step - one of the _HOOK_STEPS
function - the function to add to the list of hooks
"""
return self._hook_add("assemble", hook_step, function)
def hook_add_binary(self, hook_step, function):
"""Add a hook to the elf to binary tool
Positional Arguments:
hook_step - one of the _HOOK_STEPS
function - the function to add to the list of hooks
"""
return self._hook_add("binary", hook_step, function)
# Hook command lines
def _hook_cmdline(self, hook_type, function):
"""Add a hook to a command line function
Positional arguments:
hook_type - one of the _HOOK_TYPES
function - the function to add to the list of hooks
"""
if hook_type not in _HOOK_TYPES:
return False
self._cmdline_hooks[hook_type] = function
return True
def hook_cmdline_compiler(self, function):
"""Add a hook to the compiler command line
Positional arguments:
function - the function to call
"""
return self._hook_cmdline("compile", function)
def hook_cmdline_linker(self, function):
"""Add a hook to the linker command line
Positional arguments:
function - the function to call
"""
return self._hook_cmdline("link", function)
def hook_cmdline_assembler(self, function):
"""Add a hook to the assembler command line
Positional arguments:
function - the function to call
"""
return self._hook_cmdline("assemble", function)
def hook_cmdline_binary(self, function):
"""Add a hook to the elf to bin tool command line
Positional arguments:
function - the function to call
"""
return self._hook_cmdline("binary", function)
# Return the command line after applying the hook
def _get_cmdline(self, hook_type, cmdline):
"""Get the command line after running all hooks
Positional arguments:
hook_type - one of the _HOOK_TYPES
cmdline - the initial command line
"""
if hook_type in self._cmdline_hooks:
cmdline = self._cmdline_hooks[hook_type](
self.toolchain.__class__.__name__, cmdline)
return cmdline
def get_cmdline_compiler(self, cmdline):
"""Get the compiler command line after running all hooks
Positional arguments:
cmdline - the initial command line
"""
return self._get_cmdline("compile", cmdline)
def get_cmdline_linker(self, cmdline):
"""Get the linker command line after running all hooks
Positional arguments:
cmdline - the initial command line
"""
return self._get_cmdline("link", cmdline)
def get_cmdline_assembler(self, cmdline):
"""Get the assmebler command line after running all hooks
Positional arguments:
cmdline - the initial command line
"""
return self._get_cmdline("assemble", cmdline)
def get_cmdline_binary(self, cmdline):
"""Get the binary command line after running all hooks
Positional arguments:
cmdline - the initial command line
"""
return self._get_cmdline("binary", cmdline)
################################################################################

175
tools/regions.py Normal file
View File

@ -0,0 +1,175 @@
# mbed SDK
# SPDX-License-Identifier: Apache-2.0
# Copyright (c) 2011-2013 ARM Limited
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""
Utilities for working with region lists.
"""
import hashlib
import struct
import zlib
from time import time
from os.path import splitext, exists, dirname
from os import makedirs
from .config import Config
from .utils import (
ToolException,
intelhex_offset,
integer
)
from intelhex import IntelHex
UPDATE_WHITELIST = (
"application"
)
def _printihex(ihex):
import pprint
pprint.PrettyPrinter().pprint(ihex.todict())
def _real_region_size(region):
try:
part = intelhex_offset(region.filename, offset=region.start)
return (part.maxaddr() - part.minaddr()) + 1
except AttributeError:
return region.size
def _fill_header(region_list, current_region):
"""Fill an application header region
This is done it three steps:
* Fill the whole region with zeros
* Fill const, timestamp and size entries with their data
* Fill the digests using this header as the header region
"""
region_dict = {r.name: r for r in region_list}
header = IntelHex()
header.puts(current_region.start, b'\x00' * current_region.size)
start = current_region.start
for member in current_region.filename:
_, type, subtype, data = member
if type == "const":
fmt = {
"8le": ">B", "16le": "<H", "32le": "<L", "64le": "<Q",
"8be": "<B", "16be": ">H", "32be": ">L", "64be": ">Q"
}[subtype]
header.puts(start, struct.pack(fmt, integer(data, 0)))
elif type == "timestamp":
fmt = {"32le": "<L", "64le": "<Q",
"32be": ">L", "64be": ">Q"}[subtype]
header.puts(start, struct.pack(fmt, int(time())))
elif type == "size":
fmt = {"32le": "<L", "64le": "<Q",
"32be": ">L", "64be": ">Q"}[subtype]
size = sum(_real_region_size(region_dict[r]) for r in data)
header.puts(start, struct.pack(fmt, size))
elif type == "digest":
if data == "header":
ih = header[:start]
else:
ih = intelhex_offset(
region_dict[data].filename,
offset=region_dict[data].start
)
if subtype.startswith("CRCITT32"):
fmt = {"CRCITT32be": ">L", "CRCITT32le": "<L"}[subtype]
crc_val = zlib.crc32(ih.tobinarray()) & 0xffffffff
header.puts(start, struct.pack(fmt, crc_val))
elif subtype.startswith("SHA"):
if subtype == "SHA256":
hash = hashlib.sha256()
elif subtype == "SHA512":
hash = hashlib.sha512()
hash.update(ih.tobinarray())
header.puts(start, hash.digest())
start += Config.header_member_size(member)
return header
def merge_region_list(
region_list,
destination,
notify,
config,
padding=b'\xFF'
):
"""Merge the region_list into a single image
Positional Arguments:
region_list - list of regions, which should contain filenames
destination - file name to write all regions to
padding - bytes to fill gaps with
"""
merged = IntelHex()
_, format = splitext(destination)
notify.info("Merging Regions")
# Merged file list: Keep track of binary/hex files that we have already
# merged. e.g In some cases, bootloader may be split into multiple parts,
# but all internally referring to the same bootloader file.
merged_list = []
for region in region_list:
if region.active and not region.filename:
raise ToolException(
"Active region has no contents: No file found."
)
if isinstance(region.filename, list):
header_basename, _ = splitext(destination)
header_filename = header_basename + "_header.hex"
_fill_header(region_list, region).tofile(
header_filename, format='hex'
)
region = region._replace(filename=header_filename)
if region.filename and (region.filename not in merged_list):
notify.info(" Filling region %s with %s" % (
region.name, region.filename
))
part = intelhex_offset(region.filename, offset=region.start)
part.start_addr = None
# Normally, we assume that part.maxddr() can be beyond
# end of rom. If the size is restricted with config, don't
# allow this.
if config.target.restrict_size is not None:
part_size = (part.maxaddr() - part.minaddr()) + 1
if part_size > region.size:
raise ToolException(
"Contents of region %s does not fit" % region.name
)
merged_list.append(region.filename)
merged.merge(part)
elif region.filename in merged_list:
notify.info(
" Skipping %s as it is merged previously" % (region.name)
)
# Hex file can have gaps, so no padding needed. While other formats may
# need padding. Iterate through segments and pad the gaps.
if format != ".hex":
# begin patching from the end of the first segment
_, begin = merged.segments()[0]
for start, stop in merged.segments()[1:]:
pad_size = start - begin
merged.puts(begin, padding * pad_size)
begin = stop + 1
if not exists(dirname(destination)):
makedirs(dirname(destination))
notify.info("Space used after regions merged: 0x%x" %
(merged.maxaddr() - merged.minaddr() + 1))
merged.tofile(destination, format=format.strip("."))

View File

@ -355,7 +355,7 @@ class Target(namedtuple("Target", "name json_data resolution_order resolution_or
def is_PSA_non_secure_target(self):
return 'NSPE_Target' in self.labels
def init_hooks(self, hook, toolchain):
def get_post_build_hook(self, toolchain):
"""Initialize the post-build hooks for a toolchain. For now, this
function only allows "post binary" hooks (hooks that are executed
after the binary image is extracted from the executable file)
@ -404,8 +404,7 @@ class Target(namedtuple("Target", "name json_data resolution_order resolution_or
if toolchain_restrictions and \
not toolchain_labels.intersection(toolchain_restrictions):
return
# Finally, hook the requested function
hook.hook_add_binary("post", getattr(cls, function_name))
return getattr(cls, function_name)
################################################################################
# Target specific code goes in this section

View File

@ -18,7 +18,8 @@ limitations under the License.
import unittest
from collections import namedtuple
from mock import patch, MagicMock
from tools.build_api import prepare_toolchain, build_project, build_library, merge_region_list
from tools.build_api import prepare_toolchain, build_project, build_library
from tools.regions import merge_region_list
from tools.resources import Resources
from tools.toolchains import TOOLCHAINS
from tools.notifier.mock import MockNotifier
@ -30,7 +31,7 @@ from intelhex import IntelHex
Tests for build_api.py
"""
make_mock_target = namedtuple(
"Target", "init_hooks name features core supported_toolchains build_tools_metadata")
"Target", "get_post_build_hook name features core supported_toolchains build_tools_metadata")
#Add ARMC5 to the supported_toolchains list as ARMC5 actually refers ARM Compiler 5 and is needed by ARM/ARM_STD classes when it checks for supported toolchains
TOOLCHAINS.add("ARMC5")
#Make a mock build_tools_metadata
@ -65,7 +66,6 @@ class BuildApiTests(unittest.TestCase):
@patch('tools.toolchains.mbedToolchain.need_update',
side_effect=[i % 2 for i in range(3000)])
@patch('os.mkdir')
@patch('tools.toolchains.exists', return_value=True)
@patch('tools.toolchains.mbedToolchain.dump_build_profile')
@patch('tools.utils.run_cmd', return_value=(b'', b'', 0))
def test_always_complete_build(self, *_):
@ -94,7 +94,7 @@ class BuildApiTests(unittest.TestCase):
:return:
"""
app_config = "app_config"
mock_target = make_mock_target(lambda _, __ : None,
mock_target = make_mock_target(lambda _ : None,
"Junk", [], "Cortex-M3", TOOLCHAINS, mock_build_tools_metadata)
mock_config_init.return_value = namedtuple(
"Config", "target has_regions name")(mock_target, False, None)
@ -113,7 +113,7 @@ class BuildApiTests(unittest.TestCase):
:param mock_config_init: mock of Config __init__
:return:
"""
mock_target = make_mock_target(lambda _, __ : None,
mock_target = make_mock_target(lambda _ : None,
"Junk", [], "Cortex-M3", TOOLCHAINS, mock_build_tools_metadata)
mock_config_init.return_value = namedtuple(
"Config", "target has_regions name")(mock_target, False, None)
@ -246,7 +246,7 @@ class BuildApiTests(unittest.TestCase):
self.assertEqual(args[1]['app_config'], None,
"prepare_toolchain was called with an incorrect app_config")
@patch('tools.build_api.intelhex_offset')
@patch('tools.regions.intelhex_offset')
@patch('tools.config')
def test_merge_region_no_fit(self, mock_config, mock_intelhex_offset):
"""

File diff suppressed because it is too large Load Diff

View File

@ -15,32 +15,34 @@ See the License for the specific language governing permissions and
limitations under the License.
"""
from __future__ import print_function, absolute_import
from builtins import str
from builtins import str # noqa: F401
import re
from copy import copy
from os.path import join, dirname, splitext, basename, exists, relpath, isfile
from os import makedirs, write, curdir, remove
from os.path import join, dirname, splitext, basename, exists, isfile
from os import makedirs, write, remove
from tempfile import mkstemp
from shutil import rmtree
from distutils.version import LooseVersion
from tools.targets import CORE_ARCH
from tools.toolchains import mbedToolchain, TOOLCHAIN_PATHS
from tools.hooks import hook_tool
from tools.toolchains.mbed_toolchain import mbedToolchain, TOOLCHAIN_PATHS
from tools.utils import mkdir, NotSupportedException, run_cmd
class ARM(mbedToolchain):
LINKER_EXT = '.sct'
LIBRARY_EXT = '.ar'
STD_LIB_NAME = "%s.ar"
DIAGNOSTIC_PATTERN = re.compile('"(?P<file>[^"]+)", line (?P<line>\d+)( \(column (?P<column>\d+)\)|): (?P<severity>Warning|Error|Fatal error): (?P<message>.+)')
INDEX_PATTERN = re.compile('(?P<col>\s*)\^')
DIAGNOSTIC_PATTERN = re.compile('"(?P<file>[^"]+)", line (?P<line>\d+)( \(column (?P<column>\d+)\)|): (?P<severity>Warning|Error|Fatal error): (?P<message>.+)')
INDEX_PATTERN = re.compile('(?P<col>\s*)\^')
DEP_PATTERN = re.compile('\S+:\s(?P<file>.+)\n')
SHEBANG = "#! armcc -E"
SUPPORTED_CORES = ["Cortex-M0", "Cortex-M0+", "Cortex-M3", "Cortex-M4",
"Cortex-M4F", "Cortex-M7", "Cortex-M7F", "Cortex-M7FD", "Cortex-A9"]
SUPPORTED_CORES = [
"Cortex-M0", "Cortex-M0+", "Cortex-M3", "Cortex-M4", "Cortex-M4F",
"Cortex-M7", "Cortex-M7F", "Cortex-M7FD", "Cortex-A9"
]
ARMCC_RANGE = (LooseVersion("5.06"), LooseVersion("5.07"))
ARMCC_VERSION_RE = re.compile(b"Component: ARM Compiler (\d+\.\d+)")
@ -82,7 +84,6 @@ class ARM(mbedToolchain):
cpu = target.core
ARM_BIN = join(TOOLCHAIN_PATHS['ARM'], "bin")
ARM_INC = join(TOOLCHAIN_PATHS['ARM'], "include")
main_cc = join(ARM_BIN, "armcc")
@ -90,7 +91,10 @@ class ARM(mbedToolchain):
self.asm = [main_cc] + self.flags['common'] + self.flags['asm']
self.cc = [main_cc] + self.flags['common'] + self.flags['c']
self.cppc = [main_cc] + self.flags['common'] + self.flags['c'] + self.flags['cxx']
self.cppc = (
[main_cc] + self.flags['common'] +
self.flags['c'] + self.flags['cxx']
)
self.ld = [join(ARM_BIN, "armlink")] + self.flags['ld']
@ -104,9 +108,13 @@ class ARM(mbedToolchain):
msg = None
min_ver, max_ver = self.ARMCC_RANGE
match = self.ARMCC_VERSION_RE.search(stdout.encode("utf-8"))
found_version = LooseVersion(match.group(1).decode("utf-8")) if match else None
if match:
found_version = LooseVersion(match.group(1).decode("utf-8"))
else:
found_version = None
min_ver, max_ver = self.ARMCC_RANGE
if found_version and (found_version < min_ver or found_version >= max_ver):
if found_version and (found_version < min_ver
or found_version >= max_ver):
msg = ("Compiler version mismatch: Have {}; "
"expected version >= {} and < {}"
.format(found_version, min_ver, max_ver))
@ -135,8 +143,11 @@ class ARM(mbedToolchain):
for line in open(dep_path).readlines():
match = ARM.DEP_PATTERN.match(line)
if match is not None:
#we need to append chroot, because when the .d files are generated the compiler is chrooted
dependencies.append((self.CHROOT if self.CHROOT else '') + match.group('file'))
# we need to append chroot, because when the .d files are
# generated the compiler is chrooted
dependencies.append(
(self.CHROOT if self.CHROOT else '') + match.group('file')
)
return dependencies
def parse_output(self, output):
@ -151,14 +162,18 @@ class ARM(mbedToolchain):
'severity': match.group('severity').lower(),
'file': match.group('file'),
'line': match.group('line'),
'col': match.group('column') if match.group('column') else 0,
'message': match.group('message'),
'text': '',
'target_name': self.target.name,
'toolchain_name': self.name
}
if match.group('column'):
msg['col'] = match.group('column')
else:
msg['col'] = 0
elif msg is not None:
# Determine the warning/error column by calculating the ^ position
# Determine the warning/error column by calculating the '^'
# position
match = ARM.INDEX_PATTERN.match(line)
if match is not None:
msg['col'] = len(match.group('col'))
@ -192,7 +207,6 @@ class ARM(mbedToolchain):
return opts
@hook_tool
def assemble(self, source, object, includes):
# Preprocess first, then assemble
dir = join(dirname(object), '.temp')
@ -208,14 +222,9 @@ class ARM(mbedToolchain):
# Build main assemble command
cmd = self.asm + ["-o", object, tempfile]
# Call cmdline hook
cmd_pre = self.hook.get_cmdline_assembler(cmd_pre)
cmd = self.hook.get_cmdline_assembler(cmd)
# Return command array, don't execute
return [cmd_pre, cmd]
@hook_tool
def compile(self, cc, source, object, includes):
# Build compile command
cmd = cc + self.get_compile_options(self.get_symbols(), includes)
@ -224,9 +233,6 @@ class ARM(mbedToolchain):
cmd.extend(["-o", object, source])
# Call cmdline hook
cmd = self.hook.get_cmdline_compiler(cmd)
return [cmd]
def compile_c(self, source, object, includes):
@ -254,7 +260,7 @@ class ARM(mbedToolchain):
with open(scatter_file, "r") as input:
lines = input.readlines()
if (lines[0].startswith(self.SHEBANG) or
not lines[0].startswith("#!")):
not lines[0].startswith("#!")):
return scatter_file
else:
new_scatter = join(self.build_dir, ".link_script.sct")
@ -269,7 +275,6 @@ class ARM(mbedToolchain):
return new_scatter
@hook_tool
def link(self, output, objects, libraries, lib_dirs, scatter_file):
base, _ = splitext(output)
map_file = base + ".map"
@ -282,8 +287,7 @@ class ARM(mbedToolchain):
new_scatter = self.correct_scatter_shebang(scatter_file)
args.extend(["--scatter", new_scatter])
cmd_pre = self.ld + args
cmd = self.hook.get_cmdline_linker(cmd_pre)
cmd = self.ld + args
if self.RESPONSE_FILES:
cmd_linker = cmd[0]
@ -293,7 +297,6 @@ class ARM(mbedToolchain):
self.notify.cc_verbose("Link: %s" % ' '.join(cmd))
self.default_cmd(cmd)
@hook_tool
def archive(self, objects, lib_path):
if self.RESPONSE_FILES:
param = ['--via', self.get_arch_file(objects)]
@ -301,13 +304,12 @@ class ARM(mbedToolchain):
param = objects
self.default_cmd([self.ar, '-r', lib_path] + param)
@hook_tool
def binary(self, resources, elf, bin):
_, fmt = splitext(bin)
# On .hex format, combine multiple .hex files (for multiple load regions) into one
# On .hex format, combine multiple .hex files (for multiple load
# regions) into one
bin_arg = {".bin": "--bin", ".hex": "--i32combined"}[fmt]
cmd = [self.elf2bin, bin_arg, '-o', bin, elf]
cmd = self.hook.get_cmdline_binary(cmd)
# remove target binary file/path
if exists(bin):
@ -337,46 +339,95 @@ class ARM(mbedToolchain):
class ARM_STD(ARM):
OFFICIALLY_SUPPORTED = True
def __init__(self, target, notify=None, macros=None,
build_profile=None, build_dir=None):
ARM.__init__(self, target, notify, macros, build_dir=build_dir,
build_profile=build_profile)
def __init__(
self,
target,
notify=None,
macros=None,
build_profile=None,
build_dir=None
):
ARM.__init__(
self,
target,
notify,
macros,
build_dir=build_dir,
build_profile=build_profile
)
if int(target.build_tools_metadata["version"]) > 0:
#check only for ARMC5 because ARM_STD means using ARMC5, and thus supported_toolchains must include ARMC5
#check only for ARMC5 because ARM_STD means using ARMC5, and thus
# supported_toolchains must include ARMC5
if "ARMC5" not in target.supported_toolchains:
raise NotSupportedException("ARM compiler 5 support is required for ARM build")
raise NotSupportedException(
"ARM compiler 5 support is required for ARM build"
)
else:
if not set(("ARM", "uARM")).intersection(set(target.supported_toolchains)):
raise NotSupportedException("ARM/uARM compiler support is required for ARM build")
if not set(("ARM", "uARM")).intersection(set(
target.supported_toolchains
)):
raise NotSupportedException(
"ARM/uARM compiler support is required for ARM build"
)
class ARM_MICRO(ARM):
PATCHED_LIBRARY = False
OFFICIALLY_SUPPORTED = True
def __init__(self, target, notify=None, macros=None,
silent=False, extra_verbose=False, build_profile=None,
build_dir=None):
target.default_toolchain = "uARM"
PATCHED_LIBRARY = False
OFFICIALLY_SUPPORTED = True
def __init__(
self,
target,
notify=None,
macros=None,
silent=False,
extra_verbose=False,
build_profile=None,
build_dir=None
):
target.default_toolchain = "uARM"
if int(target.build_tools_metadata["version"]) > 0:
#At this point we already know that we want to use ARMC5+Microlib, so check for if they are supported
#For, AC6+Microlib we still use ARMC6 class
if not set(("ARMC5","uARM")).issubset(set(target.supported_toolchains)):
raise NotSupportedException("ARM/uARM compiler support is required for ARM build")
# At this point we already know that we want to use ARMC5+Microlib
# so check for if they are supported For, AC6+Microlib we still
# use ARMC6 class
if not set(("ARMC5","uARM")).issubset(set(
target.supported_toolchains
)):
raise NotSupportedException(
"ARM/uARM compiler support is required for ARM build"
)
else:
if not set(("ARM", "uARM")).intersection(set(target.supported_toolchains)):
raise NotSupportedException("ARM/uARM compiler support is required for ARM build")
ARM.__init__(self, target, notify, macros, build_dir=build_dir,
build_profile=build_profile)
if not set(("ARM", "uARM")).intersection(set(
target.supported_toolchains
)):
raise NotSupportedException(
"ARM/uARM compiler support is required for ARM build"
)
ARM.__init__(
self,
target,
notify,
macros,
build_dir=build_dir,
build_profile=build_profile
)
class ARMC6(ARM_STD):
OFFICIALLY_SUPPORTED = True
OFFICIALLY_SUPPORTED = False
SHEBANG = "#! armclang -E --target=arm-arm-none-eabi -x c"
SUPPORTED_CORES = ["Cortex-M0", "Cortex-M0+", "Cortex-M3", "Cortex-M4",
"Cortex-M4F", "Cortex-M7", "Cortex-M7F", "Cortex-M7FD",
"Cortex-M23", "Cortex-M23-NS", "Cortex-M33", "Cortex-M33F",
"Cortex-M33-NS", "Cortex-M33F-NS", "Cortex-M33FE-NS", "Cortex-M33FE",
"Cortex-A9"]
SUPPORTED_CORES = [
"Cortex-M0", "Cortex-M0+", "Cortex-M3", "Cortex-M4",
"Cortex-M4F", "Cortex-M7", "Cortex-M7F", "Cortex-M7FD",
"Cortex-M23", "Cortex-M23-NS", "Cortex-M33", "Cortex-M33F",
"Cortex-M33-NS", "Cortex-M33F-NS", "Cortex-M33FE-NS", "Cortex-M33FE",
"Cortex-A9"
]
ARMCC_RANGE = (LooseVersion("6.10"), LooseVersion("7.0"))
@staticmethod
@ -390,12 +441,20 @@ class ARMC6(ARM_STD):
"this compiler does not support the core %s" % target.core)
if int(target.build_tools_metadata["version"]) > 0:
if not set(("ARM", "ARMC6", "uARM")).intersection(set(target.supported_toolchains)):
raise NotSupportedException("ARM/ARMC6 compiler support is required for ARMC6 build")
if not set(("ARM", "ARMC6", "uARM")).intersection(set(
target.supported_toolchains
)):
raise NotSupportedException(
"ARM/ARMC6 compiler support is required for ARMC6 build"
)
else:
if not set(("ARM", "ARMC6")).intersection(set(target.supported_toolchains)):
raise NotSupportedException("ARM/ARMC6 compiler support is required for ARMC6 build")
if not set(("ARM", "ARMC6")).intersection(set(
target.supported_toolchains
)):
raise NotSupportedException(
"ARM/ARMC6 compiler support is required for ARMC6 build"
)
if getattr(target, "default_toolchain", "ARMC6") == "uARM":
if "-DMBED_RTOS_SINGLE_THREAD" not in self.flags['common']:
self.flags['common'].append("-DMBED_RTOS_SINGLE_THREAD")
@ -404,15 +463,16 @@ class ARMC6(ARM_STD):
if "--library_type=microlib" not in self.flags['ld']:
self.flags['ld'].append("--library_type=microlib")
if "-Wl,--library_type=microlib" not in self.flags['c']:
self.flags['c'].append("-Wl,--library_type=microlib")
self.flags['c'].append("-Wl,--library_type=microlib")
if "-Wl,--library_type=microlib" not in self.flags['cxx']:
self.flags['cxx'].append("-Wl,--library_type=microlib")
self.flags['cxx'].append("-Wl,--library_type=microlib")
if "--library_type=microlib" not in self.flags['asm']:
self.flags['asm'].append("--library_type=microlib")
self.flags['asm'].append("--library_type=microlib")
core = target.core
if CORE_ARCH[target.core] == 8:
if (not target.core.endswith("-NS")) and kwargs.get('build_dir', False):
if ((not target.core.endswith("-NS")) and
kwargs.get('build_dir', False)):
# Create Secure library
build_dir = kwargs['build_dir']
secure_file = join(build_dir, "cmse_lib.o")
@ -479,8 +539,10 @@ class ARMC6(ARM_STD):
self.flags['common'] + self.flags['c'])
self.cppc = ([join(TOOLCHAIN_PATHS["ARMC6"], "armclang")] +
self.flags['common'] + self.flags['cxx'])
self.asm = [join(TOOLCHAIN_PATHS["ARMC6"], "armasm")] + self.flags['asm']
self.ld = [join(TOOLCHAIN_PATHS["ARMC6"], "armlink")] + self.flags['ld']
self.asm = [join(TOOLCHAIN_PATHS["ARMC6"], "armasm")]
self.asm += self.flags['asm']
self.ld = [join(TOOLCHAIN_PATHS["ARMC6"], "armlink")]
self.ld += self.flags['ld']
self.ar = join(TOOLCHAIN_PATHS["ARMC6"], "armar")
self.elf2bin = join(TOOLCHAIN_PATHS["ARMC6"], "fromelf")
@ -514,22 +576,21 @@ class ARMC6(ARM_STD):
if config_header:
opts.extend(self.get_config_option(config_header))
if for_asm:
return ["--cpreproc",
"--cpreproc_opts=%s" % ",".join(self.flags['common'] + opts)]
return [
"--cpreproc",
"--cpreproc_opts=%s" % ",".join(self.flags['common'] + opts)
]
return opts
@hook_tool
def assemble(self, source, object, includes):
cmd_pre = copy(self.asm)
cmd_pre.extend(self.get_compile_options(
self.get_symbols(True), includes, for_asm=True))
cmd_pre.extend(["-o", object, source])
return [self.hook.get_cmdline_assembler(cmd_pre)]
return [cmd_pre]
@hook_tool
def compile(self, cc, source, object, includes):
cmd = copy(cc)
cmd.extend(self.get_compile_options(self.get_symbols(), includes))
cmd.extend(["-o", object, source])
cmd = self.hook.get_cmdline_compiler(cmd)
return [cmd]

View File

@ -21,9 +21,9 @@ from distutils.spawn import find_executable
from distutils.version import LooseVersion
from tools.targets import CORE_ARCH
from tools.toolchains import mbedToolchain, TOOLCHAIN_PATHS
from tools.hooks import hook_tool
from tools.utils import run_cmd, NotSupportedException
from tools.toolchains.mbed_toolchain import mbedToolchain, TOOLCHAIN_PATHS
from tools.utils import run_cmd
class GCC(mbedToolchain):
OFFICIALLY_SUPPORTED = True
@ -38,15 +38,21 @@ class GCC(mbedToolchain):
def __init__(self, target, notify=None, macros=None, build_profile=None,
build_dir=None):
mbedToolchain.__init__(self, target, notify, macros,
build_profile=build_profile, build_dir=build_dir)
mbedToolchain.__init__(
self,
target,
notify,
macros,
build_profile=build_profile,
build_dir=build_dir
)
tool_path=TOOLCHAIN_PATHS['GCC_ARM']
tool_path = TOOLCHAIN_PATHS['GCC_ARM']
# Add flags for current size setting
default_lib = "std"
if hasattr(target, "default_lib"):
default_lib = target.default_lib
elif hasattr(target, "default_build"): # Legacy
elif hasattr(target, "default_build"):
default_lib = target.default_build
if default_lib == "small":
@ -110,8 +116,8 @@ class GCC(mbedToolchain):
main_cc = join(tool_path, "arm-none-eabi-gcc")
main_cppc = join(tool_path, "arm-none-eabi-g++")
self.asm = [main_cc] + self.flags['asm'] + self.flags["common"]
self.cc = [main_cc]
self.cppc =[main_cppc]
self.cc = [main_cc]
self.cppc = [main_cppc]
self.cc += self.flags['c'] + self.flags['common']
self.cppc += self.flags['cxx'] + self.flags['common']
@ -130,9 +136,13 @@ class GCC(mbedToolchain):
stdout, _, retcode = run_cmd([self.cc[0], "--version"], redirect=True)
msg = None
match = self.GCC_VERSION_RE.search(stdout.encode("utf-8"))
found_version = LooseVersion(match.group(0).decode('utf-8')) if match else None
if match:
found_version = LooseVersion(match.group(0).decode('utf-8'))
else:
found_version = None
min_ver, max_ver = self.GCC_RANGE
if found_version and (found_version < min_ver or found_version >= max_ver):
if found_version and (found_version < min_ver
or found_version >= max_ver):
msg = ("Compiler version mismatch: Have {}; "
"expected version >= {} and < {}"
.format(found_version, min_ver, max_ver))
@ -195,18 +205,15 @@ class GCC(mbedToolchain):
opts = opts + self.get_config_option(config_header)
return opts
@hook_tool
def assemble(self, source, object, includes):
# Build assemble command
cmd = self.asm + self.get_compile_options(self.get_symbols(True), includes) + ["-o", object, source]
# Call cmdline hook
cmd = self.hook.get_cmdline_assembler(cmd)
cmd = self.asm + self.get_compile_options(
self.get_symbols(True), includes
) + ["-o", object, source]
# Return command array, don't execute
return [cmd]
@hook_tool
def compile(self, cc, source, object, includes):
# Build compile command
cmd = cc + self.get_compile_options(self.get_symbols(), includes)
@ -215,8 +222,6 @@ class GCC(mbedToolchain):
cmd.extend(["-o", object, source])
# Call cmdline hook
cmd = self.hook.get_cmdline_compiler(cmd)
if self.use_distcc:
cmd = ["distcc"] + cmd
@ -228,7 +233,6 @@ class GCC(mbedToolchain):
def compile_cpp(self, source, object, includes):
return self.compile(self.cppc, source, object, includes)
@hook_tool
def link(self, output, objects, libraries, lib_dirs, mem_map):
libs = []
for l in libraries:
@ -239,15 +243,23 @@ class GCC(mbedToolchain):
# Preprocess
if mem_map:
preproc_output = join(dirname(output), ".link_script.ld")
cmd = (self.preproc + [mem_map] + self.ld[1:] +
[ "-o", preproc_output])
cmd = (
self.preproc + [mem_map] + self.ld[1:] + ["-o", preproc_output]
)
self.notify.cc_verbose("Preproc: %s" % ' '.join(cmd))
self.default_cmd(cmd)
mem_map = preproc_output
# Build linker command
map_file = splitext(output)[0] + ".map"
cmd = self.ld + ["-o", output, "-Wl,-Map=%s" % map_file] + objects + ["-Wl,--start-group"] + libs + ["-Wl,--end-group"]
cmd = (
self.ld +
["-o", output, "-Wl,-Map=%s" % map_file] +
objects +
["-Wl,--start-group"] +
libs +
["-Wl,--end-group"]
)
if mem_map:
cmd.extend(['-T', mem_map])
@ -256,9 +268,6 @@ class GCC(mbedToolchain):
cmd.extend(['-L', L])
cmd.extend(libs)
# Call cmdline hook
cmd = self.hook.get_cmdline_linker(cmd)
if self.RESPONSE_FILES:
# Split link command to linker executable + response file
cmd_linker = cmd[0]
@ -269,7 +278,6 @@ class GCC(mbedToolchain):
self.notify.cc_verbose("Link: %s" % ' '.join(cmd))
self.default_cmd(cmd)
@hook_tool
def archive(self, objects, lib_path):
if self.RESPONSE_FILES:
param = ["@%s" % self.get_arch_file(objects)]
@ -279,16 +287,12 @@ class GCC(mbedToolchain):
# Exec command
self.default_cmd([self.ar, 'rcs', lib_path] + param)
@hook_tool
def binary(self, resources, elf, bin):
# Build binary command
_, fmt = splitext(bin)
bin_arg = {'.bin': 'binary', '.hex': 'ihex'}[fmt]
cmd = [self.elf2bin, "-O", bin_arg, elf, bin]
# Call cmdline hook
cmd = self.hook.get_cmdline_binary(cmd)
# Exec command
self.notify.cc_verbose("FromELF: %s" % ' '.join(cmd))
self.default_cmd(cmd)
@ -308,9 +312,12 @@ class GCC(mbedToolchain):
@staticmethod
def check_executable():
"""Returns True if the executable (arm-none-eabi-gcc) location
specified by the user exists OR the executable can be found on the PATH.
Returns False otherwise."""
if not TOOLCHAIN_PATHS['GCC_ARM'] or not exists(TOOLCHAIN_PATHS['GCC_ARM']):
specified by the user exists OR the executable can be found on the
PATH. Returns False otherwise."""
if (
not TOOLCHAIN_PATHS['GCC_ARM'] or
not exists(TOOLCHAIN_PATHS['GCC_ARM'])
):
if find_executable('arm-none-eabi-gcc'):
TOOLCHAIN_PATHS['GCC_ARM'] = ''
return True
@ -320,5 +327,6 @@ class GCC(mbedToolchain):
exec_name = join(TOOLCHAIN_PATHS['GCC_ARM'], 'arm-none-eabi-gcc')
return exists(exec_name) or exists(exec_name + '.exe')
class GCC_ARM(GCC):
pass

View File

@ -20,9 +20,9 @@ from os.path import join, splitext, exists
from distutils.version import LooseVersion
from tools.targets import CORE_ARCH
from tools.toolchains import mbedToolchain, TOOLCHAIN_PATHS
from tools.hooks import hook_tool
from tools.utils import run_cmd, NotSupportedException
from tools.toolchains.mbed_toolchain import mbedToolchain, TOOLCHAIN_PATHS
from tools.utils import run_cmd
class IAR(mbedToolchain):
OFFICIALLY_SUPPORTED = True
@ -31,20 +31,29 @@ class IAR(mbedToolchain):
STD_LIB_NAME = "%s.a"
DIAGNOSTIC_PATTERN = re.compile('"(?P<file>[^"]+)",(?P<line>[\d]+)\s+(?P<severity>Warning|Error|Fatal error)(?P<message>.+)')
INDEX_PATTERN = re.compile('(?P<col>\s*)\^')
INDEX_PATTERN = re.compile('(?P<col>\s*)\^')
IAR_VERSION_RE = re.compile(b"IAR ANSI C/C\+\+ Compiler V(\d+\.\d+)")
IAR_VERSION = LooseVersion("8.32")
@staticmethod
def check_executable():
"""Returns True if the executable (arm-none-eabi-gcc) location
specified by the user exists OR the executable can be found on the PATH.
Returns False otherwise."""
return mbedToolchain.generic_check_executable("IAR", 'iccarm', 2, "bin")
specified by the user exists OR the executable can be found on the
PATH. Returns False otherwise."""
return mbedToolchain.generic_check_executable(
"IAR", 'iccarm', 2, "bin"
)
def __init__(self, target, notify=None, macros=None, build_profile=None,
build_dir=None):
mbedToolchain.__init__(self, target, notify, macros, build_dir=build_dir, build_profile=build_profile)
mbedToolchain.__init__(
self,
target,
notify,
macros,
build_dir=build_dir,
build_profile=build_profile
)
core = target.core
if CORE_ARCH[target.core] == 8:
# Add linking time preprocessor macro DOMAIN_NS
@ -66,8 +75,8 @@ class IAR(mbedToolchain):
"Cortex-M33F": "Cortex-M33.fp.no_dsp",
"Cortex-M33FE": "Cortex-M33.fp"}.get(core, core)
# flags_cmd are used only by our scripts, the project files have them already defined,
# using this flags results in the errors (duplication)
# flags_cmd are used only by our scripts, the project files have them
# already defined, using this flags results in the errors (duplication)
# asm accepts --cpu Core or --fpu FPU, not like c/c++ --cpu=Core
asm_flags_cmd = ["--cpu", cpu]
# custom c flags
@ -84,13 +93,22 @@ class IAR(mbedToolchain):
IAR_BIN = join(TOOLCHAIN_PATHS['IAR'], "bin")
main_cc = join(IAR_BIN, "iccarm")
self.asm = [join(IAR_BIN, "iasmarm")] + asm_flags_cmd + self.flags["asm"]
self.cc = [main_cc]
self.asm = [join(IAR_BIN, "iasmarm")]
self.asm += asm_flags_cmd
self.asm += self.flags["asm"]
self.cc = [main_cc]
self.cc += self.flags["common"]
self.cc += c_flags_cmd
self.cc += self.flags["c"]
self.cppc = [main_cc]
self.cc += self.flags["common"] + c_flags_cmd + self.flags["c"]
self.cppc += self.flags["common"] + c_flags_cmd + cxx_flags_cmd + self.flags["cxx"]
self.ld = [join(IAR_BIN, "ilinkarm")] + self.flags['ld']
self.cppc += self.flags["common"]
self.cppc += c_flags_cmd
self.cppc += cxx_flags_cmd
self.cppc += self.flags["cxx"]
self.ld = [join(IAR_BIN, "ilinkarm")] + self.flags['ld']
self.ar = join(IAR_BIN, "iarchive")
self.elf2bin = join(IAR_BIN, "ielftool")
@ -114,10 +132,16 @@ class IAR(mbedToolchain):
"severity": "Warning",
})
def _inner_parse_deps(self, dep_path):
for path in open(dep_path).readlines():
if path and not path.isspace():
if self.CHROOT:
yield self.CHROOT + path.strip()
else:
yield path.strip()
def parse_dependencies(self, dep_path):
return [(self.CHROOT if self.CHROOT else '')+path.strip() for path in open(dep_path).readlines()
if (path and not path.isspace())]
return list(self._inner_parse_deps(dep_path))
def parse_output(self, output):
msg = None
@ -138,7 +162,8 @@ class IAR(mbedToolchain):
'toolchain_name': self.name
}
elif msg is not None:
# Determine the warning/error column by calculating the ^ position
# Determine the warning/error column by calculating the '^'
# position
match = IAR.INDEX_PATTERN.match(line)
if match is not None:
msg['col'] = len(match.group('col'))
@ -166,7 +191,7 @@ class IAR(mbedToolchain):
opts = ['-D%s' % d for d in defines]
if for_asm:
config_macros = self.config.get_config_data_macros()
macros_cmd = ['"-D%s"' % d for d in config_macros if not '"' in d]
macros_cmd = ['"-D%s"' % d for d in config_macros if '"' not in d]
if self.RESPONSE_FILES:
via_file = self.make_option_file(
macros_cmd, "asm_macros_{}.xcl")
@ -185,31 +210,21 @@ class IAR(mbedToolchain):
return opts
@hook_tool
def assemble(self, source, object, includes):
# Build assemble command
cmd = self.asm + self.get_compile_options(self.get_symbols(True), includes, True) + ["-o", object, source]
# Call cmdline hook
cmd = self.hook.get_cmdline_assembler(cmd)
cmd = self.asm + self.get_compile_options(
self.get_symbols(True), includes, True
) + ["-o", object, source]
# Return command array, don't execute
return [cmd]
@hook_tool
def compile(self, cc, source, object, includes):
# Build compile command
cmd = cc + self.get_compile_options(self.get_symbols(), includes)
cmd = cc + self.get_compile_options(self.get_symbols(), includes)
cmd.extend(self.get_dep_option(object))
cmd.extend(self.cc_extra(object))
cmd.extend(["-o", object, source])
# Call cmdline hook
cmd = self.hook.get_cmdline_compiler(cmd)
return [cmd]
def compile_c(self, source, object, includes):
@ -218,18 +233,16 @@ class IAR(mbedToolchain):
def compile_cpp(self, source, object, includes):
return self.compile(self.cppc, source, object, includes)
@hook_tool
def link(self, output, objects, libraries, lib_dirs, mem_map):
# Build linker command
map_file = splitext(output)[0] + ".map"
cmd = self.ld + [ "-o", output, "--map=%s" % map_file] + objects + libraries
cmd = self.ld + ["-o", output, "--map=%s" % map_file]
cmd += objects
cmd += libraries
if mem_map:
cmd.extend(["--config", mem_map])
# Call cmdline hook
cmd = self.hook.get_cmdline_linker(cmd)
if self.RESPONSE_FILES:
# Split link command to linker executable + response file
cmd_linker = cmd[0]
@ -240,7 +253,6 @@ class IAR(mbedToolchain):
self.notify.cc_verbose("Link: %s" % ' '.join(cmd))
self.default_cmd(cmd)
@hook_tool
def archive(self, objects, lib_path):
if self.RESPONSE_FILES:
param = ['-f', self.get_arch_file(objects)]
@ -252,16 +264,12 @@ class IAR(mbedToolchain):
self.default_cmd([self.ar, lib_path] + param)
@hook_tool
def binary(self, resources, elf, bin):
_, fmt = splitext(bin)
bin_arg = {".bin": "--bin", ".hex": "--ihex"}[fmt]
# Build binary command
cmd = [self.elf2bin, bin_arg, elf, bin]
# Call cmdline hook
cmd = self.hook.get_cmdline_binary(cmd)
# Exec command
self.notify.cc_verbose("FromELF: %s" % ' '.join(cmd))
self.default_cmd(cmd)

1304
tools/toolchains/mbed_toolchain.py Executable file

File diff suppressed because it is too large Load Diff