mirror of https://github.com/ARMmbed/mbed-os.git
Merge pull request #7247 from theotherjimmy/toolchain-version-check
Tools: Check compiler versionpull/7332/head
commit
dec43922ee
|
@ -552,6 +552,7 @@ def build_project(src_paths, build_path, target, toolchain_name,
|
||||||
src_paths, build_path, target, toolchain_name, macros=macros,
|
src_paths, build_path, target, toolchain_name, macros=macros,
|
||||||
clean=clean, jobs=jobs, notify=notify, config=config,
|
clean=clean, jobs=jobs, notify=notify, config=config,
|
||||||
app_config=app_config, build_profile=build_profile, ignore=ignore)
|
app_config=app_config, build_profile=build_profile, ignore=ignore)
|
||||||
|
toolchain.version_check()
|
||||||
|
|
||||||
# The first path will give the name to the library
|
# The first path will give the name to the library
|
||||||
name = (name or toolchain.config.name or
|
name = (name or toolchain.config.name or
|
||||||
|
|
|
@ -18,6 +18,79 @@ from tools.notifier.mock import MockNotifier
|
||||||
|
|
||||||
ALPHABET = [char for char in printable if char not in [u'.', u'/', u'\\']]
|
ALPHABET = [char for char in printable if char not in [u'.', u'/', u'\\']]
|
||||||
|
|
||||||
|
|
||||||
|
@patch('tools.toolchains.arm.run_cmd')
|
||||||
|
def test_arm_version_check(_run_cmd):
|
||||||
|
_run_cmd.return_value = ("""
|
||||||
|
Product: ARM Compiler 5.06
|
||||||
|
Component: ARM Compiler 5.06 update 5 (build 528)
|
||||||
|
Tool: armcc [4d3621]
|
||||||
|
""", "", 0)
|
||||||
|
notifier = MockNotifier()
|
||||||
|
toolchain = TOOLCHAIN_CLASSES["ARM"](TARGET_MAP["K64F"], notify=notifier)
|
||||||
|
toolchain.version_check()
|
||||||
|
assert notifier.messages == []
|
||||||
|
_run_cmd.return_value = ("""
|
||||||
|
Product: ARM Compiler
|
||||||
|
Component: ARM Compiler
|
||||||
|
Tool: armcc [4d3621]
|
||||||
|
""", "", 0)
|
||||||
|
toolchain.version_check()
|
||||||
|
assert len(notifier.messages) == 1
|
||||||
|
|
||||||
|
|
||||||
|
@patch('tools.toolchains.iar.run_cmd')
|
||||||
|
def test_iar_version_check(_run_cmd):
|
||||||
|
_run_cmd.return_value = ("""
|
||||||
|
IAR ANSI C/C++ Compiler V7.80.1.28/LNX for ARM
|
||||||
|
""", "", 0)
|
||||||
|
notifier = MockNotifier()
|
||||||
|
toolchain = TOOLCHAIN_CLASSES["IAR"](TARGET_MAP["K64F"], notify=notifier)
|
||||||
|
toolchain.version_check()
|
||||||
|
assert notifier.messages == []
|
||||||
|
_run_cmd.return_value = ("""
|
||||||
|
IAR ANSI C/C++ Compiler V/LNX for ARM
|
||||||
|
""", "", 0)
|
||||||
|
toolchain.version_check()
|
||||||
|
assert len(notifier.messages) == 1
|
||||||
|
_run_cmd.return_value = ("""
|
||||||
|
IAR ANSI C/C++ Compiler V/8.80LNX for ARM
|
||||||
|
""", "", 0)
|
||||||
|
toolchain.version_check()
|
||||||
|
assert len(notifier.messages) == 2
|
||||||
|
|
||||||
|
|
||||||
|
@patch('tools.toolchains.gcc.run_cmd')
|
||||||
|
def test_gcc_version_check(_run_cmd):
|
||||||
|
_run_cmd.return_value = ("""
|
||||||
|
arm-none-eabi-gcc (Arch Repository) 6.4.4
|
||||||
|
Copyright (C) 2018 Free Software Foundation, Inc.
|
||||||
|
This is free software; see the source for copying conditions. There is NO
|
||||||
|
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
""", "", 0)
|
||||||
|
notifier = MockNotifier()
|
||||||
|
toolchain = TOOLCHAIN_CLASSES["GCC_ARM"](
|
||||||
|
TARGET_MAP["K64F"], notify=notifier)
|
||||||
|
toolchain.version_check()
|
||||||
|
assert notifier.messages == []
|
||||||
|
_run_cmd.return_value = ("""
|
||||||
|
arm-none-eabi-gcc (Arch Repository) 8.1.0
|
||||||
|
Copyright (C) 2018 Free Software Foundation, Inc.
|
||||||
|
This is free software; see the source for copying conditions. There is NO
|
||||||
|
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
""", "", 0)
|
||||||
|
toolchain.version_check()
|
||||||
|
assert len(notifier.messages) == 1
|
||||||
|
_run_cmd.return_value = ("""
|
||||||
|
arm-none-eabi-gcc (Arch Repository)
|
||||||
|
Copyright (C) 2018 Free Software Foundation, Inc.
|
||||||
|
This is free software; see the source for copying conditions. There is NO
|
||||||
|
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
""", "", 0)
|
||||||
|
toolchain.version_check()
|
||||||
|
assert len(notifier.messages) == 2
|
||||||
|
|
||||||
|
|
||||||
@given(fixed_dictionaries({
|
@given(fixed_dictionaries({
|
||||||
'common': lists(text()),
|
'common': lists(text()),
|
||||||
'c': lists(text()),
|
'c': lists(text()),
|
||||||
|
|
|
@ -1567,6 +1567,13 @@ class mbedToolchain:
|
||||||
def get_config_macros(self):
|
def get_config_macros(self):
|
||||||
return self.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 []
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def version_check(self):
|
||||||
|
"""Check the version of a compiler being used and raise a
|
||||||
|
NotSupportedException when it's incorrect.
|
||||||
|
"""
|
||||||
|
raise NotImplemented
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def report(self):
|
def report(self):
|
||||||
to_ret = {}
|
to_ret = {}
|
||||||
|
|
|
@ -23,10 +23,11 @@ from os.path import join, dirname, splitext, basename, exists, relpath, isfile
|
||||||
from os import makedirs, write, curdir, remove
|
from os import makedirs, write, curdir, remove
|
||||||
from tempfile import mkstemp
|
from tempfile import mkstemp
|
||||||
from shutil import rmtree
|
from shutil import rmtree
|
||||||
|
from distutils.version import LooseVersion
|
||||||
|
|
||||||
from tools.toolchains import mbedToolchain, TOOLCHAIN_PATHS
|
from tools.toolchains import mbedToolchain, TOOLCHAIN_PATHS
|
||||||
from tools.hooks import hook_tool
|
from tools.hooks import hook_tool
|
||||||
from tools.utils import mkdir, NotSupportedException
|
from tools.utils import mkdir, NotSupportedException, run_cmd
|
||||||
|
|
||||||
class ARM(mbedToolchain):
|
class ARM(mbedToolchain):
|
||||||
LINKER_EXT = '.sct'
|
LINKER_EXT = '.sct'
|
||||||
|
@ -39,6 +40,8 @@ class ARM(mbedToolchain):
|
||||||
SHEBANG = "#! armcc -E"
|
SHEBANG = "#! armcc -E"
|
||||||
SUPPORTED_CORES = ["Cortex-M0", "Cortex-M0+", "Cortex-M3", "Cortex-M4",
|
SUPPORTED_CORES = ["Cortex-M0", "Cortex-M0+", "Cortex-M3", "Cortex-M4",
|
||||||
"Cortex-M4F", "Cortex-M7", "Cortex-M7F", "Cortex-M7FD", "Cortex-A9"]
|
"Cortex-M4F", "Cortex-M7", "Cortex-M7F", "Cortex-M7FD", "Cortex-A9"]
|
||||||
|
ARMCC_RANGE = (LooseVersion("5.06"), LooseVersion("5.07"))
|
||||||
|
ARMCC_VERSION_RE = re.compile("Product: ARM Compiler (\d+\.\d+)")
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def check_executable():
|
def check_executable():
|
||||||
|
@ -91,6 +94,31 @@ class ARM(mbedToolchain):
|
||||||
|
|
||||||
self.SHEBANG += " --cpu=%s" % cpu
|
self.SHEBANG += " --cpu=%s" % cpu
|
||||||
|
|
||||||
|
def version_check(self):
|
||||||
|
stdout, _, retcode = run_cmd([self.cc[0], "--vsn"], redirect=True)
|
||||||
|
msg = None
|
||||||
|
min_ver, max_ver = self.ARMCC_RANGE
|
||||||
|
match = self.ARMCC_VERSION_RE.search(stdout)
|
||||||
|
found_version = LooseVersion(match.group(1)) if match else None
|
||||||
|
min_ver, max_ver = self.ARMCC_RANGE
|
||||||
|
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))
|
||||||
|
elif not match or len(match.groups()) != 1:
|
||||||
|
msg = ("Compiler version mismatch: Could not detect version; "
|
||||||
|
"expected version >= {} and < {}"
|
||||||
|
.format(min_ver, max_ver))
|
||||||
|
|
||||||
|
if msg:
|
||||||
|
self.notify.cc_info({
|
||||||
|
"message": msg,
|
||||||
|
"file": "",
|
||||||
|
"line": "",
|
||||||
|
"col": "",
|
||||||
|
"severity": "ERROR",
|
||||||
|
})
|
||||||
|
|
||||||
def _get_toolchain_labels(self):
|
def _get_toolchain_labels(self):
|
||||||
if getattr(self.target, "default_lib", "std") == "small":
|
if getattr(self.target, "default_lib", "std") == "small":
|
||||||
return ["ARM", "ARM_MICRO"]
|
return ["ARM", "ARM_MICRO"]
|
||||||
|
@ -324,6 +352,8 @@ class ARMC6(ARM_STD):
|
||||||
"Cortex-M4F", "Cortex-M7", "Cortex-M7F", "Cortex-M7FD",
|
"Cortex-M4F", "Cortex-M7", "Cortex-M7F", "Cortex-M7FD",
|
||||||
"Cortex-M23", "Cortex-M23-NS", "Cortex-M33",
|
"Cortex-M23", "Cortex-M23-NS", "Cortex-M33",
|
||||||
"CortexM33-NS", "Cortex-A9"]
|
"CortexM33-NS", "Cortex-A9"]
|
||||||
|
ARMCC_RANGE = (LooseVersion("6.10"), LooseVersion("7.0"))
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def check_executable():
|
def check_executable():
|
||||||
return mbedToolchain.generic_check_executable("ARMC6", "armclang", 1)
|
return mbedToolchain.generic_check_executable("ARMC6", "armclang", 1)
|
||||||
|
|
|
@ -17,9 +17,11 @@ limitations under the License.
|
||||||
import re
|
import re
|
||||||
from os.path import join, basename, splitext, dirname, exists
|
from os.path import join, basename, splitext, dirname, exists
|
||||||
from distutils.spawn import find_executable
|
from distutils.spawn import find_executable
|
||||||
|
from distutils.version import LooseVersion
|
||||||
|
|
||||||
from tools.toolchains import mbedToolchain, TOOLCHAIN_PATHS
|
from tools.toolchains import mbedToolchain, TOOLCHAIN_PATHS
|
||||||
from tools.hooks import hook_tool
|
from tools.hooks import hook_tool
|
||||||
|
from tools.utils import run_cmd, NotSupportedException
|
||||||
|
|
||||||
class GCC(mbedToolchain):
|
class GCC(mbedToolchain):
|
||||||
LINKER_EXT = '.ld'
|
LINKER_EXT = '.ld'
|
||||||
|
@ -28,6 +30,9 @@ class GCC(mbedToolchain):
|
||||||
STD_LIB_NAME = "lib%s.a"
|
STD_LIB_NAME = "lib%s.a"
|
||||||
DIAGNOSTIC_PATTERN = re.compile('((?P<file>[^:]+):(?P<line>\d+):)(?P<col>\d+):? (?P<severity>warning|[eE]rror|fatal error): (?P<message>.+)')
|
DIAGNOSTIC_PATTERN = re.compile('((?P<file>[^:]+):(?P<line>\d+):)(?P<col>\d+):? (?P<severity>warning|[eE]rror|fatal error): (?P<message>.+)')
|
||||||
|
|
||||||
|
GCC_RANGE = (LooseVersion("6.0.0"), LooseVersion("7.0.0"))
|
||||||
|
GCC_VERSION_RE = re.compile("\d+\.\d+\.\d+")
|
||||||
|
|
||||||
def __init__(self, target, notify=None, macros=None, build_profile=None,
|
def __init__(self, target, notify=None, macros=None, build_profile=None,
|
||||||
build_dir=None):
|
build_dir=None):
|
||||||
mbedToolchain.__init__(self, target, notify, macros,
|
mbedToolchain.__init__(self, target, notify, macros,
|
||||||
|
@ -107,6 +112,29 @@ class GCC(mbedToolchain):
|
||||||
self.ar = join(tool_path, "arm-none-eabi-ar")
|
self.ar = join(tool_path, "arm-none-eabi-ar")
|
||||||
self.elf2bin = join(tool_path, "arm-none-eabi-objcopy")
|
self.elf2bin = join(tool_path, "arm-none-eabi-objcopy")
|
||||||
|
|
||||||
|
def version_check(self):
|
||||||
|
stdout, _, retcode = run_cmd([self.cc[0], "--version"], redirect=True)
|
||||||
|
msg = None
|
||||||
|
match = self.GCC_VERSION_RE.search(stdout)
|
||||||
|
found_version = LooseVersion(match.group(0)) if match else None
|
||||||
|
min_ver, max_ver = self.GCC_RANGE
|
||||||
|
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))
|
||||||
|
elif not match:
|
||||||
|
msg = ("Compiler version mismatch: Could not detect version; "
|
||||||
|
"expected version >= {} and < {}"
|
||||||
|
.format(min_ver, max_ver))
|
||||||
|
if msg:
|
||||||
|
self.notify.cc_info({
|
||||||
|
"message": msg,
|
||||||
|
"file": "",
|
||||||
|
"line": "",
|
||||||
|
"col": "",
|
||||||
|
"severity": "ERROR",
|
||||||
|
})
|
||||||
|
|
||||||
def is_not_supported_error(self, output):
|
def is_not_supported_error(self, output):
|
||||||
return "error: #error [NOT_SUPPORTED]" in output
|
return "error: #error [NOT_SUPPORTED]" in output
|
||||||
|
|
||||||
|
|
|
@ -17,9 +17,11 @@ limitations under the License.
|
||||||
import re
|
import re
|
||||||
from os import remove
|
from os import remove
|
||||||
from os.path import join, splitext, exists
|
from os.path import join, splitext, exists
|
||||||
|
from distutils.version import LooseVersion
|
||||||
|
|
||||||
from tools.toolchains import mbedToolchain, TOOLCHAIN_PATHS
|
from tools.toolchains import mbedToolchain, TOOLCHAIN_PATHS
|
||||||
from tools.hooks import hook_tool
|
from tools.hooks import hook_tool
|
||||||
|
from tools.utils import run_cmd, NotSupportedException
|
||||||
|
|
||||||
class IAR(mbedToolchain):
|
class IAR(mbedToolchain):
|
||||||
LIBRARY_EXT = '.a'
|
LIBRARY_EXT = '.a'
|
||||||
|
@ -28,6 +30,8 @@ class IAR(mbedToolchain):
|
||||||
|
|
||||||
DIAGNOSTIC_PATTERN = re.compile('"(?P<file>[^"]+)",(?P<line>[\d]+)\s+(?P<severity>Warning|Error|Fatal error)(?P<message>.+)')
|
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("IAR ANSI C/C\+\+ Compiler V(\d+\.\d+)")
|
||||||
|
IAR_VERSION = LooseVersion("7.80")
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def check_executable():
|
def check_executable():
|
||||||
|
@ -91,6 +95,27 @@ class IAR(mbedToolchain):
|
||||||
self.ar = join(IAR_BIN, "iarchive")
|
self.ar = join(IAR_BIN, "iarchive")
|
||||||
self.elf2bin = join(IAR_BIN, "ielftool")
|
self.elf2bin = join(IAR_BIN, "ielftool")
|
||||||
|
|
||||||
|
def version_check(self):
|
||||||
|
stdout, _, retcode = run_cmd([self.cc[0], "--version"], redirect=True)
|
||||||
|
msg = None
|
||||||
|
match = self.IAR_VERSION_RE.search(stdout)
|
||||||
|
found_version = match.group(1) if match else None
|
||||||
|
if found_version and LooseVersion(found_version) != self.IAR_VERSION:
|
||||||
|
msg = "Compiler version mismatch: Have {}; expected {}".format(
|
||||||
|
found_version, self.IAR_VERSION)
|
||||||
|
elif not match or len(match.groups()) != 1:
|
||||||
|
msg = ("Compiler version mismatch: Could Not detect compiler "
|
||||||
|
"version; expected {}".format(self.IAR_VERSION))
|
||||||
|
if msg:
|
||||||
|
self.notify.cc_info({
|
||||||
|
"message": msg,
|
||||||
|
"file": "",
|
||||||
|
"line": "",
|
||||||
|
"col": "",
|
||||||
|
"severity": "ERROR",
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
def parse_dependencies(self, dep_path):
|
def parse_dependencies(self, dep_path):
|
||||||
return [(self.CHROOT if self.CHROOT else '')+path.strip() for path in open(dep_path).readlines()
|
return [(self.CHROOT if self.CHROOT else '')+path.strip() for path in open(dep_path).readlines()
|
||||||
if (path and not path.isspace())]
|
if (path and not path.isspace())]
|
||||||
|
|
Loading…
Reference in New Issue