Added CPPCHECK static analysis for MBED and CMSIS libraries from command line. Use switch --cppcheck

pull/351/head
Przemek Wirkus 2014-06-10 16:38:43 +01:00
parent 51b18186be
commit 9aaf2c1220
4 changed files with 75 additions and 41 deletions

View File

@ -31,7 +31,8 @@ from workspace_tools.targets import TARGET_NAMES, TARGET_MAP
from workspace_tools.options import get_default_options_parser
from workspace_tools.build_api import build_mbed_libs, build_lib
from workspace_tools.build_api import mcu_toolchain_matrix
from workspace_tools.build_api import static_analysis_scan
from workspace_tools.settings import CPPCHECK_CMD, CPPCHECK_MSG_FORMAT
if __name__ == '__main__':
start = time()
@ -50,14 +51,16 @@ if __name__ == '__main__':
default=False, help="Compile the USB Device library")
parser.add_option("-d", "--dsp", action="store_true", dest="dsp",
default=False, help="Compile the DSP library")
parser.add_option("-v", "--verbose", action="store_true", dest="verbose",
default=False, help="Verbose diagnostic output")
parser.add_option("-b", "--ublox", action="store_true", dest="ublox",
default=False, help="Compile the u-blox library")
parser.add_option("-D", "", action="append", dest="macros",
help="Add a macro definition")
parser.add_option("-S", "--supported-toolchains", action="store_true", dest="supported_toolchains",
default=False, help="Displays supported matrix of MCUs and toolchains")
parser.add_option("", "--cppcheck", action="store_true", dest="cppcheck_validation",
default=False, help="Forces 'cppcheck' static code analysis")
parser.add_option("-v", "--verbose", action="store_true", dest="verbose",
default=False, help="Verbose diagnostic output")
parser.add_option("-x", "--extra-verbose-notifications", action="store_true", dest="extra_verbose_notify",
default=False, help="Makes compiler more verbose, CI friendly.")
(options, args) = parser.parse_args()
@ -106,41 +109,64 @@ if __name__ == '__main__':
if options.ublox:
libraries.extend(["rtx", "rtos", "usb_host", "ublox"])
# Build
# Build results
failures = []
successes = []
for toolchain in toolchains:
for target in targets:
id = "%s::%s" % (toolchain, target)
try:
mcu = TARGET_MAP[target]
notify = print_notify_verbose if options.extra_verbose_notify else None # Special notify for CI (more verbose)
build_mbed_libs(mcu, toolchain, options=options.options,
notify=notify, verbose=options.verbose, clean=options.clean,
macros=options.macros)
for lib_id in libraries:
notify = print_notify_verbose if options.extra_verbose_notify else None # Special notify for CI (more verbose)
build_lib(lib_id, mcu, toolchain, options=options.options,
notify=notify, verbose=options.verbose, clean=options.clean,
macros=options.macros)
successes.append(id)
except Exception, e:
if options.verbose:
import sys, traceback
traceback.print_exc(file=sys.stdout)
sys.exit(1)
failures.append(id)
print e
# CPPCHECK code validation
if options.cppcheck_validation:
for toolchain in toolchains:
for target in targets:
try:
mcu = TARGET_MAP[target]
# CMSIS and MBED libs analysis
static_analysis_scan(mcu, toolchain, CPPCHECK_CMD, CPPCHECK_MSG_FORMAT, verbose=options.verbose)
for lib_id in libraries:
# Static check for library
pass
except Exception, e:
if options.verbose:
import traceback
traceback.print_exc(file=sys.stdout)
sys.exit(1)
print e
else:
# Build
for toolchain in toolchains:
for target in targets:
tt_id = "%s::%s" % (toolchain, target)
try:
mcu = TARGET_MAP[target]
notify = print_notify_verbose if options.extra_verbose_notify else None # Special notify for CI (more verbose)
build_mbed_libs(mcu, toolchain, options=options.options,
notify=notify, verbose=options.verbose, clean=options.clean,
macros=options.macros)
for lib_id in libraries:
notify = print_notify_verbose if options.extra_verbose_notify else None # Special notify for CI (more verbose)
build_lib(lib_id, mcu, toolchain, options=options.options,
notify=notify, verbose=options.verbose, clean=options.clean,
macros=options.macros)
successes.append(tt_id)
except Exception, e:
if options.verbose:
import traceback
traceback.print_exc(file=sys.stdout)
sys.exit(1)
failures.append(tt_id)
print e
# Write summary of the builds
print "\n\nCompleted in: (%.2f)s" % (time() - start)
print "Completed in: (%.2f)s" % (time() - start)
print
if successes:
print "\n\nBuild successes:"
print "Build successes:"
print
print "\n".join([" * %s" % s for s in successes])
if failures:
print "\n\nBuild failures:"
print "Build failures:"
print
print "\n".join([" * %s" % f for f in failures])
sys.exit(1)

View File

