| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114 | # Copyright (c) 2021 The Linux Foundation## SPDX-License-Identifier: Apache-2.0import osimport uuidfrom west.commands import WestCommandfrom west import logfrom zspdx.sbom import SBOMConfig, makeSPDX, setupCmakeQuerySPDX_DESCRIPTION = """\This command creates an SPDX 2.2 tag-value bill of materialsfollowing the completion of a Zephyr build.Prior to the build, an empty file must be created atBUILDDIR/.cmake/api/v1/query/codemodel-v2 in order to enablethe CMake file-based API, which the SPDX command relies upon.This can be done by calling `west spdx --init` prior tocalling `west build`."""class ZephyrSpdx(WestCommand):    def __init__(self):        super().__init__(                'spdx',                'create SPDX bill of materials',                SPDX_DESCRIPTION)    def do_add_parser(self, parser_adder):        parser = parser_adder.add_parser(self.name,                help=self.help,                description = self.description)        # If you update these options, make sure to keep the docs in        # doc/guides/west/zephyr-cmds.rst up to date.        parser.add_argument('-i', '--init', action="store_true",                help="initialize CMake file-based API")        parser.add_argument('-d', '--build-dir',                help="build directory")        parser.add_argument('-n', '--namespace-prefix',                help="namespace prefix")        parser.add_argument('-s', '--spdx-dir',                help="SPDX output directory")        parser.add_argument('--analyze-includes', action="store_true",                help="also analyze included header files")        parser.add_argument('--include-sdk', action="store_true",                help="also generate SPDX document for SDK")        return parser    def do_run(self, args, unknown_args):        log.dbg(f"running zephyr SPDX generator")        log.dbg(f"  --init is", args.init)        log.dbg(f"  --build-dir is", args.build_dir)        log.dbg(f"  --namespace-prefix is", args.namespace_prefix)        log.dbg(f"  --spdx-dir is", args.spdx_dir)        log.dbg(f"  --analyze-includes is", args.analyze_includes)        log.dbg(f"  --include-sdk is", args.include_sdk)        if args.init:            do_run_init(args)        else:            do_run_spdx(args)def do_run_init(args):    log.inf("initializing Cmake file-based API prior to build")    if not args.build_dir:        log.die("Build directory not specified; call `west spdx --init --build-dir=BUILD_DIR`")    # initialize CMake file-based API - empty query file    query_ready = setupCmakeQuery(args.build_dir)    if query_ready:        log.inf("initialized; run `west build` then run `west spdx`")    else:        log.err("Couldn't create Cmake file-based API query directory")        log.err("You can manually create an empty file at $BUILDDIR/.cmake/api/v1/query/codemodel-v2")def do_run_spdx(args):    if not args.build_dir:        log.die("Build directory not specified; call `west spdx --build-dir=BUILD_DIR`")    # create the SPDX files    cfg = SBOMConfig()    cfg.buildDir = args.build_dir    if args.namespace_prefix:        cfg.namespacePrefix = args.namespace_prefix    else:        # create default namespace according to SPDX spec        # note that this is intentionally _not_ an actual URL where        # this document will be stored        cfg.namespacePrefix = f"http://spdx.org/spdxdocs/zephyr-{str(uuid.uuid4())}"    if args.spdx_dir:        cfg.spdxDir = args.spdx_dir    else:        cfg.spdxDir = os.path.join(args.build_dir, "spdx")    if args.analyze_includes:        cfg.analyzeIncludes = True    if args.include_sdk:        cfg.includeSDK = True    # make sure SPDX directory exists, or create it if it doesn't    if os.path.exists(cfg.spdxDir):        if not os.path.isdir(cfg.spdxDir):            log.err(f'SPDX output directory {cfg.spdxDir} exists but is not a directory')            return        # directory exists, we're good    else:        # create the directory        os.makedirs(cfg.spdxDir, exist_ok=False)    makeSPDX(cfg)
 |