1#!/usr/bin/env python3 2# 3# Arm SCP/MCP Software 4# Copyright (c) 2021-2022, Arm Limited and Contributors. All rights reserved. 5# 6# SPDX-License-Identifier: BSD-3-Clause 7# 8 9""" 10 A wrapper around cppcheck which will be called from CMake's context. 11 12 CMake doesn't give any mechanism to execute any programs or 13 commands prior or after cppcheck's invocation. 14 15 Usually CMAKE_C_CPPCHECK will contain the path to cppcheck binary 16 on the build system, instead CMAKE_C_CPPCHECK will now contain 17 path to this script which in turn calls cppcheck but this enables 18 to inject any commands prior to and after actual invocation of 19 cppcheck. 20 21 One use case would be to mark cppcheck's invocation as below 22 23 [CPPCHECK] ------> 24 .... 25 .... 26 [CPPCHECK] <------ 27 28 This script also prints a warning if the version of the cppcheck 29 does not match the required version. 30 31""" 32 33import sys 34import subprocess 35import re 36 37# Holds required version info. 38required_tool_version = "1.90" 39 40tool_name = "CPPCHECK" 41 42 43# Helper function 44def print_msg(message, output): 45 if output: 46 print("[{}] {}".format(tool_name, message)) 47 48 49def main(): 50 # CMake create a list of argument which include path of the 51 # tool(e.g. cppcheck) binary and its arguments. 52 tool_path = sys.argv[1] 53 tool_args = ' '.join(sys.argv[2:]) 54 cmd = "{} {}".format(tool_path, tool_args) 55 56 # Check if output of the tool (e.g. cppcheck) is to be displayed 57 if re.search("verbose", tool_args): 58 verbose = True 59 else: 60 verbose = False 61 62 # If yes, then remove verbose string from argument list. 63 if verbose: 64 tool_args.replace("verbose", "") 65 66 # Check version 67 r = subprocess.Popen(tool_path + " --version", 68 shell=True, 69 stdout=subprocess.PIPE, 70 stderr=subprocess.PIPE) 71 72 out, err = r.communicate() 73 74 tool_version = out.decode("utf-8", "ignore") 75 76 if out: 77 print_msg("------>", output=verbose) 78 print_msg("cppcheck {}" 79 " version {} ".format(tool_path, tool_version), 80 output=verbose) 81 82 if not re.search(required_tool_version, tool_version): 83 print_msg("Warning: recommended" 84 " {} version is {}" 85 " but found {}".format(tool_name, 86 required_tool_version, 87 tool_version), 88 output=True) 89 if err: 90 print_msg("Error: failed to find" 91 " binary at {}".format(tool_path), 92 output=True) 93 return 1 94 95 print_msg(cmd, output=verbose) 96 97 r = subprocess.Popen(cmd, 98 shell=True, 99 stdout=subprocess.PIPE, 100 stderr=subprocess.PIPE) 101 102 out, err = r.communicate() 103 104 if out: 105 print_msg("" + out.decode("utf-8", "ignore"), output=verbose) 106 if err: 107 print_msg("" + err.decode("utf-8", "ignore"), output=True) 108 109 print_msg("<------", output=verbose) 110 return r.returncode 111 112 113if __name__ == '__main__': 114 sys.exit(main()) 115