BaseTools/build: Expand PREBUILD/POSTBUILD DSC actions
authorMichael D Kinney <michael.d.kinney@intel.com>
Wed, 2 Aug 2017 21:07:05 +0000 (14:07 -0700)
committerMichael D Kinney <michael.d.kinney@intel.com>
Fri, 11 Aug 2017 18:20:37 +0000 (11:20 -0700)
https://bugzilla.tianocore.org/show_bug.cgi?id=670

* Extend PREBUILD/POSTBUILD define values to support more than
  one argument.
* Delay normalization of PREBUILD/POSTBUILD define values
  until all arguments in the define values can be processed.
* Convert PREBUILD/POSTBUILD build define value arguments
  that are WORKSPACE or PACKAGES_PATH relative paths to
  absolute paths.
* Append -p PlatformFile, --conf=ConfDirectory, and build target
  flags to command line used to execute PREBUILD/POSTBUILD
  actions.
* Remove PrebuildScript and PostbuildScript fields from the
  Build class and use Prebuild and Postbuild fields instead.

Cc: Liming Gao <liming.gao@intel.com>
Cc: Yonghong Zhu <yonghong.zhu@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Michael Kinney <michael.d.kinney@intel.com>
Reviewed-by: Yonghong Zhu <yonghong.zhu@intel.com>
BaseTools/Source/Python/Workspace/WorkspaceDatabase.py
BaseTools/Source/Python/build/build.py

index 73b3fe7..fe2c7c1 100644 (file)
@@ -237,7 +237,7 @@ class DscBuildData(PlatformBuildClassObject):
                         EdkLogger.error('build', FORMAT_INVALID, 'Missing double quotes in the end of %s statement.' % TAB_DSC_PREBUILD,\r
                                     File=self.MetaFile, Line=Record[-1])\r
                     PrebuildValue = Record[2][1:-1]\r
-                self._Prebuild = PathClass(NormPath(PrebuildValue, self._Macros), GlobalData.gWorkspace)\r
+                self._Prebuild = PrebuildValue\r
             elif Name == TAB_DSC_POSTBUILD:\r
                 PostbuildValue = Record[2]\r
                 if Record[2][0] == '"':\r
@@ -245,7 +245,7 @@ class DscBuildData(PlatformBuildClassObject):
                         EdkLogger.error('build', FORMAT_INVALID, 'Missing double quotes in the end of %s statement.' % TAB_DSC_POSTBUILD,\r
                                     File=self.MetaFile, Line=Record[-1])\r
                     PostbuildValue = Record[2][1:-1]\r
-                self._Postbuild = PathClass(NormPath(PostbuildValue, self._Macros), GlobalData.gWorkspace)\r
+                self._Postbuild = PostbuildValue\r
             elif Name == TAB_DSC_DEFINES_SUPPORTED_ARCHITECTURES:\r
                 self._SupArchList = GetSplitValueList(Record[2], TAB_VALUE_SPLIT)\r
             elif Name == TAB_DSC_DEFINES_BUILD_TARGETS:\r
index 4d05ee2..7436453 100644 (file)
@@ -796,8 +796,6 @@ class Build():
         self.BuildModules = []\r
         self.Db_Flag = False\r
         self.LaunchPrebuildFlag = False\r
-        self.PrebuildScript = ''\r
-        self.PostbuildScript = ''\r
         self.PlatformBuildPath = os.path.join(GlobalData.gConfDirectory,'.cache', '.PlatformBuild')\r
         if BuildOptions.CommandLength:\r
             GlobalData.gCommandMaxLength = BuildOptions.CommandLength\r
@@ -819,11 +817,11 @@ class Build():
         EdkLogger.quiet("%-16s = %s" % ("CONF_PATH", GlobalData.gConfDirectory))\r
         self.InitPreBuild()\r
         self.InitPostBuild()\r
