diff options
Diffstat (limited to 'BaseTools/Source/Python/build/BuildReport.py')
-rw-r--r-- | BaseTools/Source/Python/build/BuildReport.py | 139 |
1 files changed, 138 insertions, 1 deletions
diff --git a/BaseTools/Source/Python/build/BuildReport.py b/BaseTools/Source/Python/build/BuildReport.py index 468772930c..33b43d471f 100644 --- a/BaseTools/Source/Python/build/BuildReport.py +++ b/BaseTools/Source/Python/build/BuildReport.py @@ -10,6 +10,8 @@ ## Import Modules
#
+import json
+from pathlib import Path
import Common.LongFilePathOs as os
import re
import platform
@@ -41,6 +43,7 @@ from Common.DataType import * import collections
from Common.Expression import *
from GenFds.AprioriSection import DXE_APRIORI_GUID, PEI_APRIORI_GUID
+from AutoGen.IncludesAutoGen import IncludesAutoGen
## Pattern to extract contents in EDK DXS files
gDxsDependencyPattern = re.compile(r"DEPENDENCY_START(.+)DEPENDENCY_END", re.DOTALL)
@@ -2298,6 +2301,10 @@ class BuildReport(object): def GenerateReport(self, BuildDuration, AutoGenTime, MakeTime, GenFdsTime):
if self.ReportFile:
try:
+
+ if "COMPILE_INFO" in self.ReportType:
+ self.GenerateCompileInfo()
+
File = []
for (Wa, MaList) in self.ReportList:
PlatformReport(Wa, MaList, self.ReportType).GenerateReport(File, BuildDuration, AutoGenTime, MakeTime, GenFdsTime, self.ReportType)
@@ -2310,7 +2317,137 @@ class BuildReport(object): EdkLogger.error("BuildReport", CODE_ERROR, "Unknown fatal error when generating build report", ExtraData=self.ReportFile, RaiseError=False)
EdkLogger.quiet("(Python %s on %s\n%s)" % (platform.python_version(), sys.platform, traceback.format_exc()))
+
+ ##
+ # Generates compile data files to be used by external tools.
+ # Compile information will be generated in <Build>/<BuildTarget>/<ToolChain>/CompileInfo
+ # Files generated: compile_commands.json, cscope.files, modules_report.json
+ #
+ # @param self The object pointer
+ #
+ def GenerateCompileInfo(self):
+ try:
+ # Lists for the output elements
+ compile_commands = []
+ used_files = set()
+ module_report = []
+
+ for (Wa, MaList) in self.ReportList:
+ # Obtain list of all processed Workspace files
+ for file_path in Wa._GetMetaFiles(Wa.BuildTarget, Wa.ToolChain):
+ used_files.add(file_path)
+
+ for autoGen in Wa.AutoGenObjectList:
+
+ # Loop through all modules
+ for module in (autoGen.LibraryAutoGenList + autoGen.ModuleAutoGenList):
+
+ used_files.add(module.MetaFile.Path)
+
+ # Main elements of module report
+ module_report_data = {}
+ module_report_data["Name"] = module.Name
+ module_report_data["Arch"] = module.Arch
+ module_report_data["Path"] = module.MetaFile.Path
+ module_report_data["Guid"] = module.Guid
+ module_report_data["BuildType"] = module.BuildType
+ module_report_data["IsLibrary"] = module.IsLibrary
+ module_report_data["SourceDir"] = module.SourceDir
+ module_report_data["Files"] = []
+
+ # Files used by module
+ for data_file in module.SourceFileList:
+ module_report_data["Files"].append({"Name": data_file.Name, "Path": data_file.Path})
+
+ # Libraries used by module
+ module_report_data["Libraries"] = []
+ for data_library in module.LibraryAutoGenList:
+ module_report_data["Libraries"].append({"Path": data_library.MetaFile.Path})
+
+ # Packages used by module
+ module_report_data["Packages"] = []
+ for data_package in module.PackageList:
+ module_report_data["Packages"].append({"Path": data_package.MetaFile.Path, "Includes": []})
+ # Includes path used in package
+ for data_package_include in data_package.Includes:
+ module_report_data["Packages"][-1]["Includes"].append(data_package_include.Path)
+
+ # PPI's in module
+ module_report_data["PPI"] = []
+ for data_ppi in module.PpiList.keys():
+ module_report_data["PPI"].append({"Name": data_ppi, "Guid": module.PpiList[data_ppi]})
+
+ # Protocol's in module
+ module_report_data["Protocol"] = []
+ for data_protocol in module.ProtocolList.keys():
+ module_report_data["Protocol"].append({"Name": data_protocol, "Guid": module.ProtocolList[data_protocol]})
+
+ # PCD's in module
+ module_report_data["Pcd"] = []
+ for data_pcd in module.LibraryPcdList:
+ module_report_data["Pcd"].append({"Space": data_pcd.TokenSpaceGuidCName,
+ "Name": data_pcd.TokenCName,
+ "Value": data_pcd.TokenValue,
+ "Guid": data_pcd.TokenSpaceGuidValue,
+ "DatumType": data_pcd.DatumType,
+ "Type": data_pcd.Type,
+ "DefaultValue": data_pcd.DefaultValue})
+ # Add module to report
+ module_report.append(module_report_data)
+
+ # Include file dependencies to used files
+ includes_autogen = IncludesAutoGen(module.MakeFileDir, module)
+ for dep in includes_autogen.DepsCollection:
+ used_files.add(dep)
+
+ inc_flag = "-I" # Default include flag
+ if module.BuildRuleFamily == TAB_COMPILER_MSFT:
+ inc_flag = "/I"
+
+ for source in module.SourceFileList:
+ used_files.add(source.Path)
+ compile_command = {}
+ if source.Ext in [".c", ".cc", ".cpp"]:
+ #
+ # Generate compile command for each c file
+ #
+ compile_command["file"] = source.Path
+ compile_command["directory"] = source.Dir
+ build_command = module.BuildRules[source.Ext].CommandList[0]
+ build_command_variables = re.findall(r"\$\((.*?)\)", build_command)
+ for var in build_command_variables:
+ var_tokens = var.split("_")
+ var_main = var_tokens[0]
+ if len(var_tokens) == 1:
+ var_value = module.BuildOption[var_main]["PATH"]
+ else:
+ var_value = module.BuildOption[var_main][var_tokens[1]]
+ build_command = build_command.replace(f"$({var})", var_value)
+ include_files = f" {inc_flag}".join(module.IncludePathList)
+ build_command = build_command.replace("${src}", include_files)
+ build_command = build_command.replace("${dst}", module.OutputDir)
+
+ # Remove un defined macros
+ compile_command["command"] = re.sub(r"\$\(.*?\)", "", build_command)
+ compile_commands.append(compile_command)
+
+ # Create output folder if doesn't exist
+ compile_info_folder = Path(Wa.BuildDir).joinpath("CompileInfo")
+ compile_info_folder.mkdir(exist_ok=True)
+
+ # Sort and save files
+ compile_commands.sort(key=lambda x: x["file"])
+ SaveFileOnChange(compile_info_folder.joinpath(f"compile_commands.json"),json.dumps(compile_commands, indent=2), False)
+
+ SaveFileOnChange(compile_info_folder.joinpath(f"cscope.files"), "\n".join(sorted(used_files)), False)
+
+ module_report.sort(key=lambda x: x["Path"])
+ SaveFileOnChange(compile_info_folder.joinpath(f"module_report.json"), json.dumps(module_report, indent=2), False)
+
+ except:
+ EdkLogger.error("BuildReport", CODE_ERROR, "Unknown fatal error when generating build report compile information", ExtraData=self.ReportFile, RaiseError=False)
+ EdkLogger.quiet("(Python %s on %s\n%s)" % (platform.python_version(), sys.platform, traceback.format_exc()))
+
# This acts like the main() function for the script, unless it is 'import'ed into another script.
if __name__ == '__main__':
pass
-
|