Revision: 18579
          http://sourceforge.net/p/edk2/code/18579
Author:   lgao4
Date:     2015-10-08 09:27:14 +0000 (Thu, 08 Oct 2015)
Log Message:
-----------
BaseTools: Update Build tool to support multiple workspaces

WORKSPACE is still kept.
New PACKAGES_PATH is introduced to specify the additional WORKSPACEs.
In PACKAGES_PATH, ';' is separator in Windows, ':' is separator in Linux.

Build directory is in WORKSPACE. Package, BaseTools and Conf directory
will be found from WORKSPACE and PACKAGES_PATH.

In implementation, BaseTools adds MultipleWorkspace class for
the file path conversion from WORKSPACE and PACKAGES_PATH.

Verify two tree layouts.
Root\edk2\MdePkg
Root\edk2\MdeMdeModulePkg
Root\edk2\...
1. set WORKSPACE=Root\edk2
2. set WORKSPACE=Root, and set PACKAGES_PATH=Root\edk2

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Li YangX <[email protected]>
Reviewed-by: Liming Gao <[email protected]>

Modified Paths:
--------------
    trunk/edk2/BaseTools/Source/Python/AutoGen/AutoGen.py
    trunk/edk2/BaseTools/Source/Python/AutoGen/GenMake.py
    trunk/edk2/BaseTools/Source/Python/Common/EdkIIWorkspace.py
    trunk/edk2/BaseTools/Source/Python/Common/FdfParserLite.py
    trunk/edk2/BaseTools/Source/Python/Common/LongFilePathOsPath.py
    trunk/edk2/BaseTools/Source/Python/Common/Misc.py
    trunk/edk2/BaseTools/Source/Python/Common/String.py
    trunk/edk2/BaseTools/Source/Python/GenFds/FfsInfStatement.py
    trunk/edk2/BaseTools/Source/Python/GenFds/GenFds.py
    trunk/edk2/BaseTools/Source/Python/GenFds/GenFdsGlobalVariable.py
    trunk/edk2/BaseTools/Source/Python/GenFds/Region.py
    trunk/edk2/BaseTools/Source/Python/Workspace/WorkspaceDatabase.py
    trunk/edk2/BaseTools/Source/Python/build/BuildReport.py
    trunk/edk2/BaseTools/Source/Python/build/build.py

Added Paths:
-----------
    trunk/edk2/BaseTools/Source/Python/Common/MultipleWorkspace.py

Modified: trunk/edk2/BaseTools/Source/Python/AutoGen/AutoGen.py
===================================================================
--- trunk/edk2/BaseTools/Source/Python/AutoGen/AutoGen.py       2015-10-08 
05:51:57 UTC (rev 18578)
+++ trunk/edk2/BaseTools/Source/Python/AutoGen/AutoGen.py       2015-10-08 
09:27:14 UTC (rev 18579)
@@ -40,7 +40,7 @@
 import Common.VpdInfoFile as VpdInfoFile
 from GenPcdDb import CreatePcdDatabaseCode
 from Workspace.MetaFileCommentParser import UsageList
-
+from Common.MultipleWorkspace import MultipleWorkspace as mws
 import InfSectionParser
 
 ## Regular expression for splitting Dependency Expression string into tokens
@@ -953,7 +953,7 @@
         self._GuidValue = {}
         FdfModuleList = []
         for InfName in self._AsBuildInfList:
-            InfName = os.path.join(self.WorkspaceDir, InfName)
+            InfName = mws.join(self.WorkspaceDir, InfName)
             FdfModuleList.append(os.path.normpath(InfName))
         for F in self.Platform.Modules.keys():
             M = ModuleAutoGen(self.Workspace, F, self.BuildTarget, 
self.ToolChain, self.Arch, self.MetaFile)
@@ -1288,7 +1288,7 @@
     def _GetFdfFile(self):
         if self._FdfFile == None:
             if self.Workspace.FdfFile != "":
-                self._FdfFile= path.join(self.WorkspaceDir, 
self.Workspace.FdfFile)
+                self._FdfFile= mws.join(self.WorkspaceDir, 
self.Workspace.FdfFile)
             else:
                 self._FdfFile = ''
         return self._FdfFile
@@ -2115,8 +2115,11 @@
                         BuildOptions[Tool][Attr] = ""
                     # check if override is indicated
                     if Value.startswith('='):
-                        BuildOptions[Tool][Attr] = Value[1:]
+                        ToolPath = Value[1:]
+                        ToolPath = mws.handleWsMacro(ToolPath)
+                        BuildOptions[Tool][Attr] = ToolPath
                     else:
+                        Value = mws.handleWsMacro(Value)
                         BuildOptions[Tool][Attr] += " " + Value
         if Module.AutoGenVersion < 0x00010005 and self.Workspace.UniFlag != 
