]> git.proxmox.com Git - mirror_edk2.git/blobdiff - BaseTools/Source/Python/AutoGen/AutoGen.py
BaseTools: Update Build tool to support multiple workspaces
[mirror_edk2.git] / BaseTools / Source / Python / AutoGen / AutoGen.py
index a1e1818e3b5f5878f89a075630b55c22b20157cc..fe565743576bd6bd7688e4e454a60dde1583a3d1 100644 (file)
@@ -17,6 +17,7 @@ import Common.LongFilePathOs as os
 import re\r
 import os.path as path\r
 import copy\r
+import uuid\r
 \r
 import GenC\r
 import GenMake\r
@@ -39,7 +40,7 @@ from GenPatchPcdTable.GenPatchPcdTable import parsePcdInfoFromMapFile
 import Common.VpdInfoFile as VpdInfoFile\r
 from GenPcdDb import CreatePcdDatabaseCode\r
 from Workspace.MetaFileCommentParser import UsageList\r
-\r
+from Common.MultipleWorkspace import MultipleWorkspace as mws\r
 import InfSectionParser\r
 \r
 ## Regular expression for splitting Dependency Expression string into tokens\r
@@ -650,7 +651,7 @@ class WorkspaceAutoGen(AutoGen):
         for Pa in self.AutoGenObjectList:\r
             for Package in Pa.PackageList:\r
                 PcdList = Package.Pcds.values()\r
-                PcdList.sort(lambda x, y: cmp(x.TokenValue, y.TokenValue)) \r
+                PcdList.sort(lambda x, y: cmp(int(x.TokenValue, 0), int(y.TokenValue, 0))) \r
                 Count = 0\r
                 while (Count < len(PcdList) - 1) :\r
                     Item = PcdList[Count]\r
@@ -658,13 +659,13 @@ class WorkspaceAutoGen(AutoGen):
                     #\r
                     # Make sure in the same token space the TokenValue should be unique\r
                     #\r
-                    if (Item.TokenValue == ItemNext.TokenValue):\r
+                    if (int(Item.TokenValue, 0) == int(ItemNext.TokenValue, 0)):\r
                         SameTokenValuePcdList = []\r
                         SameTokenValuePcdList.append(Item)\r
                         SameTokenValuePcdList.append(ItemNext)\r
                         RemainPcdListLength = len(PcdList) - Count - 2\r
                         for ValueSameCount in range(RemainPcdListLength):\r
-                            if PcdList[len(PcdList) - RemainPcdListLength + ValueSameCount].TokenValue == Item.TokenValue:\r
+                            if int(PcdList[len(PcdList) - RemainPcdListLength + ValueSameCount].TokenValue, 0) == int(Item.TokenValue, 0):\r
                                 SameTokenValuePcdList.append(PcdList[len(PcdList) - RemainPcdListLength + ValueSameCount])\r
                             else:\r
                                 break;\r
@@ -698,7 +699,7 @@ class WorkspaceAutoGen(AutoGen):
                     #\r
                     # Check PCDs with same TokenSpaceGuidCName.TokenCName have same token value as well.\r
                     #\r
