1# Copyright (c) 2021 The Linux Foundation 2# 3# SPDX-License-Identifier: Apache-2.0 4 5from subprocess import run, PIPE 6 7from west import log 8 9 10# Given a path to the applicable C compiler, a C source file, and the 11# corresponding TargetCompileGroup, determine which include files would 12# be used. 13# Arguments: 14# 1) path to applicable C compiler 15# 2) C source file being analyzed 16# 3) TargetCompileGroup for the current target 17# Returns: list of paths to include files, or [] on error or empty findings. 18def getCIncludes(compilerPath, srcFile, tcg): 19 log.dbg(f" - getting includes for {srcFile}") 20 21 # prepare fragments 22 fragments = [fr for fr in tcg.compileCommandFragments if fr.strip() != ""] 23 24 # prepare include arguments 25 includes = ["-I" + incl.path for incl in tcg.includes] 26 27 # prepare defines 28 defines = ["-D" + d.define for d in tcg.defines] 29 30 # prepare command invocation 31 cmd = [compilerPath, "-E", "-H"] + fragments + includes + defines + [srcFile] 32 33 cp = run(cmd, stdout=PIPE, stderr=PIPE, universal_newlines=True) 34 if cp.returncode != 0: 35 log.dbg(f" - calling {compilerPath} failed with error code {cp.returncode}") 36 return [] 37 else: 38 # response will be in cp.stderr, not cp.stdout 39 return extractIncludes(cp.stderr) 40 41 42# Parse the response from the CC -E -H call, to extract the include file paths 43def extractIncludes(resp): 44 includes = set() 45 46 # lines we want will start with one or more periods, followed by 47 # a space and then the include file path, e.g.: 48 # .... /home/steve/programming/zephyr/zephyrproject/zephyr/include/kernel.h 49 # the number of periods indicates the depth of nesting (for transitively- 50 # included files), but here we aren't going to care about that. We'll 51 # treat everything as tied to the corresponding source file. 52 53 # once we hit the line "Multiple include guards may be useful for:", 54 # we're done; ignore everything after that 55 56 for rline in resp.splitlines(): 57 if rline.startswith("Multiple include guards"): 58 break 59 if rline[0] == ".": 60 sline = rline.split(" ", maxsplit=1) 61 if len(sline) != 2: 62 continue 63 includes.add(sline[1]) 64 65 includesList = list(includes) 66 includesList.sort() 67 return includesList 68