None:
             #
@@ -2193,8 +2196,7 @@
             return False
 
         self.SourceDir = self.MetaFile.SubDir
-        if self.SourceDir.upper().find(self.WorkspaceDir.upper()) == 0:
-            self.SourceDir = self.SourceDir[len(self.WorkspaceDir) + 1:]
+        self.SourceDir = mws.relpath(self.SourceDir, self.WorkspaceDir)
 
         self.SourceOverrideDir = None
         # use overrided path defined in DSC file
@@ -3042,7 +3044,7 @@
                 self._IncludePathList.append(self.DebugDir)
 
             for Package in self.Module.Packages:
-                PackageDir = path.join(self.WorkspaceDir, Package.MetaFile.Dir)
+                PackageDir = mws.join(self.WorkspaceDir, Package.MetaFile.Dir)
                 if PackageDir not in self._IncludePathList:
                     self._IncludePathList.append(PackageDir)
                 for Inc in Package.Includes:

Modified: trunk/edk2/BaseTools/Source/Python/AutoGen/GenMake.py
===================================================================
--- trunk/edk2/BaseTools/Source/Python/AutoGen/GenMake.py       2015-10-08 
05:51:57 UTC (rev 18578)
+++ trunk/edk2/BaseTools/Source/Python/AutoGen/GenMake.py       2015-10-08 
09:27:14 UTC (rev 18579)
@@ -19,7 +19,7 @@
 import re
 import os.path as path
 from Common.LongFilePathSupport import OpenLongFilePath as open
-
+from Common.MultipleWorkspace import MultipleWorkspace as mws
 from Common.BuildToolError import *
 from Common.Misc import *
 from Common.String import *
@@ -559,7 +559,7 @@
         found = False
         while not found and os.sep in package_rel_dir:
             index = package_rel_dir.index(os.sep)
-            current_dir = os.path.join(current_dir, package_rel_dir[:index])
+            current_dir = mws.join(current_dir, package_rel_dir[:index])
             for fl in os.listdir(current_dir):
                 if fl.endswith('.dec'):
                     found = True

Modified: trunk/edk2/BaseTools/Source/Python/Common/EdkIIWorkspace.py
===================================================================
--- trunk/edk2/BaseTools/Source/Python/Common/EdkIIWorkspace.py 2015-10-08 
05:51:57 UTC (rev 18578)
+++ trunk/edk2/BaseTools/Source/Python/Common/EdkIIWorkspace.py 2015-10-08 
09:27:14 UTC (rev 18579)
@@ -17,6 +17,7 @@
 import Common.LongFilePathOs as os, sys, time
 from DataType import *
 from Common.LongFilePathSupport import OpenLongFilePath as open
+from Common.MultipleWorkspace import MultipleWorkspace as mws
 
 ## EdkIIWorkspace
 #
@@ -112,7 +113,7 @@
     # @retval string  The full path filename
     #
     def WorkspaceFile(self, FileName):
-        return os.path.realpath(os.path.join(self.WorkspaceDir,FileName))
+        return os.path.realpath(mws.join(self.WorkspaceDir,FileName))
 
     ## Convert to a real path filename
     #

Modified: trunk/edk2/BaseTools/Source/Python/Common/FdfParserLite.py
===================================================================
--- trunk/edk2/BaseTools/Source/Python/Common/FdfParserLite.py  2015-10-08 
05:51:57 UTC (rev 18578)
+++ trunk/edk2/BaseTools/Source/Python/Common/FdfParserLite.py  2015-10-08 
09:27:14 UTC (rev 18579)
@@ -20,6 +20,7 @@
 
 import CommonDataClass.FdfClass
 from Common.LongFilePathSupport import OpenLongFilePath as open
+from Common.MultipleWorkspace import MultipleWorkspace as mws
 
 ##define T_CHAR_SPACE                ' '
 ##define T_CHAR_NULL                 '\0'
@@ -485,7 +486,8 @@
                 IncFileName = self.__Token
                 if not os.path.isabs(IncFileName):
                     if IncFileName.startswith('$(WORKSPACE)'):
-                        Str = IncFileName.replace('$(WORKSPACE)', 
os.environ.get('WORKSPACE'))
+                        Str = mws.handleWsMacro(IncFileName)
+                        Str = Str.replace('$(WORKSPACE)', 
os.environ.get('WORKSPACE'))
                         if os.path.exists(Str):
                             if not os.path.isabs(Str):
                                 Str = os.path.abspath(Str)
@@ -494,7 +496,7 @@
                         # file is in the same dir with FDF file
                         FullFdf = self.FileName
                         if not os.path.isabs(self.FileName):
-                            FullFdf = 
os.path.join(os.environ.get('WORKSPACE'), self.FileName)
+                            FullFdf = mws.join(os.environ.get('WORKSPACE'), 
self.FileName)
                 
                         IncFileName = os.path.join(os.path.dirname(FullFdf), 
IncFileName)
                     

