mirror of
				https://github.com/FreeRTOS/FreeRTOS-Kernel.git
				synced 2025-10-29 00:36:16 -04:00 
			
		
		
		
	
		
			
				
	
	
		
			219 lines
		
	
	
	
		
			6.3 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable file
		
	
	
	
	
			
		
		
	
	
			219 lines
		
	
	
	
		
			6.3 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable file
		
	
	
	
	
| #!/usr/bin/env python3
 | |
| 
 | |
| """
 | |
| Write a ninja build file to generate reports for cbmc proofs.
 | |
| 
 | |
| Given a list of folders containing cbmc proofs, write a ninja build
 | |
| file the generate reports for these proofs.  The list of folders may
 | |
| be given on the command line, in a json file, or found in the file
 | |
| system.
 | |
| """
 | |
| 
 | |
| # Add task pool
 | |
| 
 | |
| import sys
 | |
| import os
 | |
| import platform
 | |
| import argparse
 | |
| import json
 | |
| 
 | |
| ################################################################
 | |
| # The command line parser
 | |
| 
 | |
| def argument_parser():
 | |
|     """Return the command line parser."""
 | |
| 
 | |
|     parser = argparse.ArgumentParser(
 | |
|         description='Generate ninja build file for cbmc proofs.',
 | |
|         epilog="""
 | |
|             Given a list of folders containing cbmc proofs, write a ninja build
 | |
|             file the generate reports for these proofs.  The list of folders may
 | |
|             be given on the command line, in a json file, or found in the file
 | |
|             system.
 | |
|             In the json file, there should be a dict mapping the key "proofs"
 | |
|             to a list of folders containing proofs.
 | |
|             The file system, all folders folders under the current directory
 | |
|             containing a file named 'cbmc-batch.yaml' is considered a
 | |
|             proof folder.
 | |
|             This script assumes that the proof is driven by a Makefile
 | |
|             with targets goto, cbmc, coverage, property, and report.
 | |
|             This script does not work with Windows and Visual Studio.
 | |
|         """
 | |
|     )
 | |
|     parser.add_argument('folders', metavar='PROOF', nargs='*',
 | |
|                         help='Folder containing a cbmc proof')
 | |
|     parser.add_argument('--proofs', metavar='JSON',
 | |
|                         help='Json file listing folders containing cbmc proofs')
 | |
|     return parser
 | |
| 
 | |
| ################################################################
 | |
| # The list of folders containing proofs
 | |
| #
 | |
| # The list of folders will be taken from
 | |
| # 1. the list PROOFS defined here or
 | |
| # 2. the command line
 | |
| # 3. the json file specified on the command line containing a
 | |
| #    dict mapping the key JSON_KEY to a list of folders
 | |
| # 4. the folders below the current directory containing
 | |
| #    a file named FS_KEY
 | |
| #
 | |
| 
 | |
| PROOFS = [
 | |
| ]
 | |
| 
 | |
| JSON_KEY = 'proofs'
 | |
| FS_KEY = 'cbmc-batch.yaml'
 | |
| 
 | |
| def find_proofs_in_json_file(filename):
 | |
|     """Read the list of folders containing proofs from a json file."""
 | |
| 
 | |
|     if not filename:
 | |
|         return []
 | |
|     try:
 | |
|         with open(filename) as proofs:
 | |
|             return json.load(proofs)[JSON_KEY]
 | |
|     except (FileNotFoundError, KeyError):
 | |
|         raise UserWarning("Can't find key {} in json file {}".format(JSON_KEY, filename))
 | |
|     except json.decoder.JSONDecodeError:
 | |
|         raise UserWarning("Can't parse json file {}".format(filename))
 | |
| 
 | |
| def find_proofs_in_filesystem():
 | |
|     """Locate the folders containing proofs in the filesystem."""
 | |
| 
 | |
|     proofs = []
 | |
|     for root, _, files in os.walk('.'):
 | |
|         if FS_KEY in files:
 | |
|             proofs.append(os.path.normpath(root))
 | |
|     return proofs
 | |
| 
 | |
| ################################################################
 | |
| # The strings used to write sections of the ninja file
 | |
| 
 | |
