[edk2] [Patch] BaseTools: Improve build performance

BobCF posted 1 patch 6 years, 2 months ago
Failed in applying to current master (apply log)
BaseTools/Source/Python/Workspace/DscBuildData.py | 140 +++++++++++-----------
1 file changed, 71 insertions(+), 69 deletions(-)
[edk2] [Patch] BaseTools: Improve build performance
Posted by BobCF 6 years, 2 months ago
Add cache for building PcdValueInit.c.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Yonghong Zhu <yonghong.zhu@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
---
 BaseTools/Source/Python/Workspace/DscBuildData.py | 140 +++++++++++-----------
 1 file changed, 71 insertions(+), 69 deletions(-)

diff --git a/BaseTools/Source/Python/Workspace/DscBuildData.py b/BaseTools/Source/Python/Workspace/DscBuildData.py
index 0da3efbb43..6d8486aa19 100644
--- a/BaseTools/Source/Python/Workspace/DscBuildData.py
+++ b/BaseTools/Source/Python/Workspace/DscBuildData.py
@@ -35,10 +35,11 @@ from Common.Misc import ProcessDuplicatedInf
 import re
 from Common.Parsing import IsValidWord
 from Common.VariableAttributes import VariableAttributes
 import Common.GlobalData as GlobalData
 import subprocess
+from Common.Misc import SaveFileOnChange
 from Workspace.BuildClassObject import PlatformBuildClassObject, StructurePcd, PcdClassObject, ModuleBuildClassObject
 
 #
 # Treat CHAR16 as a synonym for UINT16.  CHAR16 support is required for VFR C structs
 #
@@ -1815,13 +1816,11 @@ class DscBuildData(PlatformBuildClassObject):
         CApp = CApp + PcdMainCEntry + '\n'
 
         if not os.path.exists(self.OutputPath):
             os.makedirs(self.OutputPath)
         CAppBaseFileName = os.path.join(self.OutputPath, PcdValueInitName)
-        File = open (CAppBaseFileName + '.c', 'w')
-        File.write(CApp)
-        File.close()
+        SaveFileOnChange(CAppBaseFileName + '.c', CApp, False)
 
         MakeApp = PcdMakefileHeader
         if sys.platform == "win32":
             MakeApp = MakeApp + 'ARCH = IA32\nAPPNAME = %s\n' % (PcdValueInitName) + 'OBJECTS = %s\%s.obj\n' % (self.OutputPath, PcdValueInitName) + 'INC = '
         else:
@@ -1897,92 +1896,95 @@ class DscBuildData(PlatformBuildClassObject):
         MakeApp += CC_FLAGS
 
         if sys.platform == "win32":
             MakeApp = MakeApp + PcdMakefileEnd
         MakeFileName = os.path.join(self.OutputPath, 'Makefile')
-        File = open (MakeFileName, 'w')
-        File.write(MakeApp)
-        File.close()
+        SaveFileOnChange(MakeFileName, MakeApp, False)
 
         InputValueFile = os.path.join(self.OutputPath, 'Input.txt')
         OutputValueFile = os.path.join(self.OutputPath, 'Output.txt')
-        File = open (InputValueFile, 'w')
-        File.write(InitByteValue)
-        File.close()
-
-        Messages = ''
-        if sys.platform == "win32":
-            MakeCommand = 'nmake clean & nmake -f %s' % (MakeFileName)
-            returncode, StdOut, StdErr = self.ExecuteCommand (MakeCommand)
-            Messages = StdOut
-        else:
-            MakeCommand = 'make clean & make -f %s' % (MakeFileName)
-            returncode, StdOut, StdErr = self.ExecuteCommand (MakeCommand)
-            Messages = StdErr
-        Messages = Messages.split('\n')
-        MessageGroup = []
-        if returncode <>0:
-            CAppBaseFileName = os.path.join(self.OutputPath, PcdValueInitName)
-            File = open (CAppBaseFileName + '.c', 'r')
-            FileData = File.readlines()
-            File.close()
-            for Message in Messages:
-                if " error" in Message or "warning" in Message:
-                    FileInfo = Message.strip().split('(')
-                    if len (FileInfo) > 1:
-                        FileName = FileInfo [0]
-                        FileLine = FileInfo [1].split (')')[0]
-                    else:
-                        FileInfo = Message.strip().split(':')
-                        FileName = FileInfo [0]
-                        FileLine = FileInfo [1]
-                    if FileLine.isdigit():
-                        error_line = FileData[int (FileLine) - 1]
-                        if r"//" in error_line:
-                            c_line,dsc_line = error_line.split(r"//")
-                        else:
-                            dsc_line = error_line
-                        message_itmes = Message.split(":")
-                        Index = 0
-                        if "PcdValueInit.c" not in Message:
-                            break
-                        else:
-                            for item in message_itmes:
-                                if "PcdValueInit.c" in item:
-                                    Index = message_itmes.index(item)
-                                    message_itmes[Index] = dsc_line.strip()
-                                    break
-                            MessageGroup.append(":".join(message_itmes[Index:]).strip())
-                            continue
-                    else:
-                        MessageGroup.append(Message)
-            if MessageGroup:
-                EdkLogger.error("build", PCD_STRUCTURE_PCD_ERROR, "\n".join(MessageGroup) )
-            else:
-                EdkLogger.error('Build', COMMAND_FAILURE, 'Can not execute command: %s' % MakeCommand)
+        SaveFileOnChange(InputValueFile, InitByteValue, False)
 
         PcdValueInitExe = PcdValueInitName
         if not sys.platform == "win32":
             PcdValueInitExe = os.path.join(os.getenv("EDK_TOOLS_PATH"), 'Source', 'C', 'bin', PcdValueInitName)