Modified: trunk/edk2/BaseTools/Source/Python/Common/LongFilePathOsPath.py
===================================================================
--- trunk/edk2/BaseTools/Source/Python/Common/LongFilePathOsPath.py     
2015-10-08 05:51:57 UTC (rev 18578)
+++ trunk/edk2/BaseTools/Source/Python/Common/LongFilePathOsPath.py     
2015-10-08 09:27:14 UTC (rev 18579)
@@ -49,3 +49,5 @@
 islink = os.path.islink
 isabs = os.path.isabs
 realpath = os.path.realpath
+relpath = os.path.relpath
+pardir = os.path.pardir

Modified: trunk/edk2/BaseTools/Source/Python/Common/Misc.py
===================================================================
--- trunk/edk2/BaseTools/Source/Python/Common/Misc.py   2015-10-08 05:51:57 UTC 
(rev 18578)
+++ trunk/edk2/BaseTools/Source/Python/Common/Misc.py   2015-10-08 09:27:14 UTC 
(rev 18579)
@@ -35,6 +35,7 @@
 from CommonDataClass.DataClass import *
 from Parsing import GetSplitValueList
 from Common.LongFilePathSupport import OpenLongFilePath as open
+from Common.MultipleWorkspace import MultipleWorkspace as mws
 
 ## Regular expression used to find out place holders in string template
 gPlaceholderPattern = re.compile("\$\{([^$()\s]+)\}", re.MULTILINE|re.UNICODE)
@@ -1728,6 +1729,7 @@
 
         # Remove any '.' and '..' in path
         if self.Root:
+            self.Root = mws.getWs(self.Root, self.File)
             self.Path = os.path.normpath(os.path.join(self.Root, self.File))
             self.Root = os.path.normpath(CommonPath([self.Root, self.Path]))
             # eliminate the side-effect of 'C:'
@@ -1838,7 +1840,10 @@
                 RealFile = os.path.join(self.AlterRoot, self.File)
             elif self.Root:
                 RealFile = os.path.join(self.Root, self.File)
-            return FILE_NOT_FOUND, os.path.join(self.AlterRoot, RealFile)
+            if len (mws.getPkgPath()) == 0:
+                return FILE_NOT_FOUND, os.path.join(self.AlterRoot, RealFile)
+            else:
+                return FILE_NOT_FOUND, "%s is not found in packages 
path:\n\t%s" % (self.File, '\n\t'.join(mws.getPkgPath()))
 
         ErrorCode = 0
         ErrorInfo = ''

Added: trunk/edk2/BaseTools/Source/Python/Common/MultipleWorkspace.py
===================================================================
--- trunk/edk2/BaseTools/Source/Python/Common/MultipleWorkspace.py              
                (rev 0)