-                    if (Item.TokenSpaceGuidCName == ItemNext.TokenSpaceGuidCName) and (Item.TokenCName == ItemNext.TokenCName) and (Item.TokenValue != ItemNext.TokenValue):\r
+                    if (Item.TokenSpaceGuidCName == ItemNext.TokenSpaceGuidCName) and (Item.TokenCName == ItemNext.TokenCName) and (int(Item.TokenValue, 0) != int(ItemNext.TokenValue, 0)):\r
                         EdkLogger.error(\r
                                     'build',\r
                                     FORMAT_INVALID,\r
@@ -952,7 +953,7 @@ class PlatformAutoGen(AutoGen):
         self._GuidValue = {}\r
         FdfModuleList = []\r
         for InfName in self._AsBuildInfList:\r
-            InfName = os.path.join(self.WorkspaceDir, InfName)\r
+            InfName = mws.join(self.WorkspaceDir, InfName)\r
             FdfModuleList.append(os.path.normpath(InfName))\r
         for F in self.Platform.Modules.keys():\r
             M = ModuleAutoGen(self.Workspace, F, self.BuildTarget, self.ToolChain, self.Arch, self.MetaFile)\r
@@ -1287,7 +1288,7 @@ class PlatformAutoGen(AutoGen):
     def _GetFdfFile(self):\r
         if self._FdfFile == None:\r
             if self.Workspace.FdfFile != "":\r
-                self._FdfFile= path.join(self.WorkspaceDir, self.Workspace.FdfFile)\r
+                self._FdfFile= mws.join(self.WorkspaceDir, self.Workspace.FdfFile)\r
             else:\r
                 self._FdfFile = ''\r
         return self._FdfFile\r
@@ -1962,7 +1963,8 @@ class PlatformAutoGen(AutoGen):
             # Key[0] -- tool family\r
             # Key[1] -- TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE\r
             #\r
-            if Key[0] == self.BuildRuleFamily :\r
+            if (Key[0] == self.BuildRuleFamily and\r
+                (ModuleStyle == None or len(Key) < 3 or (len(Key) > 2 and Key[2] == ModuleStyle))):\r
                 Target, ToolChain, Arch, CommandType, Attr = Key[1].split('_')\r
                 if Target == self.BuildTarget or Target == "*":\r
                     if ToolChain == self.ToolChain or ToolChain == "*":\r
@@ -1998,7 +2000,6 @@ class PlatformAutoGen(AutoGen):
                                             if Options.get((self.BuildRuleFamily, NowKey)) != None: \r
                                                 Options.pop((self.BuildRuleFamily, NowKey))\r
                                                            \r
-        \r
         for Key in Options:\r
             if ModuleStyle != None and len (Key) > 2:\r
                 # Check Module style is EDK or EDKII.\r
@@ -2024,7 +2025,7 @@ class PlatformAutoGen(AutoGen):
                     if Arch == "*" or Arch == self.Arch:\r
                         if Tool not in BuildOptions:\r
                             BuildOptions[Tool] = {}\r
-                        if Attr != "FLAGS" or Attr not in BuildOptions[Tool]:\r
+                        if Attr != "FLAGS" or Attr not in BuildOptions[Tool] or Options[Key].startswith('='):\r
                             BuildOptions[Tool][Attr] = Options[Key]\r
                         else:\r
                             # append options for the same tool\r
@@ -2032,7 +2033,7 @@ class PlatformAutoGen(AutoGen):
         # Build Option Family has been checked, which need't to be checked again for family.\r
         if FamilyMatch or FamilyIsNull:\r
             return BuildOptions\r
-        \r
+\r
         for Key in Options:\r
             if ModuleStyle != None and len (Key) > 2:\r
                 # Check Module style is EDK or EDKII.\r
@@ -2056,7 +2057,7 @@ class PlatformAutoGen(AutoGen):
                     if Arch == "*" or Arch == self.Arch:\r
                         if Tool not in BuildOptions:\r
                             BuildOptions[Tool] = {}\r
-                        if Attr != "FLAGS" or Attr not in BuildOptions[Tool]:\r
+                        if Attr != "FLAGS" or Attr not in BuildOptions[Tool] or Options[Key].startswith('='):\r
                             BuildOptions[Tool][Attr] = Options[Key]\r
                         else:\r
                             # append options for the same tool\r
@@ -2073,8 +2074,11 @@ class PlatformAutoGen(AutoGen):
         # Get the different options for the different style module\r
         if Module.AutoGenVersion < 0x00010005:\r
             PlatformOptions = self.EdkBuildOption\r
+            ModuleTypeOptions = self.Platform.GetBuildOptionsByModuleType(EDK_NAME, Module.ModuleType)\r
         else:\r
             PlatformOptions = self.EdkIIBuildOption\r
+            ModuleTypeOptions = self.Platform.GetBuildOptionsByModuleType(EDKII_NAME, Module.ModuleType)\r
+        ModuleTypeOptions = self._ExpandBuildOption(ModuleTypeOptions)\r
         ModuleOptions = self._ExpandBuildOption(Module.BuildOptions)\r
         if Module in self.Platform.Modules:\r
             PlatformModule = self.Platform.Modules[str(Module)]\r
@@ -2082,23 +2086,40 @@ class PlatformAutoGen(AutoGen):
         else:\r
             PlatformModuleOptions = {}\r
 \r
-        AllTools = set(ModuleOptions.keys() + PlatformOptions.keys() + PlatformModuleOptions.keys() + self.ToolDefinition.keys())\r
+        BuildRuleOrder = None\r
+        for Options in [self.ToolDefinition, ModuleOptions, PlatformOptions, ModuleTypeOptions, PlatformModuleOptions]:\r
+            for Tool in Options:\r
+                for Attr in Options[Tool]:\r
+                    if Attr == TAB_TOD_DEFINES_BUILDRULEORDER:\r
+                        BuildRuleOrder = Options[Tool][Attr]\r
+\r
+        AllTools = set(ModuleOptions.keys() + PlatformOptions.keys() +\r
+                       PlatformModuleOptions.keys() + ModuleTypeOptions.keys() +\r
+                       self.ToolDefinition.keys())\r
         BuildOptions = {}\r
         for Tool in AllTools:\r
             if Tool not in BuildOptions:\r
                 BuildOptions[Tool] = {}\r
 \r
-            for Options in [self.ToolDefinition, ModuleOptions, PlatformOptions, PlatformModuleOptions]:\r
+            for Options in [self.ToolDefinition, ModuleOptions, PlatformOptions, ModuleTypeOptions, PlatformModuleOptions]:\r
                 if Tool not in Options:\r
                     continue\r
                 for Attr in Options[Tool]:\r
                     Value = Options[Tool][Attr]\r
+                    #\r
+                    # Do not generate it in Makefile\r
+                    #\r
+                    if Attr == TAB_TOD_DEFINES_BUILDRULEORDER:\r
+                        continue\r
                     if Attr not in BuildOptions[Tool]:\r
                         BuildOptions[Tool][Attr] = ""\r
                     # check if override is indicated\r
                     if Value.startswith('='):\r
-                        BuildOptions[Tool][Attr] = Value[1:]\r
+                        ToolPath = Value[1:]\r
+                        ToolPath = mws.handleWsMacro(ToolPath)\r
+                        BuildOptions[Tool][Attr] = ToolPath\r
                     else:\r
+                        Value = mws.handleWsMacro(Value)\r
                         BuildOptions[Tool][Attr] += " " + Value\r
         if Module.AutoGenVersion < 0x00010005 and self.Workspace.UniFlag != None:\r
             #\r
@@ -2107,7 +2128,7 @@ class PlatformAutoGen(AutoGen):
             if 'BUILD' not in BuildOptions:\r
                 BuildOptions['BUILD'] = {}\r
             BuildOptions['BUILD']['FLAGS'] = self.Workspace.UniFlag\r
-        return BuildOptions\r
+        return BuildOptions, BuildRuleOrder\r
 \r
     Platform            = property(_GetPlatform)\r
     Name                = property(_GetName)\r
@@ -2175,8 +2196,7 @@ class ModuleAutoGen(AutoGen):
             return False\r
 \r
         self.SourceDir = self.MetaFile.SubDir\r
-        if self.SourceDir.upper().find(self.WorkspaceDir.upper()) == 0:\r
-            self.SourceDir = self.SourceDir[len(self.WorkspaceDir) + 1:]\r
+        self.SourceDir = mws.relpath(self.SourceDir, self.WorkspaceDir)\r
 \r
         self.SourceOverrideDir = None\r
         # use overrided path defined in DSC file\r
@@ -2195,6 +2215,7 @@ class ModuleAutoGen(AutoGen):
         self.DepexGenerated = False\r
 \r
         self.BuildDatabase = self.Workspace.BuildDatabase\r
+        self.BuildRuleOrder = None\r
 \r
         self._Module          = None\r
         self._Name            = None\r
@@ -2272,12 +2293,25 @@ class ModuleAutoGen(AutoGen):
                 \r
         return self._FixedAtBuildPcds        \r
 \r
+    def _GetUniqueBaseName(self):\r
+        BaseName = self.Name\r
+        for Module in self.PlatformInfo.ModuleAutoGenList:\r
+            if Module.MetaFile == self.MetaFile:\r
+                continue\r
+            if Module.Name == self.Name:\r
+                if uuid.UUID(Module.Guid) == uuid.UUID(self.Guid):\r
+                    EdkLogger.error("build", FILE_DUPLICATED, 'Modules have same BaseName and FILE_GUID:\n'\r
+                                    '  %s\n  %s' % (Module.MetaFile, self.MetaFile))\r
+                BaseName = '%s_%s' % (self.Name, self.Guid)\r
+        return BaseName\r
+\r
     # Macros could be used in build_rule.txt (also Makefile)\r
     def _GetMacros(self):\r
         if self._Macro == None:\r
             self._Macro = sdict()\r
             self._Macro["WORKSPACE"             ] = self.WorkspaceDir\r
             self._Macro["MODULE_NAME"           ] = self.Name\r
+            self._Macro["MODULE_NAME_GUID"      ] = self._GetUniqueBaseName()\r
             self._Macro["MODULE_GUID"           ] = self.Guid\r
             self._Macro["MODULE_VERSION"        ] = self.Version\r
             self._Macro["MODULE_TYPE"           ] = self.ModuleType\r
@@ -2587,7 +2621,9 @@ class ModuleAutoGen(AutoGen):
     #\r
     def _GetModuleBuildOption(self):\r
         if self._BuildOption == None:\r
-            self._BuildOption = self.PlatformInfo.ApplyBuildOption(self.Module)\r
+            self._BuildOption, self.BuildRuleOrder = self.PlatformInfo.ApplyBuildOption(self.Module)\r
+            if self.BuildRuleOrder:\r
+                self.BuildRuleOrder = ['.%s' % Ext for Ext in self.BuildRuleOrder.split()]\r
         return self._BuildOption\r
 \r
     ## Get include path list from tool option for the module build\r
@@ -2746,6 +2782,11 @@ class ModuleAutoGen(AutoGen):
         RuleChain = []\r
         SourceList = [File]\r
         Index = 0\r
+        #\r
+        # Make sure to get build rule order value\r
+        #\r
+        self._GetModuleBuildOption()\r
+\r
         while Index < len(SourceList):\r
             Source = SourceList[Index]\r
             Index = Index + 1\r
@@ -2779,7 +2820,7 @@ class ModuleAutoGen(AutoGen):
                     self._FinalBuildTargetList.add(LastTarget)\r
                 break\r
 \r
-            Target = RuleObject.Apply(Source)\r
+            Target = RuleObject.Apply(Source, self.BuildRuleOrder)\r
             if not Target:\r
                 if LastTarget:\r
                     self._FinalBuildTargetList.add(LastTarget)\r
@@ -3003,7 +3044,7 @@ class ModuleAutoGen(AutoGen):
                 self._IncludePathList.append(self.DebugDir)\r
 \r
             for Package in self.Module.Packages:\r
-                PackageDir = path.join(self.WorkspaceDir, Package.MetaFile.Dir)\r
+                PackageDir = mws.join(self.WorkspaceDir, Package.MetaFile.Dir)\r
                 if PackageDir not in self._IncludePathList:\r
                     self._IncludePathList.append(PackageDir)\r
                 for Inc in Package.Includes:\r
@@ -3076,6 +3117,76 @@ class ModuleAutoGen(AutoGen):
 \r
         return HiiExPcds\r
 \r
+    def _GenOffsetBin(self):\r
+        VfrUniBaseName = {}\r
+        for SourceFile in self.Module.Sources:\r
+            if SourceFile.Type.upper() == ".VFR" :\r
+                #\r
+                # search the .map file to find the offset of vfr binary in the PE32+/TE file. \r
+                #\r
+                VfrUniBaseName[SourceFile.BaseName] = (SourceFile.BaseName + "Bin")\r
+            if SourceFile.Type.upper() == ".UNI" :\r
+                #\r
+                # search the .map file to find the offset of Uni strings binary in the PE32+/TE file. \r
+                #\r
+                VfrUniBaseName["UniOffsetName"] = (self.Name + "Strings")\r
+\r
+        if len(VfrUniBaseName) == 0:\r
+            return None\r
+        MapFileName = os.path.join(self.OutputDir, self.Name + ".map")\r
+        EfiFileName = os.path.join(self.OutputDir, self.Name + ".efi")\r
+        VfrUniOffsetList = GetVariableOffset(MapFileName, EfiFileName, VfrUniBaseName.values())\r
+        if not VfrUniOffsetList:\r
+            return None\r
+\r
+        OutputName = '%sOffset.bin' % self.Name\r
+        UniVfrOffsetFileName    =  os.path.join( self.OutputDir, OutputName)\r
+\r
+        try:\r
+            fInputfile = open(UniVfrOffsetFileName, "wb+", 0)\r
+        except:\r
+            EdkLogger.error("build", FILE_OPEN_FAILURE, "File open failed for %s" % UniVfrOffsetFileName,None)\r
+\r
+        # Use a instance of StringIO to cache data\r
+        fStringIO = StringIO('')  \r
+\r
+        for Item in VfrUniOffsetList:\r
+            if (Item[0].find("Strings") != -1):\r
+                #\r
+                # UNI offset in image.\r
+                # GUID + Offset\r
+                # { 0x8913c5e0, 0x33f6, 0x4d86, { 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66 } }\r
+                #\r
+                UniGuid = [0xe0, 0xc5, 0x13, 0x89, 0xf6, 0x33, 0x86, 0x4d, 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66]\r
+                UniGuid = [chr(ItemGuid) for ItemGuid in UniGuid]\r
+                fStringIO.write(''.join(UniGuid))            \r
+                UniValue = pack ('Q', int (Item[1], 16))\r
+                fStringIO.write (UniValue)\r
+            else:\r
+                #\r
+                # VFR binary offset in image.\r
+                # GUID + Offset\r
+                # { 0xd0bc7cb4, 0x6a47, 0x495f, { 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2 } };\r
+                #\r
+                VfrGuid = [0xb4, 0x7c, 0xbc, 0xd0, 0x47, 0x6a, 0x5f, 0x49, 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2]\r
+                VfrGuid = [chr(ItemGuid) for ItemGuid in VfrGuid]\r
+                fStringIO.write(''.join(VfrGuid))                   \r
+                type (Item[1]) \r
+                VfrValue = pack ('Q', int (Item[1], 16))\r
+                fStringIO.write (VfrValue)\r
+        #\r
+        # write data into file.\r
+        #\r
+        try :  \r
+            fInputfile.write (fStringIO.getvalue())\r
+        except:\r
+            EdkLogger.error("build", FILE_WRITE_FAILURE, "Write data to file %s failed, please check whether the "\r
+                            "file been locked or using by other applications." %UniVfrOffsetFileName,None)\r
+\r
+        fStringIO.close ()\r
+        fInputfile.close ()\r
+        return OutputName\r
+\r
     ## Create AsBuilt INF file the module\r
     #\r
     def CreateAsBuiltInf(self):\r
@@ -3230,6 +3341,10 @@ class ModuleAutoGen(AutoGen):
             if self.ModuleType in ['DXE_SMM_DRIVER']:\r
               AsBuiltInfDict['binary_item'] += ['SMM_DEPEX|' + self.Name + '.depex']\r
 \r
+        Bin = self._GenOffsetBin()\r
+        if Bin:\r
+            AsBuiltInfDict['binary_item'] += ['BIN|%s' % Bin]\r
+\r
         for Root, Dirs, Files in os.walk(OutputDir):\r
             for File in Files:\r
                 if File.lower().endswith('.pdb'):\r