1#!/usr/bin/env python3 2# SPDX-License-Identifier: GPL-2.0+ 3 4# Copyright (c) 2016 Google, Inc 5# Written by Simon Glass <sjg@chromium.org> 6# 7# Creates binary images from input files controlled by a description 8# 9 10"""See README for more information""" 11 12import os 13import site 14import sys 15import traceback 16 17# Get the absolute path to this file at run-time 18our_path = os.path.dirname(os.path.realpath(__file__)) 19our1_path = os.path.dirname(our_path) 20our2_path = os.path.dirname(our1_path) 21 22# Extract $(srctree) from Kbuild environment, or use relative paths below 23srctree = os.environ.get('srctree', our2_path) 24 25# 26# Do not pollute source tree with cache files: 27# https://stackoverflow.com/a/60024195/2511795 28# https://bugs.python.org/issue33499 29# 30sys.pycache_prefix = os.path.relpath(our_path, srctree) 31 32# Bring in the patman and dtoc libraries (but don't override the first path 33# in PYTHONPATH) 34sys.path.insert(2, our1_path) 35 36from binman import bintool 37from u_boot_pylib import test_util 38 39# Bring in the libfdt module 40sys.path.insert(2, 'scripts/dtc/pylibfdt') 41sys.path.insert(2, os.path.join(srctree, 'scripts/dtc/pylibfdt')) 42sys.path.insert(2, os.path.join(srctree, 'build-sandbox/scripts/dtc/pylibfdt')) 43sys.path.insert(2, os.path.join(srctree, 'build-sandbox_spl/scripts/dtc/pylibfdt')) 44 45from binman import cmdline 46from binman import control 47from u_boot_pylib import test_util 48 49def RunTests(debug, verbosity, processes, test_preserve_dirs, args, toolpath): 50 """Run the functional tests and any embedded doctests 51 52 Args: 53 debug: True to enable debugging, which shows a full stack trace on error 54 verbosity: Verbosity level to use 55 test_preserve_dirs: True to preserve the input directory used by tests 56 so that it can be examined afterwards (only useful for debugging 57 tests). If a single test is selected (in args[0]) it also preserves 58 the output directory for this test. Both directories are displayed 59 on the command line. 60 processes: Number of processes to use to run tests (None=same as #CPUs) 61 args: List of positional args provided to binman. This can hold a test 62 name to execute (as in 'binman test testSections', for example) 63 toolpath: List of paths to use for tools 64 """ 65 from binman import bintool_test 66 from binman import cbfs_util_test 67 from binman import elf_test 68 from binman import entry_test 69 from binman import fdt_test 70 from binman import fip_util_test 71 from binman import ftest 72 from binman import image_test 73 import doctest 74 75 test_name = args and args[0] or None 76 77 # Run the entry tests first ,since these need to be the first to import the 78 # 'entry' module. 79 result = test_util.run_test_suites( 80 'binman', debug, verbosity, False, test_preserve_dirs, processes, 81 test_name, toolpath, 82 [bintool_test.TestBintool, entry_test.TestEntry, ftest.TestFunctional, 83 fdt_test.TestFdt, elf_test.TestElf, image_test.TestImage, 84 cbfs_util_test.TestCbfs, fip_util_test.TestFip]) 85 86 return (0 if result.wasSuccessful() else 1) 87 88def RunTestCoverage(toolpath, build_dir, args): 89 """Run the tests and check that we get 100% coverage""" 90 glob_list = control.GetEntryModules(False) 91 all_set = set([os.path.splitext(os.path.basename(item))[0] 92 for item in glob_list if '_testing' not in item]) 93 extra_args = '' 94 if toolpath: 95 for path in toolpath: 96 extra_args += ' --toolpath %s' % path 97 98 # Some files unfortunately don't thave the required test coverage. This will 99 # eventually be fixed, but exclude them for now 100 test_util.run_test_coverage('tools/binman/binman', None, 101 ['*test*', '*main.py', 'tools/patman/*', 'tools/dtoc/*', 102 'tools/u_boot_pylib/*'], 103 build_dir, all_set, extra_args or None, args=args, 104 allow_failures=['tools/binman/btool/cst.py', 105 'tools/binman/etype/nxp_imx8mcst.py', 106 'tools/binman/etype/nxp_imx8mimage.py']) 107 108def RunBinman(args): 109 """Main entry point to binman once arguments are parsed 110 111 Args: 112 args: Command line arguments Namespace object 113 """ 114 ret_code = 0 115 116 if not args.debug: 117 sys.tracebacklimit = 0 118 119 # Provide a default toolpath in the hope of finding a mkimage built from 120 # current source 121 if not args.toolpath: 122 args.toolpath = ['./tools', 'build-sandbox/tools'] 123 124 if args.cmd == 'test': 125 if args.test_coverage: 126 RunTestCoverage(args.toolpath, args.build_dir, args.tests) 127 else: 128 ret_code = RunTests(args.debug, args.verbosity, args.processes, 129 args.test_preserve_dirs, args.tests, 130 args.toolpath) 131 if args.debug and not test_util.use_concurrent: 132 print('Tests can run in parallel: pip install concurrencytest') 133 134 elif args.cmd == 'bintool-docs': 135 control.write_bintool_docs(bintool.Bintool.get_tool_list()) 136 137 elif args.cmd == 'entry-docs': 138 control.WriteEntryDocs(control.GetEntryModules()) 139 140 else: 141 try: 142 ret_code = control.Binman(args) 143 except Exception as e: 144 print('binman: %s' % e, file=sys.stderr) 145 if args.debug: 146 print() 147 traceback.print_exc() 148 ret_code = 1 149 return ret_code 150 151 152def start_binman(): 153 args = cmdline.ParseArgs(sys.argv[1:]) 154 155 ret_code = RunBinman(args) 156 sys.exit(ret_code) 157 158 159if __name__ == "__main__": 160 start_binman() 161