+++ trunk/edk2/BaseTools/Source/Python/Common/MultipleWorkspace.py      
2015-10-08 09:27:14 UTC (rev 18579)
@@ -0,0 +1,148 @@
+## @file
+# manage multiple workspace file.
+#
+# This file is required to make Python interpreter treat the directory
+# as containing package.
+#
+# Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD 
License
+# which accompanies this distribution.  The full text of the license may be 
found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+
+import Common.LongFilePathOs as os
+from Common.DataType import TAB_WORKSPACE
+
+## MultipleWorkspace
+#
+# This class manage multiple workspace behavior
+# 
+# @param class:
+#
+# @var WORKSPACE:      defined the current WORKSPACE
+# @var PACKAGES_PATH:  defined the other WORKSAPCE, if current WORKSPACE is 
invalid, search valid WORKSPACE from PACKAGES_PATH
+# 
+class MultipleWorkspace(object):
+    WORKSPACE = ''
+    PACKAGES_PATH = None
+    
+    ## convertPackagePath()
+    #
+    #   Convert path to match workspace.
+    #
+    #   @param  cls          The class pointer
+    #   @param  Ws           The current WORKSPACE
+    #   @param  Path         Path to be converted to match workspace.
+    #
+    @classmethod
+    def convertPackagePath(cls, Ws, Path):
+        if str(os.path.normcase (Path)).startswith(Ws):
+            return os.path.join(Ws, Path[len(Ws) + 1:])
+        return Path
+
+    ## setWs()
+    #
+    #   set WORKSPACE and PACKAGES_PATH environment
+    #
+    #   @param  cls          The class pointer
+    #   @param  Ws           initialize WORKSPACE variable
+    #   @param  PackagesPath initialize PackagesPath variable
+    #
+    @classmethod
+    def setWs(cls, Ws, PackagesPath=None):
+        cls.WORKSPACE = Ws
+        if PackagesPath:
+            cls.PACKAGES_PATH = [cls.convertPackagePath (Ws, 
os.path.normpath(Path.strip())) for Path in PackagesPath.split(os.pathsep)]
+        else:
+            cls.PACKAGES_PATH = []
+    
+    ## join()
+    #
+    #   rewrite os.path.join function
+    #
+    #   @param  cls       The class pointer
+    #   @param  Ws        the current WORKSPACE
+    #   @param  *p        path of the inf/dec/dsc/fdf/conf file
+    #   @retval Path      the absolute path of specified file
+    #
+    @classmethod
+    def join(cls, Ws, *p):
+        Path = os.path.join(Ws, *p)
+        if not os.path.exists(Path):
+            for Pkg in cls.PACKAGES_PATH:
+                Path = os.path.join(Pkg, *p)
+                if os.path.exists(Path):
+                    return Path
+            Path = os.path.join(Ws, *p)
+        return Path
+    
+    ## relpath()
+    #
+    #   rewrite os.path.relpath function
+    #
+    #   @param  cls       The class pointer
+    #   @param  Path      path of the inf/dec/dsc/fdf/conf file
+    #   @param  Ws        the current WORKSPACE
+    #   @retval Path      the relative path of specified file
+    #
+    @classmethod
+    def relpath(cls, Path, Ws):
+        for Pkg in cls.PACKAGES_PATH:
+            if Path.lower().startswith(Pkg.lower()):
+                Path = os.path.relpath(Path, Pkg)
+                return Path
+        if Path.lower().startswith(Ws.lower()):
+            Path = os.path.relpath(Path, Ws)
+        return Path
+    
+    ## getWs()
+    #
+    #   get valid workspace for the path
+    #
+    #   @param  cls       The class pointer
+    #   @param  Ws        the current WORKSPACE
+    #   @param  Path      path of the inf/dec/dsc/fdf/conf file
+    #   @retval Ws        the valid workspace relative to the specified file 
path
+    #
+    @classmethod
+    def getWs(cls, Ws, Path):
+        absPath = os.path.join(Ws, Path)
+        if not os.path.exists(absPath):
+            for Pkg in cls.PACKAGES_PATH:
+                absPath = os.path.join(Pkg, Path)
+                if os.path.exists(absPath):
+                    return Pkg
+        return Ws
+    
+    ## handleWsMacro()
+    #
+    #   handle the $(WORKSPACE) tag, if current workspace is invalid path 
relative the tool, replace it.
+    #
+    #   @param  cls       The class pointer
+    #   @retval PathStr   Path string include the $(WORKSPACE)
+    #
+    @classmethod
+    def handleWsMacro(cls, PathStr):
+        if TAB_WORKSPACE in PathStr:
+            Path = PathStr.replace(TAB_WORKSPACE, cls.WORKSPACE).strip()
+            if not os.path.exists(Path):
+                for Pkg in cls.PACKAGES_PATH:
+                    Path = PathStr.replace(TAB_WORKSPACE, Pkg).strip()
+                    if os.path.exists(Path):
+                        return Path
+        return PathStr
+    
+    ## getPkgPath()
+    #
+    #   get all package pathes.
+    #
+    #   @param  cls       The class pointer
+    #
+    @classmethod
+    def getPkgPath(cls):
+        return cls.PACKAGES_PATH
+            
\ No newline at end of file

Modified: trunk/edk2/BaseTools/Source/Python/Common/String.py
===================================================================
--- trunk/edk2/BaseTools/Source/Python/Common/String.py 2015-10-08 05:51:57 UTC 
(rev 18578)
+++ trunk/edk2/BaseTools/Source/Python/Common/String.py 2015-10-08 09:27:14 UTC 
(rev 18579)
@@ -24,6 +24,7 @@
 from BuildToolError import *
 from CommonDataClass.Exceptions import *
 from Common.LongFilePathSupport import OpenLongFilePath as open
+from Common.MultipleWorkspace import MultipleWorkspace as mws
 
 gHexVerPatt = re.compile('0x[a-f0-9]{4}[a-f0-9]{4}$', re.IGNORECASE)
 gHumanReadableVerPatt = re.compile(r'([1-9][0-9]*|0)\.[0-9]{1,2}$')
@@ -305,6 +306,11 @@
         # To local path format
         #
         Path = os.path.normpath(Path)
+        if Path.startswith(GlobalData.gWorkspace) and not os.path.exists(Path):
+            Path = Path[len (GlobalData.gWorkspace):]
+            if Path[0] == os.path.sep:
+                Path = Path[1:]
+            Path = mws.join(GlobalData.gWorkspace, Path)
 
     if IsRelativePath and Path[0] != '.':
         Path = os.path.join('.', Path)
@@ -702,7 +708,7 @@
 # @retval string A full path
 #
 def WorkspaceFile(WorkspaceDir, Filename):