@ -239,7 +239,7 @@ def mcu_toolchain_matrix():
print "Total permutations: %d"% (perm_counter)
def static_analysis_scan(target, toolchain_name, options=None, verbose=False, clean=False, macros=None, notify=None):
def static_analysis_scan(target, toolchain_name, CPPCHECK_CMD, CPPCHECK_MSG_FORMAT, options=None, verbose=False, clean=False, macros=None, notify=None):
# Toolchain
toolchain = TOOLCHAIN_CLASSES[toolchain_name](target, options, macros=macros, notify=notify)
toolchain.VERBOSE = verbose
@ -254,22 +254,22 @@ def static_analysis_scan(target, toolchain_name, options=None, verbose=False, cl
mkdir(TMP_PATH)
# CMSIS
toolchain.info("\n>>>> SCANNING %s (%s, %s)" % ('CMSIS', target.name, toolchain_name))
toolchain.info(">>>> STATIC ANALYSIS FOR %s (%s, %s)" % ('CMSIS', target.name, toolchain_name))
cmsis_src = join(MBED_TARGETS_PATH, "cmsis")
resources = toolchain.scan_resources(cmsis_src)
# Copy files before analysis
toolchain.copy_files(resources.headers, BUILD_TARGET)
toolchain.copy_files(resources.linker_script, BUILD_TOOLCHAIN)
# Gather include paths, c, cpp sources and macros to transfer to cppcheck command line
includes = ["-I%s " % i for i in resources.inc_dirs]
includes.append(" -I%s "% str(BUILD_TARGET))
c_sources = " ".join(resources.c_sources)
cpp_sources = " ".join(resources.cpp_sources)
macros = ['-D%s ' % s for s in toolchain.get_symbols() + toolchain.macros]
CPPCHECK_MSG_FORMAT = ["--template=\"[{severity}] {file}@{line}: {id}:{message}\"", "--xml"]
check_cmd = 'cppcheck --enable=style '
check_cmd = " ".join(CPPCHECK_CMD) + " "
check_cmd += " ".join(CPPCHECK_MSG_FORMAT) + " "
check_cmd += " ".join(includes)
check_cmd += " ".join(macros)
@ -280,11 +280,12 @@ def static_analysis_scan(target, toolchain_name, options=None, verbose=False, cl
#['cppcheck', includes, c_sources, cpp_sources]
stdout, stderr, rc = run_cmd(check_cmd)
print stdout
if verbose:
print stdout
print stderr
# MBED
toolchain.info("\n>>> BUILD LIBRARY %s (%s, %s)" % ('MBED', target.name, toolchain_name))
toolchain.info(">>> STATIC ANALYSIS FOR %s (%s, %s)" % ('MBED', target.name, toolchain_name))
# Common Headers
toolchain.copy_files(toolchain.scan_resources(MBED_API).headers, MBED_LIBRARIES)
@ -293,6 +294,8 @@ def static_analysis_scan(target, toolchain_name, options=None, verbose=False, cl
# Target specific sources
HAL_SRC = join(MBED_TARGETS_PATH, "hal")
hal_implementation = toolchain.scan_resources(HAL_SRC)
# Copy files before analysis
toolchain.copy_files(hal_implementation.headers + hal_implementation.hex_files, BUILD_TARGET, HAL_SRC)
incdirs = toolchain.scan_resources(BUILD_TARGET)
@ -303,10 +306,10 @@ def static_analysis_scan(target, toolchain_name, options=None, verbose=False, cl
target_cpp_sources = " ".join(incdirs.cpp_sources)
target_macros = ['-D%s ' % s for s in toolchain.get_symbols() + toolchain.macros]
# Common Sources
mbed_resources = toolchain.scan_resources(MBED_COMMON)
# Gather include paths, c, cpp sources and macros to transfer to cppcheck command line
mbed_includes = ["-I%s " % i for i in mbed_resources.inc_dirs]
mbed_includes.append(" -I%s "% str(BUILD_TARGET))
mbed_includes.append(" -I%s "% str(MBED_COMMON))
@ -315,7 +318,8 @@ def static_analysis_scan(target, toolchain_name, options=None, verbose=False, cl
mbed_c_sources = " ".join(mbed_resources.c_sources)
mbed_cpp_sources = " ".join(mbed_resources.cpp_sources)
check_cmd = 'cppcheck --enable=all ' + " ".join(CPPCHECK_MSG_FORMAT) + " "
check_cmd = " ".join(CPPCHECK_CMD) + " "
check_cmd += " ".join(CPPCHECK_MSG_FORMAT) + " "
check_cmd += " ".join(target_includes)
check_cmd += " ".join(mbed_includes)
check_cmd += " ".join(target_macros)
@ -328,5 +332,6 @@ def static_analysis_scan(target, toolchain_name, options=None, verbose=False, cl
#['cppcheck', includes, c_sources, cpp_sources]
stdout, stderr, rc = run_cmd(check_cmd)
print stdout
if verbose:
print stdout
print stderr

View File

@ -15,7 +15,6 @@ See the License for the specific language governing permissions and
limitations under the License.
"""
from optparse import OptionParser
from workspace_tools.toolchains import TOOLCHAINS
from workspace_tools.targets import TARGET_NAMES
@ -35,6 +34,6 @@ def get_default_options_parser():
help="clean the build directory")
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, "analyze": run static code analyzer")')
help='Add a build option ("save-asm": save the asm generated by the compiler, "debug-info": generate debugging information, "analyze": run Goanna static code analyzer")')
return parser

View File

@ -71,6 +71,10 @@ CW_EWL_PATH = "C:/Freescale/CW MCU v10.3/MCU/ARM_GCC_Support/ewl/lib"
# Goanna static analyzer
GOANNA_PATH = "c:/Program Files (x86)/RedLizards/Goanna Central 3.1.4/bin"
# cppcheck path (command) and output message format
CPPCHECK_CMD = ["cppcheck", "--enable=all"]
CPPCHECK_MSG_FORMAT = ["--template=\"[{severity}] {file}@{line}: {id}:{message}\""]
BUILD_OPTIONS = []
# mbed.org username