| NINJA_RULES = """
 | |
| ################################################################
 | |
| # task pool to force sequential builds of goto binaries
 | |
| 
 | |
| pool goto_pool
 | |
|   depth = 1
 | |
| 
 | |
| ################################################################
 | |
| # proof target rules
 | |
| 
 | |
| rule build_goto
 | |
|   command = make -C ${folder} goto
 | |
|   pool = goto_pool
 | |
| 
 | |
| rule build_cbmc
 | |
|   command = make -C ${folder} cbmc
 | |
| 
 | |
| rule build_coverage
 | |
|   command = make -C ${folder} coverage
 | |
| 
 | |
| rule build_property
 | |
|   command = make -C ${folder} property
 | |
| 
 | |
| rule build_report
 | |
|   command = make -C ${folder} report
 | |
| 
 | |
| rule clean_folder
 | |
|   command = make -C ${folder} clean
 | |
| 
 | |
| rule veryclean_folder
 | |
|   command = make -C ${folder} veryclean
 | |
| 
 | |
| rule open_proof
 | |
|   command = open ${folder}/html/index.html
 | |
| 
 | |
| """
 | |
| 
 | |
| NINJA_BUILDS = """
 | |
| ################################################################
 | |
| # {folder} proof targets
 | |
| 
 | |
| build {folder}/{entry}.goto: build_goto
 | |
|   folder={folder}
 | |
| 
 | |
| build {folder}/cbmc.txt: build_cbmc {folder}/{entry}.goto
 | |
|   folder={folder}
 | |
| 
 | |
| build {folder}/coverage.xml: build_coverage {folder}/{entry}.goto
 | |
|   folder={folder}
 | |
| 
 | |
| build {folder}/property.xml: build_property {folder}/{entry}.goto
 | |
|   folder={folder}
 | |
| 
 | |
| build {folder}/html/index.html: build_report {folder}/{entry}.goto {folder}/cbmc.txt {folder}/coverage.xml {folder}/property.xml
 | |
|   folder={folder}
 | |
| 
 | |
| build clean_{folder}: clean_folder
 | |
|   folder={folder}
 | |
| 
 | |
| build veryclean_{folder}: veryclean_folder
 | |
|   folder={folder}
 | |
| 
 | |
| build open_{folder}: open_proof
 | |
|   folder={folder}
 | |
| 
 | |
| build {folder}: phony {folder}/html/index.html
 | |
| 
 | |
| default {folder}
 | |
| 
 | |
| """
 | |
| 
 | |
| NINJA_GLOBALS = """
 | |
| ################################################################
 | |
| # global targets
 | |
| 
 | |
| build clean: phony {clean_targets}
 | |
| 
 | |
| build veryclean: phony {veryclean_targets}
 | |
| 
 | |
| build open: phony {open_targets}
 | |
| """
 | |
| 
 | |
| ################################################################
 | |
| # The main function
 | |
| 
 | |
| def get_entry(folder):
 | |
|     """Find the name of the proof in the proof Makefile."""
 | |
| 
 | |
|     with open('{}/Makefile'.format(folder)) as makefile:
 | |
|         for line in makefile:
 | |
|             if line.strip().lower().startswith('entry'):
 | |
|                 return line[line.find('=')+1:].strip()
 | |
|             if line.strip().lower().startswith('h_entry'):
 | |
|                 return line[line.find('=')+1:].strip()
 | |
|     raise UserWarning("Can't find ENTRY in {}/Makefile".format(folder))
 | |
| 
 | |
| def write_ninja_build_file():
 | |
|     """Write a ninja build file to generate proof results."""
 | |
| 
 | |
|     if platform.system().lower() == 'windows':
 | |
|         print("This script does not run on Windows.")
 | |
|         sys.exit()
 | |
| 
 | |
|     args = argument_parser().parse_args()
 | |
| 
 | |
|     proofs = (PROOFS or
 | |
|               args.folders or
 | |
|               find_proofs_in_json_file(args.proofs) or
 | |
|               find_proofs_in_filesystem())
 | |
| 
 | |
|     with open('build.ninja', 'w') as ninja:
 | |
|         ninja.write(NINJA_RULES)
 | |
|         for proof in proofs:
 | |
|             entry = get_entry(proof)
 | |
|             ninja.write(NINJA_BUILDS.format(folder=proof, entry=entry))
 | |
|         targets = lambda kind, folders: ' '.join(
 | |
|             ['{}_{}'.format(kind, folder) for folder in folders]
 | |
|         )
 | |
|         ninja.write(NINJA_GLOBALS.format(
 | |
|             clean_targets=targets('clean', proofs),
 | |
|             veryclean_targets=targets('veryclean', proofs),
 | |
|             open_targets=targets('open', proofs)
 | |
|         ))
 | |
| 
 | |
| ################################################################
 | |
| 
 | |
| if __name__ == "__main__":
 | |
|     write_ninja_build_file()
 |