-    return os.path.join(NormPath(WorkspaceDir), NormPath(Filename))
+    return mws.join(NormPath(WorkspaceDir), NormPath(Filename))
 
 ## Split string
 #

Modified: trunk/edk2/BaseTools/Source/Python/GenFds/FfsInfStatement.py
===================================================================
--- trunk/edk2/BaseTools/Source/Python/GenFds/FfsInfStatement.py        
2015-10-08 05:51:57 UTC (rev 18578)
+++ trunk/edk2/BaseTools/Source/Python/GenFds/FfsInfStatement.py        
2015-10-08 09:27:14 UTC (rev 18579)
@@ -28,6 +28,7 @@
 import RuleSimpleFile
 import RuleComplexFile
 from CommonDataClass.FdfClass import FfsInfStatementClassObject
+from Common.MultipleWorkspace import MultipleWorkspace as mws
 from Common.String import *
 from Common.Misc import PathClass
 from Common.Misc import GuidStructureByteArrayToGuidString
@@ -365,7 +366,7 @@
         #
 
         self.__InfParse__(Dict)
-        SrcFile = os.path.join( GenFdsGlobalVariable.WorkSpaceDir , 
self.InfFileName);
+        SrcFile = mws.join( GenFdsGlobalVariable.WorkSpaceDir , 
self.InfFileName);
         DestFile = os.path.join( self.OutputPath, self.ModuleGuid + '.ffs')
         
         SrcFileDir = "."
@@ -511,7 +512,7 @@
     #
     def __GetPlatformArchList__(self):
 
-        InfFileKey = 
os.path.normpath(os.path.join(GenFdsGlobalVariable.WorkSpaceDir, 
self.InfFileName))
+        InfFileKey = 
os.path.normpath(mws.join(GenFdsGlobalVariable.WorkSpaceDir, self.InfFileName))
         DscArchList = []
         PlatformDataBase = 
GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, 
'IA32', GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]
         if  PlatformDataBase != None:
@@ -878,7 +879,7 @@
             
             if not HasGneratedFlag:
                 UniVfrOffsetFileSection = ""    
-                ModuleFileName = 
os.path.join(GenFdsGlobalVariable.WorkSpaceDir, self.InfFileName)
+                ModuleFileName = mws.join(GenFdsGlobalVariable.WorkSpaceDir, 
self.InfFileName)
                 InfData = 
GenFdsGlobalVariable.WorkSpace.BuildObject[PathClass(ModuleFileName), 
self.CurrentArch]
                 #
                 # Search the source list in InfData to find if there are .vfr 
file exist.

Modified: trunk/edk2/BaseTools/Source/Python/GenFds/GenFds.py
===================================================================
--- trunk/edk2/BaseTools/Source/Python/GenFds/GenFds.py 2015-10-08 05:51:57 UTC 
(rev 18578)
+++ trunk/edk2/BaseTools/Source/Python/GenFds/GenFds.py 2015-10-08 09:27:14 UTC 
(rev 18579)
@@ -39,6 +39,7 @@
 from Common.Misc import ClearDuplicatedInf
 from Common.Misc import GuidStructureStringToGuidString
 from Common.BuildVersion import gBUILD_VERSION
+from Common.MultipleWorkspace import MultipleWorkspace as mws
 
 ## Version and Copyright
 versionNumber = "1.0" + ' ' + gBUILD_VERSION
@@ -94,6 +95,10 @@
             if (Options.debug):
                 GenFdsGlobalVariable.VerboseLogger( "Using Workspace:" + 
Workspace)
         os.chdir(GenFdsGlobalVariable.WorkSpaceDir)
+        
+        # set multiple workspace
+        PackagesPath = os.getenv("PACKAGES_PATH")
+        mws.setWs(GenFdsGlobalVariable.WorkSpaceDir, PackagesPath)
 
         if (Options.filename):
             FdfFilename = Options.filename
@@ -102,7 +107,7 @@
             if FdfFilename[0:2] == '..':
                 FdfFilename = os.path.realpath(FdfFilename)
             if not os.path.isabs (FdfFilename):
-                FdfFilename = os.path.join(GenFdsGlobalVariable.WorkSpaceDir, 
FdfFilename)
+                FdfFilename = mws.join(GenFdsGlobalVariable.WorkSpaceDir, 
FdfFilename)
             if not os.path.exists(FdfFilename):
                 EdkLogger.error("GenFds", FILE_NOT_FOUND, 
ExtraData=FdfFilename)
 
@@ -129,13 +134,13 @@
                 ActivePlatform = os.path.realpath(ActivePlatform)
 
             if not os.path.isabs (ActivePlatform):