-        if self.PrebuildScript:\r
-            EdkLogger.quiet("%-16s = %s" % ("PREBUILD", self.PrebuildScript))\r
-        if self.PostbuildScript:\r
-            EdkLogger.quiet("%-16s = %s" % ("POSTBUILD", self.PostbuildScript))\r
-        if self.PrebuildScript:\r
+        if self.Prebuild:\r
+            EdkLogger.quiet("%-16s = %s" % ("PREBUILD", self.Prebuild))\r
+        if self.Postbuild:\r
+            EdkLogger.quiet("%-16s = %s" % ("POSTBUILD", self.Postbuild))\r
+        if self.Prebuild:\r
             self.LaunchPrebuild()\r
             self.TargetTxt = TargetTxtClassObject()\r
             self.ToolDef   = ToolDefClassObject()\r
@@ -964,16 +962,37 @@ class Build():
             Platform = self.Db._MapPlatform(str(self.PlatformFile))\r
             self.Prebuild = str(Platform.Prebuild)\r
         if self.Prebuild:\r
-            PrebuildList = self.Prebuild.split()\r
-            if not os.path.isabs(PrebuildList[0]):\r
-                PrebuildList[0] = mws.join(self.WorkspaceDir, PrebuildList[0])\r
-            if os.path.isfile(PrebuildList[0]):\r
-                self.PrebuildScript = PrebuildList[0]\r
-                self.Prebuild = ' '.join(PrebuildList)\r
-                self.Prebuild += self.PassCommandOption(self.BuildTargetList, self.ArchList, self.ToolChainList)\r
-                #self.LaunchPrebuild()\r
-            else:\r
-                EdkLogger.error("Prebuild", PREBUILD_ERROR, "the prebuild script %s is not exist.\n If you'd like to disable the Prebuild process, please use the format: -D PREBUILD=\"\" " %(PrebuildList[0]))\r
+            PrebuildList = []\r
+            #\r
+            # Evaluate all arguments and convert arguments that are WORKSPACE\r
+            # relative paths to absolute paths.  Filter arguments that look like\r
+            # flags or do not follow the file/dir naming rules to avoid false\r
+            # positives on this conversion.\r
+            #\r
+            for Arg in self.Prebuild.split():\r
+                #\r
+                # Do not modify Arg if it looks like a flag or an absolute file path\r
+                #\r
+                if Arg.startswith('-')  or os.path.isabs(Arg):\r
+                    PrebuildList.append(Arg)\r
+                    continue\r
+                #\r
+                # Do not modify Arg if it does not look like a Workspace relative\r
+                # path that starts with a valid package directory name\r
+                #\r
+                if not Arg[0].isalpha() or os.path.dirname(Arg) == '':\r
+                    PrebuildList.append(Arg)\r
+                    continue\r
+                #\r
+                # If Arg looks like a WORKSPACE relative path, then convert to an\r
+                # absolute path and check to see if the file exists.\r
+                #\r
+                Temp = mws.join(self.WorkspaceDir, Arg)\r
+                if os.path.isfile(Temp):\r
+                    Arg = Temp\r
+                PrebuildList.append(Arg)\r
+            self.Prebuild       = ' '.join(PrebuildList)\r
+            self.Prebuild += self.PassCommandOption(self.BuildTargetList, self.ArchList, self.ToolChainList, self.PlatformFile, self.Target)\r
 \r
     def InitPostBuild(self):\r
         if 'POSTBUILD' in GlobalData.gCommandLineDefines.keys():\r
@@ -982,23 +1001,46 @@ class Build():
             Platform = self.Db._MapPlatform(str(self.PlatformFile))\r
             self.Postbuild = str(Platform.Postbuild)\r
         if self.Postbuild:\r
