BaseTools: Add two new sections for PCD in the build report
authorYonghong Zhu <yonghong.zhu@intel.com>
Wed, 23 Mar 2016 09:34:13 +0000 (17:34 +0800)
committerYonghong Zhu <yonghong.zhu@intel.com>
Tue, 29 Mar 2016 07:21:46 +0000 (15:21 +0800)
Build Spec updated to add two new sections for PCD in the build report.
1.Conditional directives section:If the DSC or FDF file contains
conditional directive statements.
2.Unused PCDs section: If the DSC or FDF file define values for PCDs that
are not used by any module and are not used in conditional directive
statements.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Yonghong Zhu <yonghong.zhu@intel.com>
Reviewed-by: Liming Gao <liming.gao@intel.com>
BaseTools/Source/Python/Common/Expression.py
BaseTools/Source/Python/Common/GlobalData.py
BaseTools/Source/Python/build/BuildReport.py

index 3c8d14e6ce5448582773d0a03c24c7c05d4383fb..7b3030c5fa08f9d1f219dbd83f3a81e338afd5d4 100644 (file)
@@ -1,7 +1,7 @@
 ## @file\r
 # This file is used to parse and evaluate expression in directive or PCD value.\r
 #\r
-# Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>\r
+# Copyright (c) 2011 - 2016, Intel Corporation. All rights reserved.<BR>\r
 # This program and the accompanying materials\r
 # are licensed and made available under the terms and conditions of the BSD License\r
 # which accompanies this distribution.    The full text of the license may be found at\r
@@ -76,6 +76,10 @@ def ReplaceExprMacro(String, Macros, ExceptionList = None):
             InQuote = True\r
         MacroStartPos = String.find('$(')\r
         if MacroStartPos < 0:\r
+            for Pcd in gPlatformPcds.keys():\r
+                if Pcd in String:\r
+                    if Pcd not in gConditionalPcds:\r
+                        gConditionalPcds.append(Pcd)\r
             continue\r
         RetStr = ''\r
         while MacroStartPos >= 0:\r
index 8f544bd1b2f5f59ceee02a4970bb644443b4ab1f..c3439ebbfcf589cbcf70e1ad9a49b76999d44008 100644 (file)
@@ -78,3 +78,6 @@ gFdfParser = None
 gTempInfs = []\r
 \r
 BuildOptionPcd = []\r
+\r
+# Pcd name for the Pcd which used in the Conditional directives\r
+gConditionalPcds = []\r
index 2dc02c2c4e056ecf792e3c0dbd0573440aa40c32..aee50fb3a2940da050676103ceaef647756eb097 100644 (file)
@@ -658,6 +658,8 @@ class PcdReport(object):
     #\r
     def __init__(self, Wa):\r
         self.AllPcds = {}\r
+        self.UnusedPcds = {}\r
+        self.ConditionalPcds = {}\r
         self.MaxLen = 0\r
         if Wa.FdfProfile:\r
             self.FdfPcdSet = Wa.FdfProfile.PcdDict\r
@@ -676,6 +678,63 @@ class PcdReport(object):
                     PcdList.append(Pcd)\r
                 if len(Pcd.TokenCName) > self.MaxLen:\r
                     self.MaxLen = len(Pcd.TokenCName)\r
+            #\r
+            # Collect the PCD defined in DSC/FDF file, but not used in module\r
+            #\r
+            UnusedPcdFullList = []\r
+            for item in Pa.Platform.Pcds:\r
+                Pcd = Pa.Platform.Pcds[item]\r
+                if not Pcd.Type:\r
+                    PcdTypeFlag = False\r
+                    for package in Pa.PackageList:\r
+                        for T in ["FixedAtBuild", "PatchableInModule", "FeatureFlag", "Dynamic", "DynamicEx"]:\r
+                            if (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, T) in package.Pcds:\r
+                                Pcd.Type = T\r
+                                PcdTypeFlag = True\r
+                                if not Pcd.DatumType:\r
+                                    Pcd.DatumType = package.Pcds[(Pcd.TokenCName, Pcd.TokenSpaceGuidCName, T)].DatumType\r
+                                break\r
+                        if PcdTypeFlag:\r
+                            break\r
+                if not Pcd.DatumType:\r
+                    PcdType = Pcd.Type\r
+                    # Try to remove Hii and Vpd suffix\r
+                    if PcdType.startswith("DynamicEx"):\r
+                        PcdType = "DynamicEx"\r
+                    elif PcdType.startswith("Dynamic"):\r
+                        PcdType = "Dynamic"\r
+                    for package in Pa.PackageList:\r
+                        if (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, PcdType) in package.Pcds:\r
+                            Pcd.DatumType = package.Pcds[(Pcd.TokenCName, Pcd.TokenSpaceGuidCName, PcdType)].DatumType\r
+                            break\r
+\r
+                PcdList = self.AllPcds.setdefault(Pcd.TokenSpaceGuidCName, {}).setdefault(Pcd.Type, [])\r
+                if Pcd not in PcdList and Pcd not in UnusedPcdFullList:\r
+                    UnusedPcdFullList.append(Pcd)\r
+                if len(Pcd.TokenCName) > self.MaxLen:\r
+                    self.MaxLen = len(Pcd.TokenCName)\r
+\r
+            if GlobalData.gConditionalPcds:\r
+                for PcdItem in GlobalData.gConditionalPcds:\r
+                    if '.' in PcdItem:\r
+                        (TokenSpaceGuidCName, TokenCName) = PcdItem.split('.')\r
+                        if (TokenCName, TokenSpaceGuidCName) in Pa.Platform.Pcds.keys():\r
+                            Pcd = Pa.Platform.Pcds[(TokenCName, TokenSpaceGuidCName)]\r
+                            PcdList = self.ConditionalPcds.setdefault(Pcd.TokenSpaceGuidCName, {}).setdefault(Pcd.Type, [])\r
+                            if Pcd not in PcdList:\r
+                                PcdList.append(Pcd)\r
+\r
+            UnusedPcdList = []\r
+            if UnusedPcdFullList:\r
+                for Pcd in UnusedPcdFullList:\r
+                    if Pcd.TokenSpaceGuidCName + '.' + Pcd.TokenCName in GlobalData.gConditionalPcds:\r
+                        continue\r
+                    UnusedPcdList.append(Pcd)\r
+\r
+            for Pcd in UnusedPcdList:\r
+                PcdList = self.UnusedPcds.setdefault(Pcd.TokenSpaceGuidCName, {}).setdefault(Pcd.Type, [])\r
+                if Pcd not in PcdList:\r
+                    PcdList.append(Pcd)\r
 \r
             for Module in Pa.Platform.Modules.values():\r
                 #\r