-                ActivePlatform = 
os.path.join(GenFdsGlobalVariable.WorkSpaceDir, ActivePlatform)
+                ActivePlatform = mws.join(GenFdsGlobalVariable.WorkSpaceDir, 
ActivePlatform)
 
             if not os.path.exists(ActivePlatform)  :
                 EdkLogger.error("GenFds", FILE_NOT_FOUND, "ActivePlatform 
doesn't exist!")
 
             if os.path.normcase (ActivePlatform).find(Workspace) == 0:
-                ActivePlatform = ActivePlatform[len(Workspace):]
+                ActivePlatform = mws.relpath(ActivePlatform, Workspace)
             if len(ActivePlatform) > 0 :
                 if ActivePlatform[0] == '\\' or ActivePlatform[0] == '/':
                     ActivePlatform = ActivePlatform[1:]
@@ -159,7 +164,7 @@
                 ConfDirectoryPath = 
os.path.join(GenFdsGlobalVariable.WorkSpaceDir, ConfDirectoryPath)
         else:
             # Get standard WORKSPACE/Conf, use the absolute path to the 
WORKSPACE/Conf
-            ConfDirectoryPath = 
os.path.join(GenFdsGlobalVariable.WorkSpaceDir, 'Conf')
+            ConfDirectoryPath = mws.join(GenFdsGlobalVariable.WorkSpaceDir, 
'Conf')
         GenFdsGlobalVariable.ConfDir = ConfDirectoryPath
         BuildConfigurationFile = 
os.path.normpath(os.path.join(ConfDirectoryPath, "target.txt"))
         if os.path.isfile(BuildConfigurationFile) == True:

Modified: trunk/edk2/BaseTools/Source/Python/GenFds/GenFdsGlobalVariable.py
===================================================================
--- trunk/edk2/BaseTools/Source/Python/GenFds/GenFdsGlobalVariable.py   
2015-10-08 05:51:57 UTC (rev 18578)
+++ trunk/edk2/BaseTools/Source/Python/GenFds/GenFdsGlobalVariable.py   
2015-10-08 09:27:14 UTC (rev 18579)
@@ -31,6 +31,7 @@
 import Common.DataType as DataType
 from Common.Misc import PathClass
 from Common.LongFilePathSupport import OpenLongFilePath as open
+from Common.MultipleWorkspace import MultipleWorkspace as mws
 
 ## Global variables
 #
@@ -322,12 +323,13 @@
     #   @param  String           String that may contain macro
     #
     def ReplaceWorkspaceMacro(String):
+        String = mws.handleWsMacro(String)
         Str = String.replace('$(WORKSPACE)', GenFdsGlobalVariable.WorkSpaceDir)
         if os.path.exists(Str):
             if not os.path.isabs(Str):
                 Str = os.path.abspath(Str)
         else:
-            Str = os.path.join(GenFdsGlobalVariable.WorkSpaceDir, String)
+            Str = mws.join(GenFdsGlobalVariable.WorkSpaceDir, String)
         return os.path.normpath(Str)
 
     ## Check if the input files are newer than output files

Modified: trunk/edk2/BaseTools/Source/Python/GenFds/Region.py
===================================================================
--- trunk/edk2/BaseTools/Source/Python/GenFds/Region.py 2015-10-08 05:51:57 UTC 
(rev 18578)
+++ trunk/edk2/BaseTools/Source/Python/GenFds/Region.py 2015-10-08 09:27:14 UTC 
(rev 18579)
@@ -24,6 +24,7 @@
 from Common import EdkLogger
 from Common.BuildToolError import *
 from Common.LongFilePathSupport import OpenLongFilePath as open
+from Common.MultipleWorkspace import MultipleWorkspace as mws
 
 ## generate Region
 #
@@ -205,7 +206,7 @@
             for RegionData in self.RegionDataList:
                 RegionData = GenFdsGlobalVariable.MacroExtend(RegionData, 
MacroDict)
                 if RegionData[1] != ':' :
-                    RegionData = os.path.join 
(GenFdsGlobalVariable.WorkSpaceDir, RegionData)
+                    RegionData = mws.join (GenFdsGlobalVariable.WorkSpaceDir, 
RegionData)
                 if not os.path.exists(RegionData):
                     EdkLogger.error("GenFds", FILE_NOT_FOUND, 
ExtraData=RegionData)
                 #

Modified: trunk/edk2/BaseTools/Source/Python/Workspace/WorkspaceDatabase.py
===================================================================
--- trunk/edk2/BaseTools/Source/Python/Workspace/WorkspaceDatabase.py   
2015-10-08 05:51:57 UTC (rev 18578)
+++ trunk/edk2/BaseTools/Source/Python/Workspace/WorkspaceDatabase.py   
2015-10-08 09:27:14 UTC (rev 18579)
@@ -21,6 +21,7 @@
 
 import Common.EdkLogger as EdkLogger
 import Common.GlobalData as GlobalData
+from Common.MultipleWorkspace import MultipleWorkspace as mws
 
 from Common.String import *
 from Common.DataType import *
@@ -166,7 +167,7 @@
             ModuleFile = PathClass(NormPath(Record[0]), GlobalData.gWorkspace, 
Arch=self._Arch)
             RecordList = 
self._RawData[MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH, self._Arch, None, 
ModuleId]
             if RecordList != []:
-                SourceOverridePath = os.path.join(GlobalData.gWorkspace, 
NormPath(RecordList[0][0]))
+                SourceOverridePath = mws.join(GlobalData.gWorkspace, 
NormPath(RecordList[0][0]))
 
                 # Check if the source override path exists
                 if not os.path.isdir(SourceOverridePath):
@@ -2179,8 +2180,11 @@
                 if self.AutoGenVersion < 0x00010005:
                     Macros["EDK_SOURCE"] = GlobalData.gEcpSource
                     Macros['PROCESSOR'] = self._Arch
+                    SourceFile = NormPath(Record[0], Macros)
+                    if SourceFile[0] == os.path.sep:
+                        SourceFile = mws.join(GlobalData.gWorkspace, 
SourceFile[1:])
                     # old module source files (Edk)
-                    File = PathClass(NormPath(Record[0], Macros), 
self._ModuleDir, self._SourceOverridePath,
+                    File = PathClass(SourceFile, self._ModuleDir, 
self._SourceOverridePath,
                                      '', False, self._Arch, ToolChainFamily, 
'', TagName, ToolCode)
                     # check the file validation
                     ErrorCode, ErrorInfo = File.Validate(CaseSensitive=False)
@@ -2343,10 +2347,21 @@
                     if File[0] == '.':
                         File = os.path.join(self._ModuleDir, File)
                     else:
-                        File = os.path.join(GlobalData.gWorkspace, File)
+                        File = mws.join(GlobalData.gWorkspace, File)
                     File = RealPath(os.path.normpath(File))
                     if File:
                         self._Includes.append(File)
+                    if not File and Record[0].find('EFI_SOURCE') > -1:
+                        # tricky to regard WorkSpace as EFI_SOURCE
+                        Macros['EFI_SOURCE'] = GlobalData.gWorkspace
+                        File = NormPath(Record[0], Macros)
+                        if File[0] == '.':
+                            File = os.path.join(self._ModuleDir, File)
+                        else:
+                            File = os.path.join(GlobalData.gWorkspace, File)
+                        File = RealPath(os.path.normpath(File))
+                        if File:
+                            self._Includes.append(File)
         return self._Includes
 
     ## Retrieve packages this module depends on
@@ -2797,7 +2812,7 @@
     def __init__(self, DbPath, RenewDb=False):
         self._DbClosedFlag = False
         if not DbPath:
-            DbPath = os.path.normpath(os.path.join(GlobalData.gWorkspace, 
'Conf', GlobalData.gDatabasePath))
+            DbPath = os.path.normpath(mws.join(GlobalData.gWorkspace, 'Conf', 
GlobalData.gDatabasePath))
 
         # don't create necessary path for db in memory
         if DbPath != ':memory:':

Modified: trunk/edk2/BaseTools/Source/Python/build/BuildReport.py
===================================================================
--- trunk/edk2/BaseTools/Source/Python/build/BuildReport.py     2015-10-08 
05:51:57 UTC (rev 18578)
+++ trunk/edk2/BaseTools/Source/Python/build/BuildReport.py     2015-10-08 
09:27:14 UTC (rev 18579)
@@ -41,6 +41,7 @@
 from Common.DataType import TAB_BRG_LIBRARY
 from Common.DataType import TAB_BACK_SLASH
 from Common.LongFilePathSupport import OpenLongFilePath as open
+from Common.MultipleWorkspace import MultipleWorkspace as mws
 
 ## Pattern to extract contents in EDK DXS files
 gDxsDependencyPattern = re.compile(r"DEPENDENCY_START(.+)DEPENDENCY_END", 
re.DOTALL)
@@ -1255,7 +1256,7 @@
         for Pa in Wa.AutoGenObjectList:
             for ModuleKey in Pa.Platform.Modules:
                 M = Pa.Platform.Modules[ModuleKey].M
-                InfPath = os.path.join(Wa.WorkspaceDir, M.MetaFile.File)
+                InfPath = mws.join(Wa.WorkspaceDir, M.MetaFile.File)
                 self._GuidsDb[M.Guid.upper()] = "%s (%s)" % 
(M.Module.BaseName, InfPath)
 
         #
@@ -1277,7 +1278,7 @@
                             Guid = 
GuidStructureByteArrayToGuidString(GuidValue).upper()
                     for Section in Ffs.SectionList:
                         try:
-                            ModuleSectFile = os.path.join(Wa.WorkspaceDir, 
Section.SectFileName)
+                            ModuleSectFile = mws.join(Wa.WorkspaceDir, 
Section.SectFileName)
                             self._GuidsDb[Guid] = ModuleSectFile
                         except AttributeError:
                             pass

Modified: trunk/edk2/BaseTools/Source/Python/build/build.py
===================================================================
--- trunk/edk2/BaseTools/Source/Python/build/build.py   2015-10-08 05:51:57 UTC 
(rev 18578)
+++ trunk/edk2/BaseTools/Source/Python/build/build.py   2015-10-08 09:27:14 UTC 
(rev 18579)
@@ -41,6 +41,7 @@
 from AutoGen.AutoGen import *
 from Common.BuildToolError import *
 from Workspace.WorkspaceDatabase import *
+from Common.MultipleWorkspace import MultipleWorkspace as mws
 
 from BuildReport import BuildReport
 from GenPatchPcdTable.GenPatchPcdTable import *
@@ -104,12 +105,16 @@
         EdkLogger.error("build", FORMAT_NOT_SUPPORTED, "No space is allowed in 
WORKSPACE path",
                         ExtraData=WorkspaceDir)
     os.environ["WORKSPACE"] = WorkspaceDir
+    
+    # set multiple workspace
+    PackagesPath = os.getenv("PACKAGES_PATH")
+    mws.setWs(WorkspaceDir, PackagesPath)
 
     #
     # Check EFI_SOURCE (Edk build convention). EDK_SOURCE will always point to 
ECP
     #
     if "ECP_SOURCE" not in os.environ:
-        os.environ["ECP_SOURCE"] = os.path.join(WorkspaceDir, 
GlobalData.gEdkCompatibilityPkg)
+        os.environ["ECP_SOURCE"] = mws.join(WorkspaceDir, 
GlobalData.gEdkCompatibilityPkg)
     if "EFI_SOURCE" not in os.environ:
         os.environ["EFI_SOURCE"] = os.environ["ECP_SOURCE"]
     if "EDK_SOURCE" not in os.environ:
@@ -182,7 +187,7 @@
     GlobalData.gGlobalDefines["EDK_SOURCE"] = EdkSourceDir
     GlobalData.gGlobalDefines["ECP_SOURCE"] = EcpSourceDir
     GlobalData.gGlobalDefines["EDK_TOOLS_PATH"] = os.environ["EDK_TOOLS_PATH"]
-
+    
 ## Get normalized file path
 #
 # Convert the path to be local format, and remove the WORKSPACE path at the
@@ -198,7 +203,8 @@
     if os.path.isabs(FilePath):
         FileFullPath = os.path.normpath(FilePath)
     else:
-        FileFullPath = os.path.normpath(os.path.join(Workspace, FilePath))
+        FileFullPath = os.path.normpath(mws.join(Workspace, FilePath))
+        Workspace = mws.getWs(Workspace, FilePath)
 
     # check if the file path exists or not
     if not os.path.isfile(FileFullPath):
@@ -748,10 +754,10 @@
             if not os.path.isabs(ConfDirectoryPath):
                 # Since alternate directory name is not absolute, the 
alternate directory is located within the WORKSPACE
                 # This also handles someone specifying the Conf directory in 
the workspace. Using --conf=Conf
-                ConfDirectoryPath = os.path.join(self.WorkspaceDir, 
ConfDirectoryPath)
+                ConfDirectoryPath = mws.join(self.WorkspaceDir, 
ConfDirectoryPath)
         else:
             # Get standard WORKSPACE/Conf use the absolute path to the 
WORKSPACE/Conf
-            ConfDirectoryPath = os.path.join(self.WorkspaceDir, 'Conf')
+            ConfDirectoryPath = mws.join(self.WorkspaceDir, 'Conf')
         GlobalData.gConfDirectory = ConfDirectoryPath
         GlobalData.gDatabasePath = 
os.path.normpath(os.path.join(ConfDirectoryPath, GlobalData.gDatabasePath))
 
@@ -796,7 +802,7 @@
             ToolDefinitionFile = 
self.TargetTxt.TargetTxtDictionary[DataType.TAB_TAT_DEFINES_TOOL_CHAIN_CONF]
             if ToolDefinitionFile == '':
                 ToolDefinitionFile = gToolsDefinition
-                ToolDefinitionFile = 
os.path.normpath(os.path.join(self.WorkspaceDir, 'Conf', ToolDefinitionFile))
+                ToolDefinitionFile = 
os.path.normpath(mws.join(self.WorkspaceDir, 'Conf', ToolDefinitionFile))
             if os.path.isfile(ToolDefinitionFile) == True:
                 StatusCode = self.ToolDef.LoadToolDefFile(ToolDefinitionFile)
             else:


------------------------------------------------------------------------------
_______________________________________________
edk2-commits mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/edk2-commits

Reply via email to