diff --git a/workspace_tools/build.py b/workspace_tools/build.py index 89534408cc..9dcb1e5a90 100755 --- a/workspace_tools/build.py +++ b/workspace_tools/build.py @@ -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) diff --git a/workspace_tools/build_api.py b/workspace_tools/build_api.py index 14fc2fff12..036e6dfec1 100644 --- a/workspace_tools/build_api.py +++ b/workspace_tools/build_api.py @@ -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 diff --git a/workspace_tools/options.py b/workspace_tools/options.py index bbd26f4dd3..8db194c8fe 100644 --- a/workspace_tools/options.py +++ b/workspace_tools/options.py @@ -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 diff --git a/workspace_tools/settings.py b/workspace_tools/settings.py index 4f65c4729e..abd0db9d40 100644 --- a/workspace_tools/settings.py +++ b/workspace_tools/settings.py @@ -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