@@ -709,6 +768,13 @@ class PcdReport(object):
                 if DscDefaultValue:\r
                     self.DscPcdDefault[(TokenCName, TokenSpaceGuidCName)] = DscDefaultValue\r
 \r
+    def GenerateReport(self, File, ModulePcdSet):\r
+        if self.ConditionalPcds:\r
+            self.GenerateReportDetail(File, ModulePcdSet, 1)\r
+        if self.UnusedPcds:\r
+            self.GenerateReportDetail(File, ModulePcdSet, 2)\r
+        self.GenerateReportDetail(File, ModulePcdSet)\r
+\r
     ##\r
     # Generate report for PCD information\r
     #\r
@@ -719,39 +785,52 @@ class PcdReport(object):
     # @param File            The file object for report\r
     # @param ModulePcdSet    Set of all PCDs referenced by module or None for\r
     #                        platform PCD report\r
+    # @param ReportySubType  0 means platform/module PCD report, 1 means Conditional\r
+    #                        directives section report, 2 means Unused Pcds section report\r
     # @param DscOverridePcds Module DSC override PCDs set\r
     #\r
-    def GenerateReport(self, File, ModulePcdSet):\r
+    def GenerateReportDetail(self, File, ModulePcdSet, ReportSubType = 0):\r
+        PcdDict = self.AllPcds\r
+        if ReportSubType == 1:\r
+            PcdDict = self.ConditionalPcds\r
+        elif ReportSubType == 2:\r
+            PcdDict = self.UnusedPcds\r
+\r
         if ModulePcdSet == None:\r
-            #\r
-            # For platform global PCD section\r
-            #\r
             FileWrite(File, gSectionStart)\r
-            FileWrite(File, "Platform Configuration Database Report")\r
+            if ReportSubType == 1:\r
+                FileWrite(File, "Conditional Directives used by the build system")\r
+            elif ReportSubType == 2:\r
+                FileWrite(File, "PCDs not used by modules or in conditional directives")\r
+            else:\r
+                FileWrite(File, "Platform Configuration Database Report")\r
+\r
             FileWrite(File, "  *B  - PCD override in the build option")\r
             FileWrite(File, "  *P  - Platform scoped PCD override in DSC file")\r
             FileWrite(File, "  *F  - Platform scoped PCD override in FDF file")\r
-            FileWrite(File, "  *M  - Module scoped PCD override")\r
+            if not ReportSubType:\r
+                FileWrite(File, "  *M  - Module scoped PCD override")\r
             FileWrite(File, gSectionSep)\r
         else:\r
-            #\r
-            # For module PCD sub-section\r
-            #\r
-            FileWrite(File, gSubSectionStart)\r
-            FileWrite(File, TAB_BRG_PCD)\r
-            FileWrite(File, gSubSectionSep)\r
+            if not ReportSubType:\r
+                #\r
+                # For module PCD sub-section\r
+                #\r
+                FileWrite(File, gSubSectionStart)\r
+                FileWrite(File, TAB_BRG_PCD)\r
+                FileWrite(File, gSubSectionSep)\r
 \r
-        for Key in self.AllPcds:\r
+        for Key in PcdDict:\r
             #\r
             # Group PCD by their token space GUID C Name\r
             #\r
             First = True\r
-            for Type in self.AllPcds[Key]:\r
+            for Type in PcdDict[Key]:\r
                 #\r
                 # Group PCD by their usage type\r
                 #\r
                 TypeName, DecType = gPcdTypeMap.get(Type, ("", Type))\r
-                for Pcd in self.AllPcds[Key][Type]:\r
+                for Pcd in PcdDict[Key][Type]:\r
                     #\r
                     # Get PCD default value and their override relationship\r
                     #\r
@@ -869,7 +948,8 @@ class PcdReport(object):
         if ModulePcdSet == None:\r
             FileWrite(File, gSectionEnd)\r
         else:\r
-            FileWrite(File, gSubSectionEnd)\r
+            if not ReportSubType:\r
+                FileWrite(File, gSubSectionEnd)\r
 \r
 \r
 \r