2424import shlex
2525import subprocess
2626import sys
27+ import argparse
2728
29+ parser = argparse .ArgumentParser (description = "CodeChecker Bazel Wrapper" )
2830
29- EXECUTION_MODE = os . environ . get ( "RULES_CODECHECKER_MODE " , "{Mode} " )
30- VERBOSITY = os . environ . get ( "RULES_CODECHECKER_VERBOSITY " , "{Verbosity} " )
31- CODECHECKER_PATH = os . environ . get (
32- "RULES_CODECHECKER_CODECHECKER_BIN " , "{codechecker_bin} "
31+ parser . add_argument ( "--mode " , required = True , help = "Execution mode " )
32+ parser . add_argument ( "--verbosity " , default = "INFO" , help = "Log level " )
33+ parser . add_argument (
34+ "--codechecker_path " , required = True , help = "CodeChecker path "
3335)
34- CODECHECKER_SKIPFILE = os .environ .get (
35- "RULES_CODECHECKER_CODECHECKER_SKIPFILE" , "{codechecker_skipfile}"
36- )
37- CODECHECKER_CONFIG = os .environ .get (
38- "RULES_CODECHECKER_CODECHECKER_CONFIG" , "{codechecker_config}"
39- )
40- CODECHECKER_ANALYZE = os .environ .get (
41- "RULES_CODECHECKER_CODECHECKER_ANALYZE" , "{codechecker_analyze}"
42- )
43- CODECHECKER_FILES = os .environ .get (
44- "RULES_CODECHECKER_CODECHECKER_FILES" , "{codechecker_files}"
45- )
46- CODECHECKER_LOG = os .environ .get (
47- "RULES_CODECHECKER_CODECHECKER_LOG" , "{codechecker_log}"
48- )
49- CODECHECKER_SEVERITIES = os .environ .get (
50- "RULES_CODECHECKER_SEVERITIES" , "{Severities}"
51- )
52- CODECHECKER_ENV = os .environ .get (
53- "RULES_CODECHECKER_CODECHECKER_ENV" , "{codechecker_env}"
54- )
55- COMPILE_COMMANDS = os .environ .get (
56- "RULES_CODECHECKER_COMPILE_COMMANDS" , "{compile_commands}"
36+ parser .add_argument ("--commands" , help = "Compile commands json" )
37+ parser .add_argument ("--skip" , help = "Skipfile path" )
38+ parser .add_argument ("--config" , help = "Config file path" )
39+ parser .add_argument ("--analyze" , default = "" , help = "Analysis options" )
40+ parser .add_argument (
41+ "--files" , help = "Folder where CodeChecker will store its results"
5742)
43+ parser .add_argument ("--log" , help = "Log file path" )
44+ parser .add_argument ("--env" , help = "Environment for CodeChecker" )
45+ parser .add_argument ("--severities" , help = "List of severities to fail on" )
46+
47+ args = parser .parse_args ()
48+
49+ EXECUTION_MODE = args .mode
50+ VERBOSITY = args .verbosity
51+ CODECHECKER_PATH = args .codechecker_path
52+ COMPILE_COMMANDS = args .commands
53+ CODECHECKER_SKIPFILE = args .skip
54+ CODECHECKER_CONFIG = args .config
55+ CODECHECKER_ANALYZE = args .analyze
56+ CODECHECKER_FILES = args .files
57+ CODECHECKER_LOG = args .log
58+ CODECHECKER_ENV = args .env
59+ CODECHECKER_SEVERITIES = args .severities
5860
5961START_PATH = r"\/(?:(?!\.\s+)\S)+"
6062BAZEL_PATHS = {
6567
6668
6769def fail (message , exit_code = 1 ):
68- """ Print error message and return exit code """
70+ """Print error message and return exit code"""
6971 logging .error (message )
7072 print ()
7173 print ("*" * 50 )
@@ -86,27 +88,27 @@ def fail(message, exit_code=1):
8688
8789
8890def read_file (filename ):
89- """ Read text file and return its contents """
91+ """Read text file and return its contents"""
9092 if not os .path .isfile (filename ):
9193 fail (f"File not found: { filename } " )
9294 with open (filename , encoding = "utf-8" ) as handle :
9395 return handle .read ()
9496
9597
9698def separator (method = "info" ):
97- """ Print log separator line to logging.info() or other logging methods """
99+ """Print log separator line to logging.info() or other logging methods"""
98100 getattr (logging , method )("#" * 23 )
99101
100102
101103def stage (title , method = "info" ):
102- """ Print stage title into log """
104+ """Print stage title into log"""
103105 separator (method )
104106 getattr (logging , method )("### " + title )
105107 separator (method )
106108
107109
108110def valid_parameter (parameter ):
109- """ Check if external parameter is defined and valid """
111+ """Check if external parameter is defined and valid"""
110112 if parameter is None :
111113 return False
112114 if parameter and parameter [0 ] == "{" :
@@ -115,14 +117,14 @@ def valid_parameter(parameter):
115117
116118
117119def log_file_name ():
118- """ Check and return log file name """
120+ """Check and return log file name"""
119121 if valid_parameter (CODECHECKER_LOG ):
120122 return CODECHECKER_LOG
121123 return None
122124
123125
124126def setup ():
125- """ Setup logging parameters for execution session """
127+ """Setup logging parameters for execution session"""
126128 if VERBOSITY == "INFO" :
127129 log_level = logging .INFO
128130 elif VERBOSITY == "WARN" :
@@ -140,7 +142,7 @@ def setup():
140142
141143
142144def input_data ():
143- """ Print out input (external) parameters """
145+ """Print out input (external) parameters"""
144146 stage ("CodeChecker input data:" , "debug" )
145147 logging .debug ("EXECUTION_MODE : %s" , str (EXECUTION_MODE ))
146148 logging .debug ("VERBOSITY : %s" , str (VERBOSITY ))
@@ -156,7 +158,7 @@ def input_data():
156158
157159
158160def execute (cmd , env = None , codes = None ):
159- """ Execute CodeChecker commands """
161+ """Execute CodeChecker commands"""
160162 if codes is None :
161163 codes = [0 ]
162164 with subprocess .Popen (
@@ -178,20 +180,20 @@ def execute(cmd, env=None, codes=None):
178180
179181
180182def create_folder (path ):
181- """ Create folder structure for CodeChecker data files and reports """
183+ """Create folder structure for CodeChecker data files and reports"""
182184 if not os .path .exists (path ):
183185 os .makedirs (path )
184186
185187
186188def prepare ():
187- """ Prepare CodeChecker execution environment """
189+ """Prepare CodeChecker execution environment"""
188190 stage ("CodeChecker files:" )
189191 logging .info ("Creating folder: %s" , CODECHECKER_FILES )
190192 create_folder (CODECHECKER_FILES )
191193
192194
193195def analyze ():
194- """ Run CodeChecker analyze command """
196+ """Run CodeChecker analyze command"""
195197 stage ("CodeChecker analyze:" )
196198
197199 env = os .environ
@@ -207,9 +209,11 @@ def analyze():
207209 output = execute (f"{ CODECHECKER_PATH } analyzers --details" , env = env )
208210 logging .debug ("Analyzers:\n \n %s" , output )
209211
210- command = f"{ CODECHECKER_PATH } analyze --skip={ CODECHECKER_SKIPFILE } " \
211- f"{ COMPILE_COMMANDS } --output={ CODECHECKER_FILES } /data " \
212- f"--config { CODECHECKER_CONFIG } { CODECHECKER_ANALYZE } "
212+ command = (
213+ f"{ CODECHECKER_PATH } analyze --skip={ CODECHECKER_SKIPFILE } "
214+ f"{ COMPILE_COMMANDS } --output={ CODECHECKER_FILES } /data "
215+ f"--config { CODECHECKER_CONFIG } { CODECHECKER_ANALYZE } "
216+ )
213217 # FIXME: Workaround "CodeChecker simply remove compiler-rt include path".
214218 # This can be removed once codechecker 6.16.0 is used.
215219 # command += " --keep-gcc-intrin"
@@ -222,7 +226,7 @@ def analyze():
222226
223227
224228def fix_bazel_paths ():
225- """ Remove Bazel leading paths in all files """
229+ """Remove Bazel leading paths in all files"""
226230 stage ("Fix CodeChecker output:" )
227231 folder = CODECHECKER_FILES
228232 logging .info ("Fixing Bazel paths in %s" , folder )
@@ -241,7 +245,7 @@ def fix_bazel_paths():
241245
242246
243247def realpath (filename ):
244- """ Return real full absolute path for given filename """
248+ """Return real full absolute path for given filename"""
245249 if os .path .exists (filename ):
246250 real_file_name = os .path .abspath (os .path .realpath (filename ))
247251 logging .debug ("Updating %s -> %s" , filename , real_file_name )
@@ -250,7 +254,7 @@ def realpath(filename):
250254
251255
252256def resolve_plist_symlinks (filepath ):
253- """ Resolve the symbolic links in plist files to real file paths """
257+ """Resolve the symbolic links in plist files to real file paths"""
254258 # plistlib replaced readPlist/writePlist with load/dump in Python 3.9.
255259 # Since Pylint analyzes every line,
256260 # it flags the methods missing in the current environment.
@@ -274,7 +278,7 @@ def resolve_plist_symlinks(filepath):
274278
275279
276280def resolve_yaml_symlinks (filepath ):
277- """ Resolve the symbolic links in YAML files to real file paths """
281+ """Resolve the symbolic links in YAML files to real file paths"""
278282 logging .info ("Processing YAML file: %s" , filepath )
279283 fields = [
280284 r"MainSourceFile:\s*" ,
@@ -305,7 +309,7 @@ def resolve_yaml_symlinks(filepath):
305309
306310
307311def resolve_symlinks ():
308- """ Change ".../execroot/apps" paths to absolute paths in data/* files """
312+ """Change ".../execroot/apps" paths to absolute paths in data/* files"""
309313 stage ("Resolve file paths in CodeChecker analyze output:" )
310314 analyze_outdir = CODECHECKER_FILES + "/data"
311315 logging .info (
@@ -335,14 +339,18 @@ def update_file_paths():
335339
336340
337341def parse ():
338- """ Run CodeChecker parse commands """
342+ """Run CodeChecker parse commands"""
339343 stage ("CodeChecker parse:" )
340344 logging .info ("CodeChecker parse -e json" )
341- codechecker_parse = f"{ CODECHECKER_PATH } parse --config " \
342- f"{ CODECHECKER_CONFIG } { CODECHECKER_FILES } /data"
345+ codechecker_parse = (
346+ f"{ CODECHECKER_PATH } parse --config "
347+ f"{ CODECHECKER_CONFIG } { CODECHECKER_FILES } /data"
348+ )
343349 # Save results to JSON file
344- command = f"{ codechecker_parse } --export=json > " \
345- f"{ CODECHECKER_FILES } /result.json"
350+ command = (
351+ f"{ codechecker_parse } --export=json > "
352+ f"{ CODECHECKER_FILES } /result.json"
353+ )
346354 execute (command , codes = [0 , 2 ])
347355 # logging.debug(
348356 # "JSON:\n\n%s\n", read_file(CODECHECKER_FILES + "/result.json")
@@ -366,15 +374,15 @@ def parse():
366374
367375
368376def run ():
369- """ Perform all steps for "bazel build" phase """
377+ """Perform all steps for "bazel build" phase"""
370378 prepare ()
371379 analyze ()
372380 parse ()
373381 update_file_paths ()
374382
375383
376384def check_results ():
377- """ Check/verify CodeChecker results """
385+ """Check/verify CodeChecker results"""
378386 stage ("Checking result:" )
379387 # Get results file and read it
380388 result_file = CODECHECKER_FILES + "/result.txt"
@@ -421,12 +429,12 @@ def check_results():
421429
422430
423431def test ():
424- """ Perform all steps for "bazel test" phase """
432+ """Perform all steps for "bazel test" phase"""
425433 check_results ()
426434
427435
428436def main ():
429- """ Main function """
437+ """Main function"""
430438 setup ()
431439 input_data ()
432440 try :
0 commit comments