-            PostbuildList = self.Postbuild.split()\r
-            if not os.path.isabs(PostbuildList[0]):\r
-                PostbuildList[0] = mws.join(self.WorkspaceDir, PostbuildList[0])\r
-            if os.path.isfile(PostbuildList[0]):\r
-                self.PostbuildScript = PostbuildList[0]\r
-                self.Postbuild = ' '.join(PostbuildList)\r
-                self.Postbuild += self.PassCommandOption(self.BuildTargetList, self.ArchList, self.ToolChainList)\r
-            else:\r
-                EdkLogger.error("Postbuild", POSTBUILD_ERROR, "the postbuild script %s is not exist.\n If you'd like to disable the Postbuild process, please use the format: -D POSTBUILD=\"\" " %(PostbuildList[0]))\r
-\r
-    def PassCommandOption(self, BuildTarget, TargetArch, ToolChain):\r
+            PostbuildList = []\r
+            #\r
+            # Evaluate all arguments and convert arguments that are WORKSPACE\r
+            # relative paths to absolute paths.  Filter arguments that look like\r
+            # flags or do not follow the file/dir naming rules to avoid false\r
+            # positives on this conversion.\r
+            #\r
+            for Arg in self.Postbuild.split():\r
+                #\r
+                # Do not modify Arg if it looks like a flag or an absolute file path\r
+                #\r
+                if Arg.startswith('-')  or os.path.isabs(Arg):\r
+                    PostbuildList.append(Arg)\r
+                    continue\r
+                #\r
+                # Do not modify Arg if it does not look like a Workspace relative\r
+                # path that starts with a valid package directory name\r
+                #\r
+                if not Arg[0].isalpha() or os.path.dirname(Arg) == '':\r
+                    PostbuildList.append(Arg)\r
+                    continue\r
+                #\r
+                # If Arg looks like a WORKSPACE relative path, then convert to an\r
+                # absolute path and check to see if the file exists.\r
+                #\r
+                Temp = mws.join(self.WorkspaceDir, Arg)\r
+                if os.path.isfile(Temp):\r
+                    Arg = Temp\r
+                PostbuildList.append(Arg)\r
+            self.Postbuild       = ' '.join(PostbuildList)\r
+            self.Postbuild += self.PassCommandOption(self.BuildTargetList, self.ArchList, self.ToolChainList, self.PlatformFile, self.Target)\r
+\r
+    def PassCommandOption(self, BuildTarget, TargetArch, ToolChain, PlatformFile, Target):\r
         BuildStr = ''\r
         if GlobalData.gCommand and isinstance(GlobalData.gCommand, list):\r
             BuildStr += ' ' + ' '.join(GlobalData.gCommand)\r
         TargetFlag = False\r
         ArchFlag = False\r
         ToolChainFlag = False\r
+        PlatformFileFlag = False\r
 \r
         if GlobalData.gOptions and not GlobalData.gOptions.BuildTarget:\r
             TargetFlag = True\r
@@ -1006,6 +1048,8 @@ class Build():
             ArchFlag = True\r
         if GlobalData.gOptions and not GlobalData.gOptions.ToolChain:\r
             ToolChainFlag = True\r
+        if GlobalData.gOptions and not GlobalData.gOptions.PlatformFile:\r
+            PlatformFileFlag = True\r
 \r
         if TargetFlag and BuildTarget:\r
             if isinstance(BuildTarget, list) or isinstance(BuildTarget, tuple):\r
@@ -1022,6 +1066,14 @@ class Build():
                 BuildStr += ' -t ' + ' -t '.join(ToolChain)\r
             elif isinstance(ToolChain, str):\r
                 BuildStr += ' -t ' + ToolChain\r
+        if PlatformFileFlag and PlatformFile:\r
+            if isinstance(PlatformFile, list) or isinstance(PlatformFile, tuple):\r
+                BuildStr += ' -p ' + ' -p '.join(PlatformFile)\r
+            elif isinstance(PlatformFile, str):\r
+                BuildStr += ' -p' + PlatformFile\r
+        BuildStr += ' --conf=' + GlobalData.gConfDirectory\r
+        if Target:\r
+            BuildStr += ' ' + Target\r
 \r
         return BuildStr\r
 \r