mirror of https://github.com/ARMmbed/mbed-os.git
Integrated support for Red Lizzard's "goanna" static analysis tool
Initial support (activate with "-o analyze"). Not working well with IAR for now (partially because of a bug in goannac++ which was reported to Red Lizzard).pull/93/head
parent
330e59fb85
commit
62f1ac097d
|
@ -35,6 +35,6 @@ def get_default_options_parser():
|
||||||
help="clean the build directory")
|
help="clean the build directory")
|
||||||
|
|
||||||
parser.add_option("-o", "--options", action="append",
|
parser.add_option("-o", "--options", action="append",
|
||||||
help='Add a build option ("save-asm": save the asm generated by the compiler, "debug-info": generate debugging information)')
|
help='Add a build option ("save-asm": save the asm generated by the compiler, "debug-info": generate debugging information, "analyze": run static code analyzer")')
|
||||||
|
|
||||||
return parser
|
return parser
|
||||||
|
|
|
@ -26,6 +26,7 @@ from workspace_tools.patch import patch
|
||||||
from workspace_tools.settings import BUILD_OPTIONS
|
from workspace_tools.settings import BUILD_OPTIONS
|
||||||
|
|
||||||
import workspace_tools.hooks as hooks
|
import workspace_tools.hooks as hooks
|
||||||
|
import re
|
||||||
|
|
||||||
def print_notify(event):
|
def print_notify(event):
|
||||||
# Default command line notification
|
# Default command line notification
|
||||||
|
@ -141,7 +142,10 @@ class mbedToolchain:
|
||||||
"Cortex-M0+": ["__CORTEX_M0PLUS", "ARM_MATH_CM0"],
|
"Cortex-M0+": ["__CORTEX_M0PLUS", "ARM_MATH_CM0"],
|
||||||
"Cortex-M4" : ["__CORTEX_M4", "ARM_MATH_CM4", "__FPU_PRESENT=1"],
|
"Cortex-M4" : ["__CORTEX_M4", "ARM_MATH_CM4", "__FPU_PRESENT=1"],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GOANNA_FORMAT = "[Goanna] warning [%FILENAME%:%LINENO%] - [%CHECKNAME%(%SEVERITY%)] %MESSAGE%"
|
||||||
|
GOANNA_DIAGNOSTIC_PATTERN = re.compile(r'"\[Goanna\] (?P<severity>warning) \[(?P<file>[^:]+):(?P<line>\d+)\] \- (?P<message>.*)"')
|
||||||
|
|
||||||
def __init__(self, target, options=None, notify=None):
|
def __init__(self, target, options=None, notify=None):
|
||||||
self.target = target
|
self.target = target
|
||||||
self.name = self.__class__.__name__
|
self.name = self.__class__.__name__
|
||||||
|
@ -168,6 +172,12 @@ class mbedToolchain:
|
||||||
self.labels = None
|
self.labels = None
|
||||||
|
|
||||||
self.build_all = False
|
self.build_all = False
|
||||||
|
|
||||||
|
def goanna_parse_line(self, line):
|
||||||
|
if "analyze" in self.options:
|
||||||
|
return self.GOANNA_DIAGNOSTIC_PATTERN.match(line)
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
def get_symbols(self):
|
def get_symbols(self):
|
||||||
if self.symbols is None:
|
if self.symbols is None:
|
||||||
|
|
|
@ -20,6 +20,7 @@ from os.path import join
|
||||||
from workspace_tools.toolchains import mbedToolchain
|
from workspace_tools.toolchains import mbedToolchain
|
||||||
from workspace_tools.settings import ARM_BIN, ARM_INC, ARM_LIB, MY_ARM_CLIB, ARM_CPPLIB
|
from workspace_tools.settings import ARM_BIN, ARM_INC, ARM_LIB, MY_ARM_CLIB, ARM_CPPLIB
|
||||||
from workspace_tools.hooks import hook_tool
|
from workspace_tools.hooks import hook_tool
|
||||||
|
from workspace_tools.settings import GOANNA_PATH
|
||||||
|
|
||||||
class ARM(mbedToolchain):
|
class ARM(mbedToolchain):
|
||||||
LINKER_EXT = '.sct'
|
LINKER_EXT = '.sct'
|
||||||
|
@ -39,7 +40,8 @@ class ARM(mbedToolchain):
|
||||||
else:
|
else:
|
||||||
cpu = target.core
|
cpu = target.core
|
||||||
|
|
||||||
common = [join(ARM_BIN, "armcc"), "-c",
|
main_cc = join(ARM_BIN, "armcc")
|
||||||
|
common = ["-c",
|
||||||
"--cpu=%s" % cpu, "--gnu",
|
"--cpu=%s" % cpu, "--gnu",
|
||||||
"-Ospace", "--split_sections", "--apcs=interwork",
|
"-Ospace", "--split_sections", "--apcs=interwork",
|
||||||
"--brief_diagnostics", "--restrict"
|
"--brief_diagnostics", "--restrict"
|
||||||
|
@ -56,9 +58,13 @@ class ARM(mbedToolchain):
|
||||||
'-I%s' % ARM_INC
|
'-I%s' % ARM_INC
|
||||||
]
|
]
|
||||||
|
|
||||||
self.asm = common
|
self.asm = [main_cc] + common
|
||||||
self.cc = common + common_c + ["--c99"]
|
if not "analyze" in self.options:
|
||||||
self.cppc = common + common_c + ["--cpp", "--no_rtti"]
|
self.cc = [main_cc] + common + common_c + ["--c99"]
|
||||||
|
self.cppc = [main_cc] + common + common_c + ["--cpp", "--no_rtti"]
|
||||||
|
else:
|
||||||
|
self.cc = [join(GOANNA_PATH, "goannacc"), "--with-cc=" + main_cc.replace('\\', '/'), "--dialect=armcc", '--output-format="%s"' % self.GOANNA_FORMAT] + common + common_c + ["--c99"]
|
||||||
|
self.cppc= [join(GOANNA_PATH, "goannac++"), "--with-cxx=" + main_cc.replace('\\', '/'), "--dialect=armcc", '--output-format="%s"' % self.GOANNA_FORMAT] + common + common_c + ["--cpp", "--no_rtti"]
|
||||||
|
|
||||||
self.ld = [join(ARM_BIN, "armlink")]
|
self.ld = [join(ARM_BIN, "armlink")]
|
||||||
self.sys_libs = []
|
self.sys_libs = []
|
||||||
|
@ -92,7 +98,15 @@ class ARM(mbedToolchain):
|
||||||
match.group('line'),
|
match.group('line'),
|
||||||
match.group('message')
|
match.group('message')
|
||||||
)
|
)
|
||||||
|
match = self.goanna_parse_line(line)
|
||||||
|
if match is not None:
|
||||||
|
self.cc_info(
|
||||||
|
match.group('severity').lower(),
|
||||||
|
match.group('file'),
|
||||||
|
match.group('line'),
|
||||||
|
match.group('message')
|
||||||
|
)
|
||||||
|
|
||||||
def archive(self, objects, lib_path):
|
def archive(self, objects, lib_path):
|
||||||
self.default_cmd([self.ar, '-r', lib_path] + objects)
|
self.default_cmd([self.ar, '-r', lib_path] + objects)
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@ from os.path import join, basename, splitext
|
||||||
|
|
||||||
from workspace_tools.toolchains import mbedToolchain
|
from workspace_tools.toolchains import mbedToolchain
|
||||||
from workspace_tools.settings import GCC_ARM_PATH, GCC_CR_PATH, GCC_CS_PATH, CW_EWL_PATH, CW_GCC_PATH
|
from workspace_tools.settings import GCC_ARM_PATH, GCC_CR_PATH, GCC_CS_PATH, CW_EWL_PATH, CW_GCC_PATH
|
||||||
|
from workspace_tools.settings import GOANNA_PATH
|
||||||
|
|
||||||
class GCC(mbedToolchain):
|
class GCC(mbedToolchain):
|
||||||
LINKER_EXT = '.ld'
|
LINKER_EXT = '.ld'
|
||||||
|
@ -59,11 +59,17 @@ class GCC(mbedToolchain):
|
||||||
|
|
||||||
if "debug-info" in self.options:
|
if "debug-info" in self.options:
|
||||||
common_flags.append("-g")
|
common_flags.append("-g")
|
||||||
|
|
||||||
self.asm = [join(tool_path, "arm-none-eabi-as")] + self.cpu
|
self.asm = [join(tool_path, "arm-none-eabi-as")] + self.cpu
|
||||||
|
|
||||||
self.cc = [join(tool_path, "arm-none-eabi-gcc"), "-std=gnu99"] + common_flags
|
main_cc = join(tool_path, "arm-none-eabi-gcc")
|
||||||
self.cppc =[join(tool_path, "arm-none-eabi-g++"), "-std=gnu++98"] + common_flags
|
main_cppc = join(tool_path, "arm-none-eabi-g++")
|
||||||
|
if not "analyze" in self.options:
|
||||||
|
self.cc = [main_cc, "-std=gnu99"] + common_flags
|
||||||
|
self.cppc =[main_cppc, "-std=gnu++98"] + common_flags
|
||||||
|
else:
|
||||||
|
self.cc = [join(GOANNA_PATH, "goannacc"), "--with-cc=" + main_cc.replace('\\', '/'), "-std=gnu99", "--dialect=gnu", '--output-format="%s"' % self.GOANNA_FORMAT] + common_flags
|
||||||
|
self.cppc= [join(GOANNA_PATH, "goannac++"), "--with-cxx=" + main_cppc.replace('\\', '/'), "-std=gnu++98", "--dialect=gnu", '--output-format="%s"' % self.GOANNA_FORMAT] + common_flags
|
||||||
|
|
||||||
self.ld = [join(tool_path, "arm-none-eabi-gcc"), "-Wl,--gc-sections", "-Wl,--wrap,main"] + self.cpu
|
self.ld = [join(tool_path, "arm-none-eabi-gcc"), "-Wl,--gc-sections", "-Wl,--wrap,main"] + self.cpu
|
||||||
self.sys_libs = ["stdc++", "supc++", "m", "c", "gcc"]
|
self.sys_libs = ["stdc++", "supc++", "m", "c", "gcc"]
|
||||||
|
@ -98,6 +104,16 @@ class GCC(mbedToolchain):
|
||||||
WHERE, WHAT = 0, 1
|
WHERE, WHAT = 0, 1
|
||||||
state, file, message = WHERE, None, None
|
state, file, message = WHERE, None, None
|
||||||
for line in output.splitlines():
|
for line in output.splitlines():
|
||||||
|
match = self.goanna_parse_line(line)
|
||||||
|
if match is not None:
|
||||||
|
self.cc_info(
|
||||||
|
match.group('severity').lower(),
|
||||||
|
match.group('file'),
|
||||||
|
match.group('line'),
|
||||||
|
match.group('message')
|
||||||
|
)
|
||||||
|
continue
|
||||||
|
|
||||||
# Each line should start with the file information: "filepath: ..."
|
# Each line should start with the file information: "filepath: ..."
|
||||||
# i should point past the file path ^
|
# i should point past the file path ^
|
||||||
# avoid the first column in Windows (C:\)
|
# avoid the first column in Windows (C:\)
|
||||||
|
|
|
@ -20,7 +20,7 @@ from os.path import join, exists
|
||||||
|
|
||||||
from workspace_tools.toolchains import mbedToolchain
|
from workspace_tools.toolchains import mbedToolchain
|
||||||
from workspace_tools.settings import IAR_PATH
|
from workspace_tools.settings import IAR_PATH
|
||||||
|
from workspace_tools.settings import GOANNA_PATH
|
||||||
|
|
||||||
class IAR(mbedToolchain):
|
class IAR(mbedToolchain):
|
||||||
LIBRARY_EXT = '.a'
|
LIBRARY_EXT = '.a'
|
||||||
|
@ -49,10 +49,14 @@ class IAR(mbedToolchain):
|
||||||
c_flags.append("-r")
|
c_flags.append("-r")
|
||||||
|
|
||||||
IAR_BIN = join(IAR_PATH, "bin")
|
IAR_BIN = join(IAR_PATH, "bin")
|
||||||
|
main_cc = join(IAR_BIN, "iccarm")
|
||||||
self.asm = [join(IAR_BIN, "iasmarm")] + ["--cpu", target.core]
|
self.asm = [join(IAR_BIN, "iasmarm")] + ["--cpu", target.core]
|
||||||
self.cc = [join(IAR_BIN, "iccarm")] + c_flags
|
if not "analyze" in self.options:
|
||||||
self.cppc = [join(IAR_BIN, "iccarm"), "--c++", "--no_rtti", "--no_exceptions"] + c_flags
|
self.cc = [main_cc] + c_flags
|
||||||
|
self.cppc = [main_cc, "--c++", "--no_rtti", "--no_exceptions"] + c_flags
|
||||||
|
else:
|
||||||
|
self.cc = [join(GOANNA_PATH, "goannacc"), '--with-cc="%s"' % main_cc.replace('\\', '/'), "--dialect=iar-arm", '--output-format="%s"' % self.GOANNA_FORMAT] + c_flags
|
||||||
|
self.cppc = [join(GOANNA_PATH, "goannac++"), '--with-cxx="%s"' % main_cc.replace('\\', '/'), "--dialect=iar-arm", '--output-format="%s"' % self.GOANNA_FORMAT] + ["--c++", "--no_rtti", "--no_exceptions"] + c_flags
|
||||||
self.ld = join(IAR_BIN, "ilinkarm")
|
self.ld = join(IAR_BIN, "ilinkarm")
|
||||||
self.ar = join(IAR_BIN, "iarchive")
|
self.ar = join(IAR_BIN, "iarchive")
|
||||||
self.elf2bin = join(IAR_BIN, "ielftool")
|
self.elf2bin = join(IAR_BIN, "ielftool")
|
||||||
|
@ -67,6 +71,14 @@ class IAR(mbedToolchain):
|
||||||
match.group('line'),
|
match.group('line'),
|
||||||
match.group('message'),
|
match.group('message'),
|
||||||
)
|
)
|
||||||
|
match = self.goanna_parse_line(line)
|
||||||
|
if match is not None:
|
||||||
|
self.cc_info(
|
||||||
|
match.group('severity').lower(),
|
||||||
|
match.group('file'),
|
||||||
|
match.group('line'),
|
||||||
|
match.group('message')
|
||||||
|
)
|
||||||
|
|
||||||
def get_dep_opt(self, dep_path):
|
def get_dep_opt(self, dep_path):
|
||||||
return ["--dependencies", dep_path]
|
return ["--dependencies", dep_path]
|
||||||
|
|
Loading…
Reference in New Issue