1# Copyright (c) 2020, 2021 The Linux Foundation 2# 3# SPDX-License-Identifier: Apache-2.0 4 5import os 6 7from west import log 8 9from zspdx.walker import WalkerConfig, Walker 10from zspdx.scanner import ScannerConfig, scanDocument 11from zspdx.writer import writeSPDX 12 13 14# SBOMConfig contains settings that will be passed along to the various 15# SBOM maker subcomponents. 16class SBOMConfig: 17 def __init__(self): 18 super(SBOMConfig, self).__init__() 19 20 # prefix for Document namespaces; should not end with "/" 21 self.namespacePrefix = "" 22 23 # location of build directory 24 self.buildDir = "" 25 26 # location of SPDX document output directory 27 self.spdxDir = "" 28 29 # should also analyze for included header files? 30 self.analyzeIncludes = False 31 32 # should also add an SPDX document for the SDK? 33 self.includeSDK = False 34 35 36# create Cmake file-based API directories and query file 37# Arguments: 38# 1) build_dir: build directory 39def setupCmakeQuery(build_dir): 40 # check that query dir exists as a directory, or else create it 41 cmakeApiDirPath = os.path.join(build_dir, ".cmake", "api", "v1", "query") 42 if os.path.exists(cmakeApiDirPath): 43 if not os.path.isdir(cmakeApiDirPath): 44 log.err(f'cmake api query directory {cmakeApiDirPath} exists and is not a directory') 45 return False 46 # directory exists, we're good 47 else: 48 # create the directory 49 os.makedirs(cmakeApiDirPath, exist_ok=False) 50 51 # check that codemodel-v2 exists as a file, or else create it 52 queryFilePath = os.path.join(cmakeApiDirPath, "codemodel-v2") 53 if os.path.exists(queryFilePath): 54 if not os.path.isfile(queryFilePath): 55 log.err(f'cmake api query file {queryFilePath} exists and is not a directory') 56 return False 57 # file exists, we're good 58 return True 59 else: 60 # file doesn't exist, let's create an empty file 61 cm_fd = open(queryFilePath, "w") 62 cm_fd.close() 63 return True 64 65 66# main entry point for SBOM maker 67# Arguments: 68# 1) cfg: SBOMConfig 69def makeSPDX(cfg): 70 # report any odd configuration settings 71 if cfg.analyzeIncludes and not cfg.includeSDK: 72 log.wrn(f"config: requested to analyze includes but not to generate SDK SPDX document;") 73 log.wrn(f"config: will proceed but will discard detected includes for SDK header files") 74 75 # set up walker configuration 76 walkerCfg = WalkerConfig() 77 walkerCfg.namespacePrefix = cfg.namespacePrefix 78 walkerCfg.buildDir = cfg.buildDir 79 walkerCfg.analyzeIncludes = cfg.analyzeIncludes 80 walkerCfg.includeSDK = cfg.includeSDK 81 82 # make and run the walker 83 w = Walker(walkerCfg) 84 retval = w.makeDocuments() 85 if not retval: 86 log.err("SPDX walker failed; bailing") 87 return False 88 89 # set up scanner configuration 90 scannerCfg = ScannerConfig() 91 92 # scan each document from walker 93 if cfg.includeSDK: 94 scanDocument(scannerCfg, w.docSDK) 95 scanDocument(scannerCfg, w.docApp) 96 scanDocument(scannerCfg, w.docZephyr) 97 scanDocument(scannerCfg, w.docBuild) 98 99 # write each document, in this particular order so that the 100 # hashes for external references are calculated 101 102 # write SDK document, if we made one 103 if cfg.includeSDK: 104 retval = writeSPDX(os.path.join(cfg.spdxDir, "sdk.spdx"), w.docSDK) 105 if not retval: 106 log.err("SPDX writer failed for SDK document; bailing") 107 return False 108 109 # write app document 110 retval = writeSPDX(os.path.join(cfg.spdxDir, "app.spdx"), w.docApp) 111 if not retval: 112 log.err("SPDX writer failed for app document; bailing") 113 return False 114 115 # write zephyr document 116 writeSPDX(os.path.join(cfg.spdxDir, "zephyr.spdx"), w.docZephyr) 117 if not retval: 118 log.err("SPDX writer failed for zephyr document; bailing") 119 return False 120 121 # write build document 122 writeSPDX(os.path.join(cfg.spdxDir, "build.spdx"), w.docBuild) 123 if not retval: 124 log.err("SPDX writer failed for build document; bailing") 125 return False 126 127 # write modules document 128 writeSPDX(os.path.join(cfg.spdxDir, "modules-deps.spdx"), w.docModulesExtRefs) 129 if not retval: 130 log.err("SPDX writer failed for modules-deps document; bailing") 131 return False 132 133 return True 134