-
-        Command = PcdValueInitExe + ' -i %s -o %s' % (InputValueFile, OutputValueFile)
-        returncode, StdOut, StdErr = self.ExecuteCommand (Command)
-        if returncode <> 0:
-            EdkLogger.warn('Build', COMMAND_FAILURE, 'Can not collect output from command: %s' % Command)
-            FileBuffer = []
         else:
-            File = open (OutputValueFile, 'r')
-            FileBuffer = File.readlines()
-            File.close()
+            PcdValueInitExe = os.path.join(os.getenv("EDK_TOOLS_PATH"), 'Bin', 'Win32', PcdValueInitName) +".exe"
+        if not os.path.exists(PcdValueInitExe) or self.NeedUpdateOutput(OutputValueFile, CAppBaseFileName + '.c'):
+            Messages = ''
+            if sys.platform == "win32":
+                MakeCommand = 'nmake clean & nmake -f %s' % (MakeFileName)
+                returncode, StdOut, StdErr = self.ExecuteCommand (MakeCommand)
+                Messages = StdOut
+            else:
+                MakeCommand = 'make clean & make -f %s' % (MakeFileName)
+                returncode, StdOut, StdErr = self.ExecuteCommand (MakeCommand)
+                Messages = StdErr
+            Messages = Messages.split('\n')
+            MessageGroup = []
+            if returncode <>0:
+                CAppBaseFileName = os.path.join(self.OutputPath, PcdValueInitName)
+                File = open (CAppBaseFileName + '.c', 'r')
+                FileData = File.readlines()
+                File.close()
+                for Message in Messages:
+                    if " error" in Message or "warning" in Message:
+                        FileInfo = Message.strip().split('(')
+                        if len (FileInfo) > 1:
+                            FileName = FileInfo [0]
+                            FileLine = FileInfo [1].split (')')[0]
+                        else:
+                            FileInfo = Message.strip().split(':')
+                            FileName = FileInfo [0]
+                            FileLine = FileInfo [1]
+                        if FileLine.isdigit():
+                            error_line = FileData[int (FileLine) - 1]
+                            if r"//" in error_line:
+                                c_line,dsc_line = error_line.split(r"//")
+                            else:
+                                dsc_line = error_line
+                            message_itmes = Message.split(":")
+                            Index = 0
+                            if "PcdValueInit.c" not in Message:
+                                break
+                            else:
+                                for item in message_itmes:
+                                    if "PcdValueInit.c" in item:
+                                        Index = message_itmes.index(item)
+                                        message_itmes[Index] = dsc_line.strip()
+                                        break
+                                MessageGroup.append(":".join(message_itmes[Index:]).strip())
+                                continue
+                        else:
+                            MessageGroup.append(Message)
+                if MessageGroup:
+                    EdkLogger.error("build", PCD_STRUCTURE_PCD_ERROR, "\n".join(MessageGroup) )
+                else:
+                    EdkLogger.error('Build', COMMAND_FAILURE, 'Can not execute command: %s' % MakeCommand)
+            Command = PcdValueInitExe + ' -i %s -o %s' % (InputValueFile, OutputValueFile)
+            returncode, StdOut, StdErr = self.ExecuteCommand (Command)
+            if returncode <> 0:
+                EdkLogger.warn('Build', COMMAND_FAILURE, 'Can not collect output from command: %s' % Command)
+
+        File = open (OutputValueFile, 'r')
+        FileBuffer = File.readlines()
+        File.close()
 
         StructurePcdSet = []
         for Pcd in FileBuffer:
             PcdValue = Pcd.split ('|')
             PcdInfo = PcdValue[0].split ('.')
             StructurePcdSet.append((PcdInfo[0],PcdInfo[1], PcdInfo[2], PcdInfo[3], PcdValue[2].strip()))
         return StructurePcdSet
 
+    def NeedUpdateOutput(self,OutputFile, ValueCFile):
+        if not os.path.exists(OutputFile):
+            return True
+        if os.stat(OutputFile).st_mtime <= os.stat(ValueCFile).st_mtime:
+            return True
+        return False
+
     ## Retrieve dynamic PCD settings
     #
     #   @param  Type    PCD type
     #
     #   @retval a dict object contains settings of given PCD type
-- 
2.14.3.windows.1

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel