From 2897231803d9d506f7cb7c68eeb59dcc4805084d Mon Sep 17 00:00:00 2001 From: jwang36 Date: Mon, 22 Jan 2007 09:59:07 +0000 Subject: [PATCH] Python script for generating build files for platform and modules, which uses the enhanced XmlRoutines.py written by Bruce. The functionalities include: - parse all packages(.spd) and modules(.msa) - parse active platform(.fpd). You must set active platform in target.txt otherwise nothing will be parsed. - parse tools_def.txt and target.txt - generate Ant build files for active platform and its modules. The generated build file is re-designed and can be called separately once generated. - multi-thread build The functionalities which haven't been implemented include: - AutoGen. No AutoGen.h and AutoGen.c will be generated. If you want run the build file, you have to run the "build" command in advance to generate the AutoGen.h/.c files and remove the any other intermediate files. - generate FFS and FV files. Only compiling will be done by the generated build file. Usage: - type "python ${WORKSPACE}/Tools/Python/buildgen/BuildFile.py" in shell to generate build file - goto "${WORKSPACE}/Build/${platform}/${target}_${toolchaintag}/", type "ant" to run the build file git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@2278 6f19259b-4bc3-4df7-8a09-765794883524 --- Tools/Python/buildgen/AntTasks.py | 84 + Tools/Python/buildgen/BuildConfig.py | 185 ++ Tools/Python/buildgen/BuildFile.py | 574 ++++++ Tools/Python/buildgen/FrameworkElement.py | 523 ++++++ Tools/Python/buildgen/SurfaceAreaElement.py | 1549 +++++++++++++++++ Tools/Python/buildgen/XmlRoutines.py | 104 ++ Tools/Python/buildgen/module_build_path.txt | 5 + Tools/Python/buildgen/platform_build_path.txt | 5 + 8 files changed, 3029 insertions(+) create mode 100644 Tools/Python/buildgen/AntTasks.py create mode 100644 Tools/Python/buildgen/BuildConfig.py create mode 100644 Tools/Python/buildgen/BuildFile.py create mode 100644 Tools/Python/buildgen/FrameworkElement.py create mode 100644 Tools/Python/buildgen/SurfaceAreaElement.py create mode 100644 Tools/Python/buildgen/XmlRoutines.py create mode 100644 Tools/Python/buildgen/module_build_path.txt create mode 100644 Tools/Python/buildgen/platform_build_path.txt diff --git a/Tools/Python/buildgen/AntTasks.py b/Tools/Python/buildgen/AntTasks.py new file mode 100644 index 0000000000..ce694f9b80 --- /dev/null +++ b/Tools/Python/buildgen/AntTasks.py @@ -0,0 +1,84 @@ +#!/usr/bin/env python + +# Copyright (c) 2007, Intel Corporation +# All rights reserved. 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. + +"""Ant Tasks Dom Element""" + +import xml.dom.minidom, os + +class AntTask: + def __init__(self, document, _name, _body=None, **_attributes): + """Instantiate an Ant task element + document, _name=task name, _body=task body, **_attributes=task attributes + """ + self.Document = document + self.Root = "" + + if _name == None or _name == "": + raise Exception("No Ant task name") + + taskElement = self.Document.createElement(_name) + for name in _attributes: + taskElement.setAttribute(name, _attributes[name]) + + if _body != None: + if isinstance(_body, str): + text = self.Document.createTextNode(_body) + taskElement.appendChild(text) + elif isinstance(_body, list): + for subtask in _body: + taskElement.appendChild(subtask) + + self.Root = taskElement + + def SubTask(self, _name, _body=None, **_attributes): + """Insert a sub-task into this task""" + newTask = AntTask(self.Document, _name , _body, **_attributes) + self.Root.appendChild(newTask.Root) + return newTask + + def AddSubTask(self, subTask): + """Insert a existing sub-task into this task""" + self.Root.appendChild(subTask.Root.cloneNode(True)) + return subTask + + def Comment(self, string): + """Generate a XML comment""" + self.Root.appendChild(self.Document.createComment(string)) + + def Blankline(self): + """Generate a blank line""" + self.Root.appendChild(self.Document.createTextNode("")) + + +class AntBuildFile(AntTask): + _FileComment = "DO NOT EDIT\nThis file is auto-generated by the build utility\n\nAbstract:\nAuto-generated ANT build file for building Framework modules and platforms\n" + + def __init__(self, name, basedir=".", default="all"): + """Instantiate an Ant build.xml + name=project name, basedir=project default directory, default=default target of this project + """ + self.Document = xml.dom.minidom.getDOMImplementation().createDocument(None, "project", None) + self.Root = self.Document.documentElement + + self.Document.insertBefore(self.Document.createComment(self._FileComment), self.Root) + self.Root.setAttribute("name", name) + self.Root.setAttribute("basedir", basedir) + self.Root.setAttribute("default", default) + + def Create(self, file): + """Generate the build.xml using given file path""" + buildFileDir = os.path.dirname(file) + if not os.path.exists(buildFileDir): + os.makedirs(buildFileDir) + + f = open(file, "w") + f.write(self.Document.toprettyxml(2*" ", encoding="UTF-8")) + f.close() diff --git a/Tools/Python/buildgen/BuildConfig.py b/Tools/Python/buildgen/BuildConfig.py new file mode 100644 index 0000000000..e91bd294a5 --- /dev/null +++ b/Tools/Python/buildgen/BuildConfig.py @@ -0,0 +1,185 @@ +#!/usr/bin/env python + +# Copyright (c) 2007, Intel Corporation +# All rights reserved. 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. + +"""Tools and build configuration""" + +from sets import Set + +class Config(dict): + def __init__(self, file): + """file (target configuration file)""" + configFile = open(file) + while True: + line = configFile.readline() + if line == "": break ## no more line + + line = line.strip() + # skip blank line + if line == "": continue + # skip comment line + if line[0] == '#': continue + # skip invalid line + if line[0] == '=': + print "! invalid configuration:", line + continue + + defStrings = line.split('=', 1) + name = defStrings[0].strip() + value = defStrings[1].strip() + self[name] = value + + configFile.close() + + def __getitem__(self, attr): + if attr not in self: + return "" + + value = dict.__getitem__(self, attr) + if value == None: + value = "" + return value + +class ToolConfig(dict): + def __init__(self, file): + """file (tools configuration file path)""" + self.Targets = Set() + self.Toolchains = Set() + self.Archs = Set() + self.ToolCodes = Set() + self.Families = Set() + self.Attributes = Set(["FAMILY", "NAME", "PATH", "FLAGS", "EXT", "DPATH", "SPATH", "LIBPATH", "INCLUDEPATH"]) + + configFile = open(file) + while True: + line = configFile.readline() + if line == "": break + + line = line.strip() + # skip blank line + if line == "": continue + # skip comment line + if line[0] == '#': continue + # skip invalid line + if line[0] == '=': + print "! invalid definition:", line + continue + + # split the definition at the first "=" + tool_def = line.split('=', 1) + name = tool_def[0].strip() + value = tool_def[1].strip() + + # the name of a tool definition must have five parts concatenated by "_" + keys = name.split('_') + # skip non-definition line + if len(keys) < 5: continue + + keys = (keys[1], keys[0], keys[2], keys[3], keys[4]) + self[keys] = value + + ############################################### + ## statistics + ############################################### + if keys[0] != '*': self.Toolchains.add(keys[0]) + if keys[1] != '*': self.Targets.add(keys[1]) + if keys[2] != '*': self.Archs.add(keys[2]) + if keys[3] != '*': self.ToolCodes.add(keys[3]) + if keys[4] == "FAMILY": self.Families.add(value) + elif keys[4] == '*': raise Exception("No * allowed in ATTRIBUTE field") + + configFile.close() + # expand the "*" in each field + self.expand() + + def __getitem__(self, attrs): + if len(attrs) != 5: + return "" + + if attrs not in self: + return "" + + value = dict.__getitem__(self, attrs) + if value == None: + value = "" + return value + + def expand(self): + summary = {} + toolchains = [] + targets = [] + archs = [] + toolcodes = [] + for key in self: + value = self[key] + if key[0] == '*': + toolchains = self.Toolchains + else: + toolchains = [key[0]] + + for toolchain in toolchains: + if key[1] == '*': + targets = self.Targets + else: + targets = [key[1]] + + for target in targets: + if key[2] == '*': + archs = self.Archs + else: + archs = [key[2]] + + for arch in archs: + if key[3] == '*': + toolcodes = self.ToolCodes + else: + toolcodes = [key[3]] + + for toolcode in toolcodes: + attribute = key[4] + summary[(toolchain, target, arch, toolcode, attribute)] = value + self.clear() + for toolchain in self.Toolchains: + for target in self.Targets: + for arch in self.Archs: + for toolcode in self.ToolCodes: + key = (toolchain, target, arch, toolcode, "NAME") + if key not in summary: continue + for attr in self.Attributes: + key = (toolchain, target, arch, toolcode, attr) + if key not in summary: continue + self[key] = summary[key] + + + def __str__(self): + s = "" + for entry in self: + s += entry[0] + "_" + entry[1] + "_" + entry[2] + "_" + entry[3] + "_" + entry[4] + s += " = " + self[entry] + "\n" + return s + +class TargetConfig(Config): + pass + +## for test +if __name__ == "__main__": + import os + if "WORKSPACE" not in os.environ: + raise "No WORKSPACE given" + cfg = ToolConfig(os.path.join(os.environ["WORKSPACE"], "Tools", "Conf", "tools_def.txt")) + tgt = TargetConfig(os.path.join(os.environ["WORKSPACE"], "Tools", "Conf", "target.txt")) + + for key in cfg: + print key,"=",cfg[key] + + print + for name in tgt: + print name,"=",tgt[name] + \ No newline at end of file diff --git a/Tools/Python/buildgen/BuildFile.py b/Tools/Python/buildgen/BuildFile.py new file mode 100644 index 0000000000..8514e4c8a4 --- /dev/null +++ b/Tools/Python/buildgen/BuildFile.py @@ -0,0 +1,574 @@ +#!/usr/bin/env python + +# Copyright (c) 2007, Intel Corporation +# All rights reserved. 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. + +"""Generate build file for given platform""" + +import os, sys, copy +import xml.dom.minidom, pprint +import FrameworkElement + +from SurfaceAreaElement import * +from XmlRoutines import * +from AntTasks import * +from sets import Set + +class BuildFile: + def __init__(self, workspace, platform, toolchain, target): + if workspace == None or workspace == "": + raise Exception("No workspace, no build") + if platform == None or platform == "": + raise Exception("No platform, no build") + if toolchain == None or toolchain == "": + raise Exception("No toolchain, no build") + if target == None or target == "": + raise Exception("No target, no build") + + self.Workspace = workspace + self.Platform = platform + self.Toolchain = toolchain + self.Target = target + self.Path = "" + + def Generate(self): + """Generate the build file""" + pass + +# generating build.xml for platform +class AntPlatformBuildFile(BuildFile): + def __init__(self, workspace, platform, toolchain, target): + BuildFile.__init__(self, workspace, platform, toolchain, target) + # Form the build file path, hard-coded at present. It should be specified by a configuration file + self.Path = os.path.join(self.Workspace.Path, self.Platform.OutputPath, target + "_" + toolchain, "build.xml") + print "" + # Generate a common build option property file in the format of Java's property file + self.DefaultBuildOptions() + + # new a build file object + self.BuildXml = AntBuildFile(name="platform", basedir=".", default="all") + + # generate the top level properties, tasks, etc. + self.Header() + + # generate "prebuild" target + self.PreBuild() + + # generate "libraries" target for building library modules + self.Libraries() + + # generate "modules" target for building non-library modules + self.Modules() + + # generate "fvs" target for building firmware volume. (not supported yet) + + # generate "fds" target for building FlashDevice. (not supported yet) + + # generate "postbuild" target + self.PostBuild() + + def Generate(self): + print "Generating platform build file ...", self.Path + self.BuildXml.Create(self.Path) + + def Header(self): + _topLevel = self.BuildXml + # import external tasks + _topLevel.SubTask("taskdef", resource="GenBuild.tasks") + _topLevel.SubTask("taskdef", resource="frameworktasks.tasks") + _topLevel.SubTask("taskdef", resource="net/sf/antcontrib/antlib.xml") + + # platform wide properties + _topLevel.Blankline() + _topLevel.Comment("WORKSPACE wide attributes") + _topLevel.SubTask("property", environment="env") + _topLevel.SubTask("property", name="WORKSPACE_DIR", value="${env.WORKSPACE}") + _topLevel.SubTask("property", name="CONFIG_DIR", value="${WORKSPACE_DIR}/Tools/Conf") + + _topLevel.Blankline() + _topLevel.Comment("Common build attributes") + _topLevel.SubTask("property", name="THREAD_COUNT", value=self.Workspace.ThreadCount) + _topLevel.SubTask("property", name="SINGLE_MODULE_BUILD", value="no") + _topLevel.SubTask("property", name="MODULE_BUILD_TARGET", value="platform_module_build") + + _topLevel.Blankline() + _topLevel.SubTask("property", name="TOOLCHAIN", value=self.Toolchain) + _topLevel.SubTask("property", name="TARGET", value=self.Target) + + _topLevel.Blankline() + _topLevel.Comment("Platform attributes") + _topLevel.SubTask("property", name="PLATFORM", value=self.Platform.Name) + _topLevel.SubTask("property", name="PLATFORM_GUID", value=self.Platform.GuidValue) + _topLevel.SubTask("property", name="PLATFORM_VERSION", value=self.Platform.Version) + _topLevel.SubTask("property", name="PLATFORM_RELATIVE_DIR", value=self.Platform.Dir) + _topLevel.SubTask("property", name="PLATFORM_DIR", value="${WORKSPACE_DIR}/${PLATFORM_RELATIVE_DIR}") + _topLevel.SubTask("property", name="PLATFORM_OUTPUT_DIR", value=self.Platform.OutputPath) + + # user configurable build path for platform + _topLevel.Blankline() + _topLevel.Comment("Common path definition for platform build") + _topLevel.SubTask("property", file="${WORKSPACE_DIR}/Tools/Python/buildgen/platform_build_path.txt") + + # common build tasks in the form of Ant macro + _topLevel.Blankline() + _topLevel.Comment("Task Macros for Compiling, Assembling, Linking, etc.") + _topLevel.SubTask("import", file="${CONFIG_DIR}/BuildMacro.xml") + _topLevel.Blankline() + _topLevel.SubTask("echo", message="${PLATFORM}-${PLATFORM_VERSION} (${PLATFORM_RELATIVE_DIR})", level="info") + + # define the targets execution sequence + _topLevel.Blankline() + _topLevel.Comment("Default target") + _topLevel.SubTask("target", name="all", depends="prebuild, libraries, modules, postbuild") + + def PreBuild(self): + _topLevel = self.BuildXml + _topLevel.Blankline() + _topLevel.Comment(" TARGET: prebuild ") + + # prebuild is defined by user in the fpd file through element, + # which has attribute "identifier=0" or "identifier=prebuild" + prebuildTasks = [] + if self.Platform.UserExtensions.has_key("0"): + prebuildTasks = self.Platform.UserExtensions["0"] + elif self.Platform.UserExtensions.has_key("postbuild"): + prebuildTasks = self.Platform.UserExtensions["prebuild"] + + _topLevel.SubTask("target", prebuildTasks, name="prebuild") + + def Libraries(self): + _topLevel = self.BuildXml + _topLevel.Blankline() + _topLevel.Comment(" TARGET: libraries ") + + librariesTarget = _topLevel.SubTask("target", name="libraries") + parallelBuild = librariesTarget.SubTask("parallel", threadCount="${THREAD_COUNT}") + + libraryNumber = 0 + for arch in self.Platform.Libraries: + libraryNumber += len(self.Platform.Libraries[arch]) + libraryIndex = 0 + for arch in self.Platform.Libraries: + for lib in self.Platform.Libraries[arch]: + libraryIndex += 1 + print "Generating library build files ... %d%%\r" % int((float(libraryIndex) / float(libraryNumber)) * 100), + buildFile = AntModuleBuildFile(self.Workspace, self.Platform, lib, self.Toolchain, self.Target, arch) + buildFile.Generate() + buildDir = os.path.join("${TARGET_DIR}", arch, lib.Module.Package.SubPath(lib.Module.Dir), + lib.Module.FileBaseName) + parallelBuild.SubTask("ant", dir=buildDir, + #antfile="build.xml", + inheritAll="true", + target="${MODULE_BUILD_TARGET}") + print "" + + def Modules(self): + _topLevel = self.BuildXml + _topLevel.Blankline() + _topLevel.Comment(" TARGET: modules ") + + modulesTarget = _topLevel.SubTask("target", name="modules") + parallelBuild = modulesTarget.SubTask("parallel", threadCount="${THREAD_COUNT}") + + moduleNumber = 0 + for arch in self.Platform.Modules: + moduleNumber += len(self.Platform.Modules[arch]) + + moduleIndex = 0 + for arch in self.Platform.Modules: + for module in self.Platform.Modules[arch]: + moduleIndex += 1 + print "Generating module build files ... %d%%\r" % int((float(moduleIndex) / float(moduleNumber)) * 100), + + buildDir = os.path.join("${TARGET_DIR}", arch, module.Module.Package.SubPath(module.Module.Dir), + module.Module.FileBaseName) + parallelBuild.SubTask("ant", dir=buildDir, + #antfile="build.xml", + inheritAll="true", + target="${MODULE_BUILD_TARGET}") + buildFile = AntModuleBuildFile(self.Workspace, self.Platform, module, self.Toolchain, self.Target, arch) + buildFile.Generate() + print "" + + def Fvs(self): + pass + + def Fds(self): + pass + + def PostBuild(self): + _topLevel = self.BuildXml + _topLevel.Blankline() + _topLevel.Comment(" TARGET: postbuild ") + + # postbuild is defined by user in the fpd file through element, + # which has attribute "identifier=1" or "identifier=postbuild" + postbuildTasks = [] + if self.Platform.UserExtensions.has_key("1"): + postbuildTasks = self.Platform.UserExtensions["1"] + elif self.Platform.UserExtensions.has_key("postbuild"): + postbuildTasks = self.Platform.UserExtensions["postbuild"] + + _topLevel.SubTask("target", postbuildTasks, name="postbuild") + + def Clean(self): + pass + + def CleanAll(self): + pass + + def UserExtensions(self): + pass + + def DefaultBuildOptions(self): + """Generate ${ARCH}_build.opt which contains the default build&tool definitions""" + tools = self.Workspace.ToolConfig.ToolCodes + for arch in self.Workspace.ActiveArchs: + optFileDir = os.path.join(self.Workspace.Path, self.Platform.OutputPath, + self.Target + "_" + self.Toolchain) + optFileName = arch + "_build.opt" + if not os.path.exists(optFileDir): os.makedirs(optFileDir) + f = open(os.path.join(optFileDir, optFileName), "w") + for tool in tools: + key = (self.Toolchain, self.Target, arch, tool, "FLAGS") + flag = self.Workspace.ToolConfig[key] + f.write("DEFAULT_%s_FLAGS=%s\n" % (tool, flag)) + + f.write("\n") + for tool in tools: + key = (self.Toolchain, self.Target, arch, tool, "FLAGS") + if key in self.Platform.BuildOptions: + flag = self.Platform.BuildOptions[key] + else: + key = (self.Toolchain, self.Target, arch, tool, "FAMILY") + family = self.Workspace.ToolConfig[key] + key = (family, self.Target, arch, tool, "FLAGS") + if key in self.Platform.BuildOptions: + flag = self.Platform.BuildOptions[key] + else: + flag = "" + f.write("PLATFORM_%s_FLAGS=%s\n" % (tool, flag)) + + f.write("\n") + for tool in tools: + for attr in self.Workspace.ToolConfig.Attributes: + if attr == "FLAGS": continue + key = (self.Toolchain, self.Target, arch, tool, attr) + value = self.Workspace.ToolConfig[key] + if attr == "NAME": + f.write("%s=%s\n" % (tool, value)) + else: + f.write("%s_%s=%s\n" % (tool, attr, value)) + f.write("%s_FLAGS=${DEFAULT_%s_FLAGS} ${DEFAULT_MODULE_%s_FLAGS} ${PLATFORM_%s_FLAGS} ${MODULE_%s_FLAGS}\n" % + (tool, tool, tool, tool, tool)) + f.write("\n") + + f.close() + +class AntModuleBuildFile(BuildFile): + def __init__(self, workspace, platform, module, toolchain, target, arch): + BuildFile.__init__(self, workspace, platform, toolchain, target) + self.Module = module + self.Arch = arch + self.Path = os.path.join(self.Workspace.Path, self.Platform.OutputPath, + target + "_" + toolchain, arch, self.Module.Module.Package.Dir, + self.Module.Module.Dir, self.Module.Module.FileBaseName, "build.xml") + self.BuildXml = AntBuildFile(self.Module.Module.Name) + + self.SourceFiles = self.GetSourceFiles() + + self.Header() + self.PreBuild() + self.Libraries() + self.Sourcefiles() + self.Sections() + self.Ffs() + self.PostBuild() + + def Generate(self): + # print self.Path,"\r", + self.BuildXml.Create(self.Path) + + def Header(self): + _topLevel = self.BuildXml + _topLevel.SubTask("taskdef", resource="frameworktasks.tasks") + _topLevel.SubTask("taskdef", resource="cpptasks.tasks") + _topLevel.SubTask("taskdef", resource="cpptasks.types") + _topLevel.SubTask("taskdef", resource="net/sf/antcontrib/antlib.xml") + + _topLevel.Blankline() + _topLevel.Comment(" TODO ") + _topLevel.SubTask("property", environment="env") + _topLevel.SubTask("property", name="WORKSPACE_DIR", value="${env.WORKSPACE}") + + _topLevel.Blankline() + _topLevel.Comment("Common build attributes") + _topLevel.SubTask("property", name="SINGLE_MODULE_BUILD", value="yes") + _topLevel.SubTask("property", name="MODULE_BUILD_TARGET", value="single_module_build") + _topLevel.SubTask("property", name="PLATFORM_PREBUILD", value="yes") + _topLevel.SubTask("property", name="PLATFORM_POSTBUILD", value="no") + + _topLevel.Blankline() + _topLevel.Comment(" TODO ") + ifTask = _topLevel.SubTask("if") + ifTask.SubTask("istrue", value="${SINGLE_MODULE_BUILD}") + thenTask = ifTask.SubTask("then") + platformBuildFile = os.path.join("${WORKSPACE_DIR}", self.Platform.OutputPath, + self.Target + "_" + self.Toolchain, "build.xml") + thenTask.SubTask("import", file=platformBuildFile) + + _topLevel.Blankline() + _topLevel.SubTask("property", name="ARCH", value=self.Arch) + + module = self.Module.Module + package = module.Package + _topLevel.Blankline() + _topLevel.SubTask("property", name="PACKAGE", value=package.Name) + _topLevel.SubTask("property", name="PACKAGE_GUID", value=package.GuidValue) + _topLevel.SubTask("property", name="PACKAGE_VERSION", value=package.Version) + _topLevel.SubTask("property", name="PACKAGE_RELATIVE_DIR", value=package.Dir) + _topLevel.SubTask("property", name="PACKAGE_DIR", value=os.path.join("${WORKSPACE_DIR}","${PACKAGE_RELATIVE_DIR}")) + + _topLevel.Blankline() + _topLevel.SubTask("property", name="MODULE", value=module.Name) + _topLevel.SubTask("property", name="MODULE_GUID", value=module.GuidValue) + _topLevel.SubTask("property", name="MODULE_VERSION", value=module.Version) + _topLevel.SubTask("property", name="MODULE_TYPE", value=module.Type) + _topLevel.SubTask("property", name="MODULE_FILE_BASE_NAME", value=module.FileBaseName) + _topLevel.SubTask("property", name="MODULE_RELATIVE_DIR", value=module.Dir) + _topLevel.SubTask("property", name="MODULE_DIR", value=os.path.join("${PACKAGE_DIR}", "${MODULE_RELATIVE_DIR}")) + _topLevel.SubTask("property", name="BASE_NAME", value=module.BaseName) + + _topLevel.Blankline() + _topLevel.SubTask("property", file="${WORKSPACE_DIR}/Tools/Python/buildgen/module_build_path.txt") + + self._BuildOption() + + _topLevel.Blankline() + _topLevel.SubTask("property", name="ENTRYPOINT", value="_ModuleEntryPoint") + + _topLevel.SubTask("property", name="SOURCE_FILES", value="\n ".join(self._GetSourceFileList())) + _topLevel.SubTask("property", name="LIBS", value="\n ".join(self._GetLibList())) + + _topLevel.Blankline() + _topLevel.SubTask("property", file="${PLATFORM_BUILD_DIR}/%s_build.opt" % self.Arch) + _topLevel.Blankline() + _topLevel.SubTask("echo", message="${MODULE}-${MODULE_VERSION} [${ARCH}] from package ${PACKAGE}-${PACKAGE_VERSION} (${MODULE_RELATIVE_DIR})", level="info") + + _topLevel.Blankline() + _topLevel.Comment("Default target") + _topLevel.SubTask("target", name="all", depends="single_module_build") + _topLevel.SubTask("target", name="platform_module_build", depends="prebuild, sourcefiles, sections, output, postbuild") + _topLevel.SubTask("target", name="single_module_build", depends="prebuild, libraries, sourcefiles, sections, output, postbuild") + + def _BuildOption(self): + _topLevel = self.BuildXml + _topLevel.Blankline() + baseModule = self.Module.Module + tools = self.Workspace.ToolConfig.ToolCodes + + for tool in tools: + key = (self.Toolchain, self.Target, self.Arch, tool, "FLAGS") + flag = "" + if key in baseModule.BuildOptions: + flag = baseModule.BuildOptions[key] + _topLevel.SubTask("property", name="DEFAULT_MODULE_%s_FLAGS" % tool, value=flag) + + _topLevel.Blankline() + for tool in tools: + key = (self.Toolchain, self.Target, self.Arch, tool, "FLAGS") + flag = "" + if key in self.Module.BuildOptions: + flag = self.Module.BuildOptions[key] + _topLevel.SubTask("property", name="MODULE_%s_FLAGS" % tool, value=flag) + + def PreBuild(self): + _topLevel = self.BuildXml + _topLevel.Blankline() + _topLevel.Comment(" TARGET: prebuild ") + + prebuildTasks = [] + module = self.Module.Module + if module.UserExtensions.has_key("0"): + prebuildTasks = module.UserExtensions["0"] + elif module.UserExtensions.has_key("postbuild"): + prebuildTasks = module.UserExtensions["prebuild"] + + _topLevel.SubTask("target", prebuildTasks, name="prebuild") + + + def Libraries(self): + _topLevel = self.BuildXml + _topLevel.Blankline() + _topLevel.Comment(" TARGET: libraries ") + + librariesTarget = _topLevel.SubTask("target", name="libraries") + parallelBuild = librariesTarget.SubTask("parallel", threadCount="${THREAD_COUNT}") + for lib in self.Module.Libraries: + module = lib.Module + buildDir = os.path.join("${BIN_DIR}", module.Package.SubPath(module.Dir), module.FileBaseName) + libTask = parallelBuild.SubTask("ant", dir=buildDir, + inheritAll="false", + target="${MODULE_BUILD_TARGET}") + libTask.SubTask("property", name="PLATFORM_PREBUILD", value="false") + libTask.SubTask("property", name="PLATFORM_POSTBUILD", value="false") + + def Sourcefiles(self): + _topLevel = self.BuildXml + _topLevel.Blankline() + _topLevel.Comment(" TARGET: sourcefiles ") + _sourcefilesTarget = _topLevel.SubTask("target", name="sourcefiles") + + _incTask = AntTask(self.BuildXml.Document, "EXTRA.INC") + _incTask.SubTask("includepath", path="${WORKSPACE_DIR}") + _incTask.SubTask("includepath", path="${MODULE_DIR}") + _incTask.SubTask("includepath", path=os.path.join("${MODULE_DIR}", self.Arch.capitalize())) + _incTask.SubTask("includepath", path="${DEST_DIR_DEBUG}") + if self.Arch in self.Module.Module.IncludePaths: + for inc in self.Module.Module.IncludePaths[self.Arch]: + _incTask.SubTask("includepath", path=os.path.join("${WORKSPACE_DIR}", inc)) + + # init + if not self.Module.Module.IsBinary: + _buildTask = _sourcefilesTarget.SubTask("Build_Init") + _buildTask.AddSubTask(_incTask) + + # AutoGen firt + _buildTask = _sourcefilesTarget.SubTask("Build_AUTOGEN", FILEEXT="c", FILENAME="AutoGen", FILEPATH=".") + _buildTask.AddSubTask(_incTask) + + # uni file follows + type = "UNI" + if type in self.SourceFiles: + for srcpath in self.SourceFiles[type]: + taskName = "Build_" + type + fileDir = os.path.dirname(srcpath) + if fileDir == "": fileDir = "." + fileBaseName,fileExt = os.path.basename(srcpath).rsplit(".", 1) + _buildTask = _sourcefilesTarget.SubTask(taskName, FILENAME=fileBaseName, FILEEXT=fileExt, FILEPATH=fileDir) + _buildTask.AddSubTask(_incTask) + + # others: c, vfr, ... + for type in self.SourceFiles: + if type == "Unicode": continue + for srcpath in self.SourceFiles[type]: + taskName = "Build_" + type + fileDir = os.path.dirname(srcpath) + if fileDir == "": fileDir = "." + fileBaseName,fileExt = os.path.basename(srcpath).rsplit(".", 1) + _buildTask = _sourcefilesTarget.SubTask(taskName, FILENAME=fileBaseName, FILEEXT=fileExt, FILEPATH=fileDir) + _buildTask.AddSubTask(_incTask) + + def Sections(self): + _topLevel = self.BuildXml + _topLevel.Blankline() + _topLevel.Comment(" TARGET: sections ") + _sectionsTarget = _topLevel.SubTask("target", name="sections") + + def Ffs(self): + _topLevel = self.BuildXml + _topLevel.Blankline() + _topLevel.Comment(" TARGET: output ") + _sectionsTarget = _topLevel.SubTask("target", name="output") + + def PostBuild(self): + _topLevel = self.BuildXml + _topLevel.Blankline() + _topLevel.Comment(" TARGET: postbuild ") + + postbuildTasks = [] + module = self.Module.Module + if module.UserExtensions.has_key("1"): + postbuildTasks = module.UserExtensions["1"] + elif module.UserExtensions.has_key("postbuild"): + postbuildTasks = module.UserExtensions["postbuild"] + + _topLevel.SubTask("target", postbuildTasks, name="postbuild") + + def Clean(self): + pass + + def CleanAll(self): + pass + + def UserExtensions(self): + pass + + def GetSourceFiles(self): + ## check arch, toolchain, family, toolcode, ext + ## if the arch of source file supports active arch + ## if the toolchain of source file supports active toolchain + ## if the toolchain family of source file supports active toolchain family + ## if the ext of the source file is supported by the toolcode + module = self.Module.Module + files = {} # file type -> src + for type in module.SourceFiles[self.Arch]: + if not module.IsBuildable(type): + # print type,"is not buildable" + continue + + if type not in files: + files[type] = [] + for src in module.SourceFiles[self.Arch][type]: + if self.Toolchain not in src.Toolchains: + # print self.Toolchain,"not in ",src.Toolchains + continue + if not self.IsCompatible(src.Families, self.Workspace.ActiveFamilies): + # print src.Families,"not compatible with",self.Workspace.ActiveFamilies + continue + toolcode = src.GetToolCode(src.Type) + if toolcode != "": + ext = self.Workspace.GetToolDef(self.Toolchain, self.Target, self.Arch, toolcode, "EXT") + if ext != "" and ext != src.Ext: + # print ext,"in tools_def.txt is not the same as",src.Ext + continue + ## fileFullPath = os.path.join("${MODULE_DIR}", ) + ## print fileFullPath + files[type].append(src.Path) + + return files + + def Intersection(self, list1, list2): + return list(Set(list1) & Set(list2)) + + def IsCompatible(self, list1, list2): + return len(self.Intersection(list1, list2)) > 0 + + def _GetLibList(self): + libList = [] + for lib in self.Module.Libraries: + module = lib.Module + libList.append(os.path.join("${BIN_DIR}", module.Name + ".lib")) + return libList + + def _GetSourceFileList(self): + srcList = [] + for type in self.SourceFiles: + srcList.extend(self.SourceFiles[type]) + return srcList + +class NmakeFile(BuildFile): + pass + +class GmakeFile(BuildFile): + pass + +# for test +if __name__ == "__main__": + workspacePath = os.getenv("WORKSPACE", os.getcwd()) + startTime = time.clock() + ws = Workspace(workspacePath, [], []) + + # generate build.xml + ap = ws.ActivePlatform + for target in ws.ActiveTargets: + ant = AntPlatformBuildFile(ws, ap, ws.ActiveToolchain, target) + ant.Generate() + + print "\n[Finished in %fs]" % (time.clock() - startTime) diff --git a/Tools/Python/buildgen/FrameworkElement.py b/Tools/Python/buildgen/FrameworkElement.py new file mode 100644 index 0000000000..6fd8740789 --- /dev/null +++ b/Tools/Python/buildgen/FrameworkElement.py @@ -0,0 +1,523 @@ +#!/usr/bin/env python + +# Copyright (c) 2007, Intel Corporation +# All rights reserved. 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. + +"""Framework Element Classes + +TODO +""" + +################################################################################ +## +## Element class: base class for representing framework elements +## +################################################################################ +class Element: + def __init__(self, **kwargs): + """(Name, GuidValue, Version, Path, Dir, Archs, Usage, Features, Signature)""" + ## The path and directory where the information of the element comes from + self.Path = "." + self.Dir = "." + + ## Element name, guid and version + self.Name = "" + self.GuidValue = "" + self.Version = "" + + ## The element supported architecture + self.Archs = [] + + ## Indiciate how the element is used + self.Usage = "ALWAYS_CONSUMED" + + ## Indicate what kind of features this element is bound + self.Features = [] + + ## Element signature, used to check the its integerity + self.Signature = 0 + + def __str__(self): + return self.Name + "-" + self.Version + " " + " [" + self.GuidValue + "]" + + def __eq__(self, other): + if not isinstance(other, Element): + return False + + if self.GuidValue != other.GuidValue: + return False + + if self.Version != other.Version: + return False + + return True + + def __hash__(self): + return hash(self.GuidValue + self.Version) + +################################################################################ +## +## ToolOption: build tool option +## +################################################################################ +class ToolOption(Element): + + def __init__(self, **kwargs): + """Prefix, Value, Tool, Toolchains, Families, Targets""" + Element.__init__(self) + + self.Prefix = "/" + self.Value = "" + self.Tool = "" + self.Toolchains = "" + self.Families = "MSFT" + self.Targets = "DEBUG" + +################################################################################ +## +## BuildTool: build tool +## +################################################################################ +class BuildTool(Element): + def __init__(self, **kwargs): + """Options, Toolchains, Families, Targets""" + Element.__init__(self) + + self.Options = [] + self.Toolchains = [] + self.Families = [] + self.Targets = [] + +################################################################################ +## +## SourceFile: files in a module for build +## +################################################################################ +class SourceFile(Element): + def __init__(self, **kwargs): + """BaseName, Ext, Type, Toolchains, Families, Targets""" + Element.__init__(self) + + self.BaseName = "" + self.Ext = "" + self.Type = "" + self.Toolchains = [] + self.Families = [] + self.Targets = [] + +################################################################################ +## +## IncludeFile: header file +## +################################################################################ +class IncludeFile(SourceFile): + def __init__(self, **kwargs): + """Type, Package, ModuleType""" + SourceFile.__init__(self) + + self.Type = "HeaderFile" + self.Package = "" + self.ModuleType = "" + +################################################################################ +## +## IncludePath: +## +################################################################################ +class IncludePath(IncludeFile): + pass + +################################################################################ +## +## LibraryInterface: library class interface +## +################################################################################ +class LibraryInterface(Element): + def __init__(self, **kwargs): + """Package, FavoriteInstance, Instances, ModuleTypes, Consumers""" + Element.__init__(self) + + self.Package = "" + self.FavoriteInstance = "" + self.Instances = [] + self.ModuleTypes = [] + self.Consumers = [] + + def __eq__(self, other): + if not isinstance(other, LibraryInterface): + return False + return self.Name == other.Name + + def __hash__(self): + return hash(self.Name) + +################################################################################ +## +## LibraryClass: library class +## +################################################################################ +class LibraryClass(Element): + def __init__(self, **kwargs): + """ + () + """ + Element.__init__(self) + + self.Interface = "" + self.FavoriteInstance = "" + + def __eq__(self, other): + if not isinstance(other, LibraryClass): + return False + return self.Name == other.Name + + def __hash__(self): + return hash(self.Name) + +################################################################################ +## +## Guid: +## +################################################################################ +class Guid(Element): + def __init__(self, **kwargs): + """CName, Types, ModuleTypes""" + Element.__init__(self) + + self.CName = "" + self.Types = [] + self.ModuleTypes= [] + +################################################################################ +## +## Protocol: +## +################################################################################ +class Protocol(Guid): + pass + +################################################################################ +## +## ProtocolNotify: +## +################################################################################ +class ProtocolNotify(Protocol): + pass + +################################################################################ +## +## Ppi: +## +################################################################################ +class Ppi(Guid): + pass + +################################################################################ +## +## PpiNotify: +## +################################################################################ +class PpiNotify(Ppi): + pass + +################################################################################ +## +## Extern: +## +################################################################################ +class Extern(Element): + def __init__(self, **kwargs): + """Specifications, ModuleEntryPoints, ModuleUnloadImages, Constructors, Destructors, DriverBindings, ComponentNames, DriverConfigs, DriverDiags, SetVirtualAddressMapCallBacks, ExitBootServicesCallBacks""" + Element.__init__(self) + + self.Specifications = [] + self.ModuleEntryPoints = [] + self.ModuleUnloadImages = [] + self.Constructors = [] + self.Destructors = [] + self.DriverBindings = [] + self.ComponentNames = [] + self.DriverConfigs = [] + self.DriverDiags = [] + self.SetVirtualAddressMapCallBacks = [] + self.ExitBootServicesCallBacks = [] + +################################################################################ +## +## Sku: +## +################################################################################ +class Sku(Element): + def __init__(self, **kwargs): + """Id, Value""" + Element.__init__(self) + + self.Id = 0 + self.Value = "" + +################################################################################ +## +## Pcd: +## +################################################################################ +class Pcd(Element): + def __init__(self, **kwargs): + """Types, CName, Value, Token, TokenSpace, DatumType, Sku, ModuleTypes""" + Element.__init__(self) + + self.Types = [] + self.CName = "" + self.Value = "" + self.Token = "" + self.TokenSpace = "" + self.DatumType = "" + self.Default = "" + self.Sku = "" + self.ModuleTypes= [] + +################################################################################ +## +## Module: framework module +## +################################################################################ +class Module(Element): + def __init__(self, **kwargs): + """Workspace, Package, Type, BaseName, FileBaseName, IsLibrary, PcdIsDriver, + NeedsFlashMap_h, SourceFiles, IncludePaths, IncludeFiles, NonProcessedFiles, + LibraryClasses, Guids, Protocols, Ppis, Externs, Pcds, + UserExtensions, BuildOptions, Environment + """ + Element.__init__(self) + + self.Workspace = "" + self.Package = "" + self.Type = "" + self.BaseName = "" + self.FileBaseName = "" + self.IsLibrary = False + self.IsBinary = False + self.PcdIsDriver = False + self.NeedsFlashMap_h = False + self.SourceFiles = {} # arch -> {file type -> [source file list]} + self.IncludePaths = {} # arch -> [path list] + self.IncludeFiles = {} + + self.NonProcessedFiles = [] + self.LibraryClasses = {} # arch -> [library class list] + + self.Guids = {} # arch -> [guid object list] + self.Protocols = {} # arch -> [] + self.Ppis = {} # arch -> [] + + self.Externs = {} # arch -> [] + self.Pcds = {} # arch -> [] + + self.UserExtensions = {} # identifier -> ... + self.BuildOptions = {} # (toolchain, target, arch, toolcode, "FLAGS") -> flag + self.Environment = {} + + def __eq__(self, other): + if not isinstance(other, Module): + return False + + if self.GuidValue != other.GuidValue: + return False + + if self.Version != other.Version: + return False + + if self.Package != other.Package: + return False + + return True + + def __hash__(self): + return hash(self.GuidValue + self.Version + hash(self.Package)) + +################################################################################ +## +## PlatformModule: module for build +## +################################################################################ +class PlatformModule(Element): + def __init__(self, **kwargs): + """Workspace, Platform, Module, Libraries, Pcds, FfsLayouts, FvBindings + BuildOptions, BuildType, BuildFile, BuildPath, Sections, FfsFile, Environment + """ + Element.__init__(self) + self.Workspace = "" + self.Platform = "" + self.Module = "" + self.Libraries = [] + self.Pcds = [] + self.FfsLayouts = [] + self.FvBindings = [] + self.BuildOptions = {} + + self.BuildType = "efi" ## efi or lib + self.BuildFile = "build.xml" + self.BuildPath = "${MODULE_BUILD_DIR}" + self.Sections = [] + self.FfsFile = "" + + self.Environment = {} # name/value pairs + + def __eq__(self, other): + if not isinstance(other, PlatformModule): + if not isinstance(other, Module): + return False + elif self.Module != other: + return False + elif self.Module != other.Module: + return False + + return True + + def __hash__(self): + return hash(self.Module) + +################################################################################ +## +## Package: framework package +## +################################################################################ +class Package(Element): + def __init__(self, **kwargs): + """Workspace, ReadOnly, Repackage, Modules, PackageIncludes, StandardIncludes, + LibraryInterfaces, Guids, Protocols, Ppis, Pcds, Environment + """ + Element.__init__(self) + + self.Workspace = "" + self.ReadOnly = True + self.Repackage = True + self.Modules = [] + self.PackageIncludes = {} # module type -> [include file list] + self.StandardIncludes = [] + self.LibraryInterfaces = {} # class name -> include file + self.Guids = {} # cname -> guid object + self.Protocols = {} # cname -> protocol object + self.Ppis = {} # cname -> ppi object + self.Pcds = {} # token -> pcd object + + self.Environment = {} + +################################################################################ +## +## PackageDependency: +## +################################################################################ +class PackageDependency(Element): + def __init__(self, **kwargs): + """Package""" + Element.__init__(self) + + self.Package = "" + +################################################################################ +## +## Platform: +## +################################################################################ +class Platform(Element): + def __init__(self, **kwargs): + """Targets, OutputPath, Images, Modules, DynamicPcds, Fvs, Libraries + BuildFile, BuildPath, BuildOptions, UserExtensions + """ + Element.__init__(self) + + self.Targets = [] + self.OutputPath = "" + self.Images = [] + self.Modules = {} # arch -> [module list] + self.DynamicPcds = [] + self.FfsLayouts = {} + self.Fvs = {} + + self.Libraries = {} # arch -> [library instance] + self.BuildFile = "build.xml" + self.BuildPath = "${PLATFORM_BUILD_DIR}" + self.BuildOptions = {} + self.UserExtensions = {} + + self.Environment = {} # name/value pairs + +################################################################################ +## +## Workspace: +## +################################################################################ +class Workspace(Element): + def __init__(self, **kwargs): + """Packages, Platforms, Fars, Modules, PlatformIndex, PackageIndex""" + Element.__init__(self) + + self.Packages = [] + self.Platforms = [] + self.Fars = [] + self.Modules = [] + + ## "GUID" : {guid : {version : platform}} + ## "PATH" : {path : platform} + ## "NAME" : {name : [platform]} + self.PlatformXref = { + "GUID" : {}, + "PATH" : {}, + "NAME" : {}, + } + ## "GUID" : {guid : {version : package}} + ## "PATH" : {path : package} + ## "NAME" : {name : package} + self.PackageXref = { + "GUID" : {}, + "PATH" : {}, + "NAME" : {}, + } + ## "GUID" : {guid : {version : [module]}} + ## "PATH" : {path : module} + ## "NAME" : {name : module} + self.ModuleXref = { + "GUID" : {}, + "PATH" : {}, + "NAME" : {}, + } + ## "NAME" : {name : library interface} + ## "PATH" : {path : library interface} + self.LibraryInterfaceXref = { + "PATH" : {}, + "NAME" : {}, + } + ## TODO + self.FarIndex = {} + + # from target.txt + self.TargetConfig = {} + # from tools_def.txt + self.ToolConfig = {} + + self.ActivePlatform = "" + self.ActiveToolchain = "" + self.ActiveFamilies = [] + self.ActiveModules = [] + self.ActiveTargets = [] + self.ActiveArchs = [] + + self.IndividualModuleBuild = False + self.MultiThreadBuild = False + self.ThreadCount = "2" + + self.Environment = {} + +################################################################################ +## +## For test: +## +################################################################################ +if __name__ == "__main__": + pass diff --git a/Tools/Python/buildgen/SurfaceAreaElement.py b/Tools/Python/buildgen/SurfaceAreaElement.py new file mode 100644 index 0000000000..29aaa8398e --- /dev/null +++ b/Tools/Python/buildgen/SurfaceAreaElement.py @@ -0,0 +1,1549 @@ +#!/usr/bin/env python + +# Copyright (c) 2007, Intel Corporation +# All rights reserved. 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. + +"""Framework SurfaceArea Elemments""" +# +# TODO: FFS layout, Flash, FV, PCD +# +import os, sys, re, getopt, string, glob, xml.dom.minidom, pprint, time, copy, shelve +from XmlRoutines import * +import FrameworkElement +import BuildConfig + +################################################################################ +## +## Convert given list to a string in the format like: [a, b, c] +## +################################################################################ +def ListString(lst): + return "[%s]" % ",".join(lst) + +class SurfaceAreaElement: + """Base class for Surface Area XML element""" + _ModuleTypes = ('BASE', 'SEC', 'PEI_CORE', 'PEIM', 'DXE_CORE', 'DXE_DRIVER', + 'DXE_RUNTIME_DRIVER', 'DXE_SAL_DRIVER', 'DXE_SMM_DRIVER', + 'TOOL', 'UEFI_DRIVER', 'UEFI_APPLICATION', 'USER_DEFINED') + _GuidTypes = ('DATA_HUB_RECORD', 'EFI_EVENT', 'EFI_SYSTEM_CONFIGURATION_TABLE', + 'EFI_VARIABLE', 'GUID', 'HII_PACKAGE_LIST', 'HOB', 'TOKEN_SPACE_GUID') + _Archs = ('EBC', 'IA32', 'X64', 'IPF', 'ARM', 'PPC') + _Usages = ('ALWAYS_CONSUMED', 'SOMETIMES_CONSUMED', 'ALWAYS_PRODUCED', + 'SOMETIMES_PRODUCED', 'TO_START', 'BY_START', 'PRIVATE') + _FileTypes = { + ".c" : "CCode", + ".C" : "CCode", + ".cpp" : "CCode", + ".Cpp" : "CCode", + ".CPP" : "CCode", + ".h" : "CHeader", + ".H" : "CHeader", + ".asm" : "ASM", + ".Asm" : "Assembly", + ".ASM" : "Assembly", + ".s" : "IpfAssembly", + ".S" : "GccAssembly", + ".uni" : "UNI", + ".Uni" : "Unicode", + ".UNI" : "Unicode", + ".vfr" : "VFR", + ".Vfr" : "VFR", + ".VFR" : "VFR", + ".dxs" : "DPX", + ".Dxs" : "DPX", + ".DXS" : "DPX", + ".fv" : "FirmwareVolume", + ".Fv" : "FirmwareVolume", + ".FV" : "FirmwareVolume", + ".efi" : "EFI", + ".Efi" : "EFI", + ".EFI" : "EFI", + ".SEC" : "FFS", + ".PEI" : "FFS", + ".DXE" : "FFS", + ".APP" : "FFS", + ".FYI" : "FFS", + ".FFS" : "FFS", + ".bmp" : "BMP", + ".i" : "PPCode", + ".asl" : "ASL", + ".Asl" : "ASL", + ".ASL" : "ASL", + } + _ToolMapping = { + "CCode" : "CC", + "CHeader" : "", + "ASM" : "ASM", + "Assembly" : "ASM", + "IpfAssembly" : "ASM", + "GccAssembly" : "ASM", + "UNI" : "", + "Unicode" : "", + "VFR" : "", + "DPX" : "", + "FirmwareVolume" : "", + "EFI" : "", + "FFS" : "", + "PPCode" : "PP", + "BMP" : "", + } + + _BuildableFileTypes = ("CCode", "ASM", "Assembly", "IpfAssembly", "GccAssembly", "UNI", "Unicode", "VFR", "DPX", "EFI") + + def __init__(self, workspace, owner=None, dom=None, parse=True, postprocess=True): + self._Workspace = workspace + + if owner == None: self._Owner = "" + else: self._Owner = owner + + if dom == None: self._Root = "" + else: self._Root = dom + + self._Elements = {} + + if parse: self.Parse() + if postprocess: self.Postprocess() + + def Parse(self): + """Parse the XML element in DOM form""" + pass + + def Postprocess(self): + """Re-organize the original information form XML DOM into a format which can be used directly""" + pass + + def GetArchList(self, dom): + """Parse the SupArchList attribute. If not spcified, return all ARCH supported""" + archs = XmlAttribute(dom, "SupArchList").split() + if archs == []: + if self._Owner.Archs != []: + archs = self._Owner.Archs + elif self._Workspace.ActiveArchs != []: + archs = self._Workspace.ActiveArchs + elif self._Workspace.ActivePlatform != "" and self._Workspace.ActivePlatform.Archs != []: + archs = self._Workspace.ActivePlatform.Archs + else: + archs = self._Archs + return archs + + def GetModuleTypeList(self, dom): + """Parse the SupModuleList attribute. If not specified, return all supported module types""" + moduleTypes = XmlAttribute(dom, "SupModuleList").split() + if moduleTypes == []: + moduleTypes = self._ModuleTypes + return moduleTypes + + def GetGuidTypeList(self, dom): + """Parse GuidTypeList attribute. Default to GUID if not specified""" + guidTypes = XmlAttribute(dom, "GuidTypeList") + if guidTypes == []: + guidTypes = ["GUID"] + return guidTypes + + def GetFeatureList(self, dom): + """Parse FeatureFlag attribute""" + return XmlAttribute(dom, "FeatureFlag").split() + + def GetToolchainTagList(self, dom): + """Parse TagName attribute. Return all defined toolchains defined in tools_def.txt if not given""" + toolchainTagString = XmlAttribute(dom, "TagName") + if toolchainTagString == "": + return self._Workspace.ToolConfig.Toolchains + return toolchainTagString.split() + + def GetToolchainFamilyList(self, dom): + """Parse ToolChainFamily attribute. Return all defined toolchain families in tools_def.txt if not given""" + familyString = XmlAttribute(dom, "ToolChainFamily") + if familyString != "": + return familyString.split() + return self._Workspace.ToolConfig.Families + + def GetTargetList(self, dom): + """Parse BuildTargets attribute. Return all build targets defined in tools_def.txt if not given""" + targetList = XmlAttribute(dom, "BuildTargets").split() + if targetList == []: + targetList = self._Workspace.ToolConfig.Targets + return targetList + + def GetUsage(self, dom): + """Parse Usage attribute. Default to ALWAYS_CONSUMED if not given""" + usageString = XmlAttribute(dom, "Usage") + if usageString == "": + return "ALWAYS_CONSUMED" + return usageString + + def GetBuildOptionList(self, dom): + """Parse Options/Option element. Return a options dictionay with keys as (toolchain, target, arch, toolcode, attr)""" + optionList = XmlList(dom, "/Options/Option") + buildOptions = {} + for option in optionList: + targets = self.GetTargetList(option) + toolchainFamilies = self.GetToolchainFamilyList(option) + toolchainTags = self.GetToolchainTagList(option) + toolcode = XmlAttribute(option, "ToolCode") + archs = self.GetArchList(option) + flag = XmlElementData(option) + # print flag + + toolchains = [] + if toolchainTags != []: + toolchains = toolchainTags + elif toolchainFamilies != []: + toolchains = toolchainFamilies + else: + raise Exception("No toolchain specified for a build option: " + self._Owner.Name) + + if targets == []: targets = self._Workspace.ActiveTargets + if archs == []: archs = self._Workspace.ActiveArchs + + for toolchain in toolchains: + for target in targets: + for arch in archs: + buildOptions[(toolchain, target, arch, toolcode, "FLAGS")] = flag + return buildOptions + + def GetFvBindingList(self, dom): + """Parse FvBinding element. If not specified, return NULL FV""" + fvBindingList = XmlElementData(dom).split() + if fvBindingList == []: + fvBindingList = ["NULL"] + return fvBindingList + + def IsBuildable(self, type): + """Test if a file with the type can be built by a tool""" + return type in self._BuildableFileTypes + + def GetToolCode(self, type): + """Get the toolcode which must be used to build files with the type""" + toolcode = "" + if type in self._ToolMapping: + toolcode = self._ToolMapping[type] + return toolcode + + def GetBoolean(self, dom): + """Transate true/false in string form to python's True/False value""" + boolString = XmlElementData(dom).upper() + if boolString == "" or boolString == "FALSE" or boolString == "NO": + return False + else: + return True + +class LibraryDeclaration(FrameworkElement.LibraryInterface, SurfaceAreaElement): + def __init__(self, workspace, package, dom): + FrameworkElement.LibraryInterface.__init__(self) + self.Package = package + SurfaceAreaElement.__init__(self, workspace, package, dom) + + def Parse(self): + dom = self._Root + self.Name = XmlAttribute(dom, "Name") + self.Path = os.path.normpath(XmlElementData(XmlElement(dom, "/LibraryClass/IncludeHeader"))) + self.Dir = os.path.dirname(self.Path) + + attribute = XmlAttribute(dom, "RecommendedInstanceGuid") + if attribute is not '': + self.FavoriteIntance = FrameworkElement.Module() + self.FavoriteIntance.Guid = attribute + + attribute = XmlAttribute(dom, "RecommendedInstanceVersion") + if attribute is not '': + if self.FavoriteIntance == "": + raise "No GUID for the recommened library instance" + self.FavoriteIntance.Version = attribute + + self.Archs = self.GetArchList(dom) + self.ModuleTypes = self.GetModuleTypeList(dom) + +class LibraryClass(FrameworkElement.LibraryClass, SurfaceAreaElement): + def __init__(self, workspace, module, dom): + FrameworkElement.LibraryClass.__init__(self) + SurfaceAreaElement.__init__(self, workspace, module, dom) + + def Parse(self): + dom = self._Root + + self.Name = XmlElementData(XmlElement(dom, "/LibraryClass/Keyword")) + self.Usage = self.GetUsage(dom) + self.Features = self.GetFeatureList(dom) + self.Archs = self.GetArchList(dom) + + attribute = XmlAttribute(dom, "RecommendedInstanceGuid") + if attribute is not '': + self.FavoriteIntance = FrameworkElement.Module() + self.FavoriteIntance.Guid = attribute + + attribute = XmlAttribute(dom, "RecommendedInstanceVersion") + if attribute is not '': + if self.FavoriteIntance == "": + self.FavoriteIntance = FrameworkElement.Module() + self.FavoriteIntance.Version = attribute + + def Postprocess(self): + self.Interface = self._Workspace.GetLibraryInterface(self.Name) + +class SourceFile(FrameworkElement.SourceFile, SurfaceAreaElement): + def __init__(self, workspace, module, dom): + FrameworkElement.SourceFile.__init__(self) + SurfaceAreaElement.__init__(self, workspace, module, dom) + + def Parse(self): + dom = self._Root + self.Path = os.path.normpath(XmlElementData(dom)) + self.Dir = os.path.dirname(self.Path) + self.Type = self.GetFileType() + self.Toolchains = self.GetToolchainTagList(dom) + self.Families = self.GetToolchainFamilyList(dom) + self.Archs = self.GetArchList(dom) + self.Features = self.GetFeatureList(dom) + + def GetFileType(self): + type = XmlAttribute(self._Root, "ToolCode") + if type == "": + fileName = os.path.basename(self.Path) + self.BaseName,self.Ext = os.path.splitext(fileName) + if self.Ext in self._FileTypes: + type = self._FileTypes[self.Ext] + else: + type = "" + return type + +class PackageDependency(FrameworkElement.PackageDependency, SurfaceAreaElement): + def __init__(self, workspace, module, dom): + FrameworkElement.PackageDependency.__init__(self) + SurfaceAreaElement.__init__(self, workspace, module, dom) + + def Parse(self): + dom = self._Root + self.GuidValue = XmlAttribute(dom, "PackageGuid").upper() + self.Version = XmlAttribute(dom, "PackageVersion") + self.Archs = self.GetArchList(dom) + self.Features = self.GetFeatureList(dom) + + def Postprocess(self): + self.Package = self._Workspace.GetPackage(self.GuidValue, self.Version) + if self.Package == "": raise "No package with GUID=" + self.GuidValue + "VERSION=" + self.Version + +class Protocol(FrameworkElement.Protocol, SurfaceAreaElement): + def __init__(self, workspace, module, dom): + FrameworkElement.Protocol.__init__(self) + SurfaceAreaElement.__init__(self, workspace, module, dom) + + def Parse(self): + dom = self._Root + self.CName = XmlElementData(XmlElement(dom, "/Protocol/ProtocolCName")) + self.Usage = self.GetUsage(dom) + self.Archs = self.GetArchList(dom) + self.Features = self.GetFeatureList(dom) + + def Postprocess(self): + for pd in self._Owner._Elements["PackageDependencies"]: + if self.CName not in pd.Package.Protocols: continue + self.GuidValue = pd.Package.Protocols[self.CName] + +class ProtocolNotify(FrameworkElement.ProtocolNotify, SurfaceAreaElement): + def __init__(self, workspace, module, dom): + FrameworkElement.ProtocolNotify.__init__(self) + SurfaceAreaElement.__init__(self, workspace, module, dom) + + def Parse(self): + dom = self._Root + + self.CName = XmlElementData(XmlElement(dom, "/ProtocolNotify/ProtocolCName")) + self.Usage = self.GetUsage(dom) + self.Archs = self.GetArchList(dom) + self.Features = self.GetFeatureList(dom) + + def Postprocess(self): + for pd in self._Owner._Elements["PackageDependencies"]: + if self.CName not in pd.Package.Protocols: continue + self.GuidValue = pd.Package.Protocols[self.CName] + +class Ppi(FrameworkElement.Ppi, SurfaceAreaElement): + def __init__(self, workspace, module, dom): + FrameworkElement.Ppi.__init__(self) + SurfaceAreaElement.__init__(self, workspace, module, dom) + + def Parse(self): + dom = self._Root + self.CName = XmlElementData(XmlElement(dom, "/Ppi/PpiCName")) + self.Usage = self.GetUsage(dom) + self.Archs = self.GetArchList(dom) + self.Features = self.GetFeatureList(dom) + + def Postprocess(self): + for pd in self._Owner._Elements["PackageDependencies"]: + if self.CName not in pd.Package.Ppis: continue + self.GuidValue = pd.Package.Ppis[self.CName] + +class PpiNotify(FrameworkElement.PpiNotify, SurfaceAreaElement): + def __init__(self, workspace, module, dom): + FrameworkElement.PpiNotify.__init__(self) + SurfaceAreaElement.__init__(self, workspace, module, dom) + + def Parse(self): + dom = self._Root + self.CName = XmlElementData(XmlElement(dom, "/PpiNotify/PpiCName")) + self.Usage = self.GetUsage(dom) + self.Archs = self.GetArchList(dom) + self.Features = self.GetFeatureList(dom) + + def Postprocess(self): + for pd in self._Owner._Elements["PackageDependencies"]: + if self.CName not in pd.Package.Ppis: continue + self.GuidValue = pd.Package.Ppis[self.CName] + +class Guid(FrameworkElement.Guid, SurfaceAreaElement): + def __init__(self, workspace, module, dom): + FrameworkElement.Guid.__init__(self) + SurfaceAreaElement.__init__(self, workspace, module, dom) + + def Parse(self): + dom = self._Root + self.CName = XmlElementData(XmlElement(dom, "/GuidCNames/GuidCName")) + self.Usage = self.GetUsage(dom) + self.Archs = self.GetArchList(dom) + self.Features = self.GetFeatureList(dom) + + def Postprocess(self): + for pd in self._Owner._Elements["PackageDependencies"]: + if self.CName not in pd.Package.Guids: continue + self.GuidValue = pd.Package.Guids[self.CName] + +class Extern(FrameworkElement.Extern, SurfaceAreaElement): + def __init__(self, workspace, module, dom): + FrameworkElement.Extern.__init__(self) + SurfaceAreaElement.__init__(self, workspace, module, dom) + + def Parse(self): + dom = self._Root + self.Archs = self.GetArchList(dom) + self.Features = self.GetFeatureList(dom) + + extern = XmlElement(dom, "/Extern/ModuleEntryPoint") + if extern is not None and extern is not '': + self.ModuleEntryPoints.append(XmlElementData(extern)) + + extern = XmlElement(dom, "/Extern/ModuleUnloadImage") + if extern is not None and extern is not '': + self.ModuleUnloadImages.append(XmlElementData(extern)) + + extern = XmlElement(dom, "/Extern/Constructor") + if extern is not None and extern is not '': + self.Constructors.append(XmlElementData(extern)) + + extern = XmlElement(dom, "/Extern/Destructor") + if extern is not None and extern is not '': + self.Destructors.append(XmlElementData(extern)) + + extern = XmlElement(dom, "/Extern/DriverBinding") + if extern is not None and extern is not '': + self.DriverBindings.append(XmlElementData(extern)) + + extern = XmlElement(dom, "/Extern/ComponentName") + if extern is not None and extern is not '': + self.ComponentNames.append(XmlElementData(extern)) + + extern = XmlElement(dom, "/Extern/DriverConfig") + if extern is not None and extern is not '': + self.DriverConfigs.append(XmlElementData(extern)) + + extern = XmlElement(dom, "/Extern/DriverDiag") + if extern is not None and extern is not '': + self.DriverDiags.append(XmlElementData(extern)) + + extern = XmlElement(dom, "/Extern/SetVirtualAddressMapCallBacks") + if extern is not None and extern is not '': + self.SetVirtualAddressMapCallBacks.append(XmlElementData(extern)) + + extern = XmlElement(dom, "/Extern/ExitBootServicesCallBack") + if extern is not None and extern is not '': + self.ExitBootServicesCallBacks.append(XmlElementData(extern)) + +class IndustryStdHeader(FrameworkElement.IncludeFile, SurfaceAreaElement): + def __init__(self, workspace, package, dom): + FrameworkElement.IncludeFile.__init__(self) + SurfaceAreaElement.__init__(self, workspace, package, dom) + + def Parse(self): + dom = self._Root + self.Path = os.path.normpath(XmlElementData(XmlElement(dom, "/IndustryStdHeader/IncludeHeader"))) + self.Dir = os.path.dirname(self.Path) + self.Archs = self.GetArchList(dom) + self.ModuleTypes = self.GetModuleTypeList(dom) + +class PackageHeader(FrameworkElement.IncludeFile, SurfaceAreaElement): + def __init__(self, workspace, package, dom): + FrameworkElement.IncludeFile.__init__(self) + SurfaceAreaElement.__init__(self, workspace, package, dom) + + def Parse(self): + dom = self._Root + self.Path = os.path.normpath(XmlElementData(dom)) + self.Dir = os.path.dirname(self.Path) + self.ModuleType = XmlAttribute(dom, "ModuleType") + +class GuidDeclaration(FrameworkElement.Guid, SurfaceAreaElement): + def __init__(self, workspace, package, dom): + FrameworkElement.Guid.__init__(self) + SurfaceAreaElement.__init__(self, workspace, package, dom) + + def Parse(self): + dom = self._Root + self.CName = XmlElementData(XmlElement(dom, "/Entry/C_Name")) + self.GuidValue = XmlElementData(XmlElement(dom, "/Entry/GuidValue")).upper() + self.Name = XmlAttribute(dom, "Name") + self.Types = self.GetGuidTypeList(dom) + self.Archs = self.GetArchList(dom) + self.ModuleTypes = self.GetModuleTypeList(dom) + + def Postprocess(self): + pass + +class ProtocolDeclaration(GuidDeclaration, SurfaceAreaElement): + pass + +class PpiDeclaration(GuidDeclaration, SurfaceAreaElement): + pass + +class PcdDeclaration(FrameworkElement.Pcd, SurfaceAreaElement): + def __init__(self, workspace, package, dom): + FrameworkElement.Pcd.__init__(self) + SurfaceAreaElement.__init__(self, workspace, package, dom) + + def Parse(self): + dom = self._Root + self.Types = XmlElementData(XmlElement(dom, "/PcdEntry/ValidUsage")).split() + self.CName = XmlElementData(XmlElement(dom, "/PcdEntry/C_Name")) + self.Token = XmlElementData(XmlElement(dom, "/PcdEntry/Token")) + self.TokenSpace = XmlElementData(XmlElement(dom, "/PcdEntry/TokenSpaceGuidCName")) + self.DatumType = XmlElementData(XmlElement(dom, "/PcdEntry/DatumType")) + self.Default = XmlElementData(XmlElement(dom, "/PcdEntry/DefaultValue")) + self.Archs = self.GetArchList(dom) + self.ModuleTypes= self.GetModuleTypeList(dom) + +class LibraryInstance(FrameworkElement.PlatformModule, SurfaceAreaElement): + def __init__(self, workspace, platformModule, dom): + FrameworkElement.PlatformModule.__init__(self) + SurfaceAreaElement.__init__(self, workspace, platformModule, dom) + + def Parse(self): + dom = self._Root + self.GuidValue = XmlAttribute(dom, "ModuleGuid").upper() + self.Version = XmlAttribute(dom, "ModuleVersion") + self._Elements["PackageGuid"] = XmlAttribute(dom, "PackageGuid").upper() + self._Elements["PackageVersion"] = XmlAttribute(dom, "PackageVersion") + + def Postprocess(self): + self.Module = self._Workspace.GetModule(self.GuidValue, self.Version, + self._Elements["PackageGuid"], self._Elements["PackageVersion"]) + self.Platform = self._Owner.Platform + self.Archs = self._Owner.Archs + self.Pcds = self._Owner.Pcds + self.BuildType = "lib" + +class PlatformModule(FrameworkElement.PlatformModule, SurfaceAreaElement): + def __init__(self, workspace, platform, dom): + FrameworkElement.PlatformModule.__init__(self) + self.Platform = platform + SurfaceAreaElement.__init__(self, workspace, platform, dom) + + def Parse(self): + dom = self._Root + self.GuidValue = XmlAttribute(dom, "ModuleGuid").upper() + self.Version = XmlAttribute(dom, "ModuleVersion") + self.Archs = self.GetArchList(dom) + + self._Elements["PackageGuid"] = XmlAttribute(dom, "PackageGuid").upper() + self._Elements["PackageVersion"] = XmlAttribute(dom, "PackageVersion") + + libraryList = XmlList(dom, "/ModuleSA/Libraries/Instance") + for lib in libraryList: + self.Libraries.append(LibraryInstance(self._Workspace, self, lib)) + + dom = XmlElement(dom, "/ModuleSA/ModuleSaBuildOptions") + self.FvBindings = self.GetFvBindingList(XmlElement(dom, "/ModuleSaBuildOptions/FvBinding")) + self.FfsLayouts = XmlElementData(XmlElement(dom, "/ModuleSaBuildOptions/FfsFormatKey")).split() + self.BuildOptions = self.GetBuildOptionList(XmlElement(dom, "/ModuleSaBuildOptions/Options")) + + def Postprocess(self): + self.Module = self._Workspace.GetModule(self.GuidValue, self.Version, + self._Elements["PackageGuid"], self._Elements["PackageVersion"]) + if self.Module == "": + raise Exception("No module found: \n\t\tGUID=%s \n\t\tVERSION=%s \n\t\tPACKAGE_GUID=%s \n\t\tPACKAGE_VERSION=%s" % ( + self.GuidValue, self.Version, self._Elements["PackageGuid"], self._Elements["PackageVersion"])) + +## def SetupEnvironment(self): +## self.Environment = { +## "ARCH" : "", +## "MODULE_BUILD_TARGET" : "", +## "SINGLE_MODULE_BUILD" : "", +## "PLATFORM_PREBUILD" : "", +## "PLATFORM_POSTBUILD" : "", +## "LIBS" : "", +## "SOURCE_FILES" : "", +## "ENTRYPOINT" : "_ModuleEntryPoint", +## } # name/value pairs +## self.Environment["MODULE_BUILD_TARGET"] = "platform_module_build" + +class ModuleSurfaceArea(FrameworkElement.Module, SurfaceAreaElement): + def __init__(self, workspace, package, path): + FrameworkElement.Module.__init__(self) + + self.Path = os.path.normpath(path) + self.Dir = os.path.dirname(self.Path) + self.FileBaseName,_ext = os.path.splitext(os.path.basename(self.Path)) + self.Package = package + SurfaceAreaElement.__init__(self, workspace, package) + + def _MsaHeader(self, xpath): + dom = XmlElement(self._Root, xpath) + if dom == '': return + self.Name = XmlElementData(XmlElement(dom, "/MsaHeader/ModuleName")) + self.Type = XmlElementData(XmlElement(dom, "/MsaHeader/ModuleType")) + self.GuidValue = XmlElementData(XmlElement(dom, "/MsaHeader/GuidValue")).upper() + self.Version = XmlElementData(XmlElement(dom, "/MsaHeader/Version")) + + def _ModuleDefinitions(self, xpath): + dom = XmlElement(self._Root, xpath) + if dom == '': return + self.Archs = XmlElementData(XmlElement(dom, "/ModuleDefinitions/SupportedArchitectures")).split() + self.IsBinary = self.GetBoolean(XmlElement(dom, "/ModuleDefinitions/BinaryModule")) + self.BaseName = XmlElementData(XmlElement(dom, "/ModuleDefinitions/OutputFileBasename")) + + def _LibraryClassDefinitions(self, xpath): + dom = XmlElement(self._Root, xpath) + if dom == '': return + lcList = [] + for lc in XmlList(dom, "/LibraryClassDefinitions/LibraryClass"): + lcList.append(LibraryClass(self._Workspace, self, lc)) + self._Elements["LibraryClassDefinitions"] = lcList + + def _SourceFiles(self, xpath): + dom = XmlElement(self._Root, xpath) + if dom == '': return + srcList = [] + for f in XmlList(dom, "/SourceFiles/Filename"): + srcList.append(SourceFile(self._Workspace, self, f)) + self._Elements["SourceFiles"] = srcList + + def _NonProcessedFiles(self, xpath): + dom = XmlElement(self._Root, xpath) + if dom == '': return + for f in XmlList(dom, "/NonProcessedFiles/Filename"): + self.NonProcessedFiles.append(SourceFile(self._Workspace, self, f)) + + def _PackageDependencies(self, xpath): + dom = XmlElement(self._Root, xpath) + if dom == '': return + pdList = [] + for pkg in XmlList(dom, "/PackageDependencies/Package"): + pdList.append(PackageDependency(self._Workspace, self, pkg)) + self._Elements["PackageDependencies"] = pdList + + def _Protocols(self, xpath): + dom = XmlElement(self._Root, xpath) + if dom == '': return + + protocolList = [] + for p in XmlList(dom, "/Protocols/Protocol"): + protocolList.append(Protocol(self._Workspace, self, p)) + for p in XmlList(dom, "/Protocols/ProtocolNotify"): + protocolList.append(ProtocolNotify(self._Workspace, self, p)) + + self._Elements["Protocols"] = protocolList + + def _Ppis(self, xpath): + dom = XmlElement(self._Root, xpath) + if dom == '': return + + ppiList = [] + for p in XmlList(dom, "/PPIs/Ppi"): + ppiList.append(Ppi(self._Workspace, self, p)) + for p in XmlList(dom, "/PPIs/PpiNotify"): + ppiList.append(PpiNotify(self._Workspace, self, p)) + + self._Elements["PPIs"] = ppiList + + def _Guids(self, xpath): + dom = XmlElement(self._Root, xpath) + if dom == '': return + guidList = [] + for g in XmlList(dom, "/Guids/GuidCNames"): + guidList.append(Guid(self._Workspace, self, g)) + self._Elements["Guids"] = guidList + + def _Externs(self, xpath): + dom = XmlElement(self._Root, xpath) + if dom == '': return + self.PcdIsDriver = self.GetBoolean(XmlElement(dom, "/Externs/PcdIsDriver")) + self.NeedsFlashMap_h = self.GetBoolean(XmlElement(dom, "/Externs/TianoR8FlashMap_h")) + + externList = [] + specs = FrameworkElement.Extern() + specs.Archs = self._Archs + externList.append(specs) + for spec in XmlList(dom, "/Externs/Specification"): + specs.Specifications.append(XmlElementData(spec)) + for ext in XmlList(dom, "/Externs/Extern"): + externList.append(Extern(self._Workspace, self, ext)) + self._Elements["Externs"] = externList + + def _ModuleBuildOptions(self, xpath): + dom = XmlElement(self._Root, xpath) + if dom == '': return + self.BuildOptions = self.GetBuildOptionList(XmlElement(dom, "/ModuleBuildOptions/Options")) + + def _UserExtensions(self, xpath): + domList = XmlList(self._Root, xpath) + if domList == []: return + for extension in domList: + userId = XmlAttribute(extension, "UserID") + identifier = XmlAttribute(extension, "Identifier") + if userId == '' or identifier == '': + raise Exception("No UserId or Identifier specified") + if userId != "TianoCore": continue + if identifier not in self.UserExtensions: + self.UserExtensions[identifier] = [] + + contentList = self.UserExtensions[identifier] + for node in extension.childNodes: + #print node.nodeType + contentList.append(node.cloneNode(True)) + + def Parse(self): + fileFullPath = self._Workspace.SubPath(os.path.dirname(self.Package.Path), self.Path) + self._Root = xml.dom.minidom.parse(fileFullPath) + assert self._Root.documentElement.tagName == "ModuleSurfaceArea" + + # print " Parsing...",self.Path + self._MsaHeader("/ModuleSurfaceArea/MsaHeader") + self._ModuleDefinitions("/ModuleSurfaceArea/ModuleDefinitions") + self._PackageDependencies("/ModuleSurfaceArea/PackageDependencies") + self._LibraryClassDefinitions("/ModuleSurfaceArea/LibraryClassDefinitions") + self._SourceFiles("/ModuleSurfaceArea/SourceFiles") + self._NonProcessedFiles("/ModuleSurfaceArea/NonProcessedFiles") + self._Protocols("/ModuleSurfaceArea/Protocols") + self._Ppis("/ModuleSurfaceArea/Ppis") + self._Guids("/ModuleSurfaceArea/Guids") + self._Externs("/ModuleSurfaceArea/Externs") + self._ModuleBuildOptions("/ModuleSurfaceArea/ModuleBuildOptions") + self._UserExtensions("/ModuleSurfaceArea/UserExtensions") + + def Postprocess(self): + # resolve package dependency + if self._Elements.has_key("PackageDependencies"): + for pd in self._Elements["PackageDependencies"]: + package = pd.Package + if self.Type not in package.PackageIncludes: + print "! Module type %s is not supported in the package %s" % (self.Type, package.Name) + + for arch in pd.Archs: + if arch not in self.IncludePaths: + self.IncludePaths[arch] = [] + self.IncludePaths[arch].append(package.SubPath("Include")) + self.IncludePaths[arch].append(package.SubPath("Include", arch.capitalize())) + + if arch not in self.IncludeFiles: + self.IncludeFiles[arch] = [] + if self.Type in package.PackageIncludes: + for path in package.PackageIncludes[self.Type]: + self.IncludeFiles[arch].append(package.SubPath(path)) + + # resolve library class + if self._Elements.has_key("LibraryClassDefinitions"): + for lc in self._Elements["LibraryClassDefinitions"]: + lc.Interface = self._Workspace.GetLibraryInterface(lc.Name) + if "ALWAYS_PRODUCED" in lc.Usage: + self.IsLibrary = True + lc.Interface.Instances.append(self) + else: + lc.Interface.Consumers.append(self) + + for arch in lc.Archs: + if arch not in self.LibraryClasses: + self.LibraryClasses[arch] = [] + self.LibraryClasses[arch].append(lc) + + # expand source files + if self._Elements.has_key("SourceFiles"): + for src in self._Elements["SourceFiles"]: + for arch in src.Archs: + if arch not in self.SourceFiles: + self.SourceFiles[arch] = {} + if src.Type not in self.SourceFiles[arch]: + self.SourceFiles[arch][src.Type] = [] + self.SourceFiles[arch][src.Type].append(src) + + # expand guids + if self._Elements.has_key("Guids"): + for guid in self._Elements["Guids"]: + for arch in guid.Archs: + if arch not in self.Guids: + self.Guids[arch] = [] + self.Guids[arch].append(guid) + + # expand protocol + if self._Elements.has_key("Protocols"): + for protocol in self._Elements["Protocols"]: + for arch in protocol.Archs: + if arch not in self.Protocols: + self.Protocols[arch] = [] + self.Protocols[arch].append(protocol) + + # expand ppi + if self._Elements.has_key("PPIs"): + for ppi in self._Elements["PPIs"]: + for arch in ppi.Archs: + if arch not in self.Ppis: + self.Ppis[arch] = [] + self.Ppis[arch].append(ppi) + + # expand extern + if self._Elements.has_key("Externs"): + for extern in self._Elements["Externs"]: + for arch in extern.Archs: + if arch not in self.Externs: + self.Externs[arch] = [] + self.Externs[arch].append(extern) +## def SetupEnvironment(self): +## self.Environment["MODULE"] = self.Name +## self.Environment["MODULE_GUID"] = self.GuidValue +## self.Environment["MODULE_VERSION"] = self.Version +## self.Environment["MODULE_TYPE"] = self.Type +## self.Environment["MODULE_FILE_BASE_NAME"] = os.path.basename(self.Path).split(".")[0] +## self.Environment["MODULE_RELATIVE_DIR"] = os.path.dirname(self.Path) +## self.Environment["BASE_NAME"] = self.OutputName + +class Workspace(FrameworkElement.Workspace, SurfaceAreaElement): + _Db = "Tools/Conf/FrameworkDatabase.db" + _Target = "Tools/Conf/Target.txt" + _PlatformBuildPath = "Tools/Conf/platform_build_path.txt" + _ModuleBuildPath = "Tools/Conf/module_build_path.txt" + + def __init__(self, path, fpdList=None, msaList=None): + FrameworkElement.Workspace.__init__(self) + SurfaceAreaElement.__init__(self, self, None, None, False, False) + self.Path = os.path.normpath(path) + self.Dir = os.path.dirname(self.Path) + self._Elements["PlatformList"] = fpdList + self._Elements["ModuleList"] = msaList + self.Parse() + self.Postprocess() + + def _FdbHeader(self, xpath): + dom = XmlElement(self._Root, xpath) + if dom == '': return + self.Name = XmlElementData(XmlElement(dom, "/FdbHeader/DatabaseName")) + self.GuidValue = XmlElementData(XmlElement(dom, "/FdbHeader/GuidValue")).upper() + self.Version = XmlElementData(XmlElement(dom, "/FdbHeader/Version")) + + def _PackageList(self, xpath): + dom = XmlElement(self._Root, xpath) + if dom == '': return + + fileList = XmlList(dom, "/PackageList/Filename") + packages = [] + for f in fileList: + packages.append(os.path.normpath(XmlElementData(f))) + self._Elements["PackageList"] = packages + + def _PlatformList(self, xpath): + if len(self._Elements["PlatformList"]) > 0: + return + + dom = XmlElement(self._Root, xpath) + if dom == '': return + + fileList = XmlList(dom, "/PlatformList/Filename") + platforms = [] + for f in fileList: + platforms.append(os.path.normpath(XmlElementData(f))) + self._Elements["PlatformList"] = platforms + + def _FarList(self, xpath): + dom = XmlElement(self._Root, xpath) + if dom == '': return + + fileList = XmlList(dom, "/FarList/Filename") + fars = [] + for f in fileList: + fars.append(os.path.normpath(XmlElementData(f))) + self._Elements["FarList"] = fars + + def ParseWorkspaceDatabase(self): + # parse frameworkdatabase.db + self._Root = xml.dom.minidom.parse(self.SubPath(self._Db)) + assert self._Root.documentElement.tagName == "FrameworkDatabase" + + self._FdbHeader("/FrameworkDatabase/FdbHeader") + self._PackageList("/FrameworkDatabase/PackageList") + self._PlatformList("/FrameworkDatabase/PlatformList") + self._FarList("/FrameworkDatabase/FarList") + + def ParseConfig(self): + # parse target.txt + self.ParseTargetConfig() + # parse tools_def.txt + self.ParseToolConfig() + # parse platform/module_build_path.txt + + # active toolchain + # print self.TargetConfig + self.ActiveToolchain = self.TargetConfig["TOOL_CHAIN_TAG"] + if self.ActiveToolchain not in self.ToolConfig.Toolchains: + raise "Not supported tool chain tag %s" % self.ActiveToolchain + + # active toolchain family + self.ActiveFamilies = [] + for key in self.ToolConfig: + if self.ActiveToolchain in key and "FAMILY" in key: + family = self.ToolConfig[key] + if family not in self.ActiveFamilies: + self.ActiveFamilies.append(family) + + + def ParsePackage(self, packagePaths=None): + if packagePaths == None: + return + + for packagePath in packagePaths: + self.Packages.append(PackageSurfaceArea(self, packagePath)) + + def ParsePlatform(self, platformPaths=None): + # Only one active platform is allowed + activePlatformPath = "" + if self.TargetConfig["ACTIVE_PLATFORM"] == "": + if platformPaths != None and len(platformPaths) == 1: + activePlatformPath = platformPaths[0] + else: + raise Exception("No active platform specified or implied!") + else: + activePlatformPath = os.path.normpath(self.TargetConfig["ACTIVE_PLATFORM"]) + + self.ActivePlatform = PlatformSurfaceArea(self, activePlatformPath) + self.Platforms.append(self.ActivePlatform) + + def ParseTargetConfig(self): + self.TargetConfig = BuildConfig.TargetConfig(self.SubPath(self._Target)) + # print self.TargetConfig + + def ParseToolConfig(self): + self.ToolConfig = BuildConfig.ToolConfig(self.SubPath(self.TargetConfig["TOOL_CHAIN_CONF"])) + + def GetModule(self, guid, version, packageGuid, packageVersion): + moduleGuidIndex = self.ModuleXref["GUID"] + if guid not in moduleGuidIndex: + print "! No module has GUID=" + guid + return "" + + moduleVersionList = moduleGuidIndex[guid] + # print moduleVersionList + moduleList = [] + module = "" + if version != "": + if version in moduleVersionList: + moduleList = moduleVersionList[version] + else: + return "" + else: + ## no version given, return the first one + version = "0.0" + for ver in moduleVersionList: + if ver > version: version = ver + moduleList = moduleVersionList[version] + + if packageGuid == "": + ## if no package GUID given, just return the latest one + version = "0.0" + for m in moduleList: + if m.Package.Version > version: + version = m.Package.Version + module = m + else: + version = "0.0" + for m in moduleList: + if m.Package.GuidValue != packageGuid: continue + if packageVersion == "": + ## if no version given, just return the latest + if m.Package.Version > version: + version = m.Package.Version + module = m + elif packageVersion == m.Package.Version: + module = m + break; + + return module + + def GetModuleByPath(self, path): + ownerPackage = "" + ownerPackageFullPath = "" + for package in self.Packages: + ownerPackageFullPath = self.SubPath(package.Path) + if path.startswith(packageFullPath): break + + if ownerPackage == "": + return "" + + for module in ownerPackage.Modules: + moduleFullPath = os.path.join(ownerPackageFullPath, module.Path) + if moduleFullPath == path: + return module + + return "" + + def GetPackage(self, guid, version): + packageGuidIndex = self.PackageXref["GUID"] + if guid not in packageGuidIndex: + # raise Exception("No package has GUID=" + guid) + return "" + + packageList = packageGuidIndex[guid] + package = "" + if version != "": + if version in packageList: + package = packageList[version] + else: + ## no version given, return the latest one + version = "0.0" + for ver in packageList: + if ver > version: version = ver + package = packageList[version] + + return package + + def GetPlatform(self, guid, version): + pass + + def GetPlatformByPath(self, path): + for platform in self.Platforms: + platformFullPath = self.SubPath(platform.Path) + if platformFullPath == path: + return platform + return "" + + def GetLibraryInterface(self, name): + if name not in self.LibraryInterfaceXref["NAME"]: + return "" + return self.LibraryInterfaceXref["NAME"][name] + + def SubPath(self, *relativePathList): + return os.path.normpath(os.path.join(self.Path, *relativePathList)) + + def SetupCrossRef(self): + ## + ## setup platform cross reference as nest-dict + ## guid -> {version -> platform} + ## + ## platformList = self.Platforms + ## for p in platformList: + ## guid = p.GuidValue + ## version = p.Version + ## if guid not in self.PlatformIndex: + ## self.PlatformIndex[guid] = {} + ## if version in self.PlatformIndex[guid]: + ## raise Exception("Duplicate platform") + ## self.PlatformIndex[guid][version] = p + + ## + ## setup package cross reference as nest-dict + ## guid -> {version -> package} + ## name -> [package list] + ## path -> package + ## + packageList = self.Packages + for p in packageList: + guid = p.GuidValue + version = p.Version + packageGuidIndex = self.PackageXref["GUID"] + if guid not in packageGuidIndex: + packageGuidIndex[guid] = {} + if version in packageGuidIndex[guid]: + raise Exception("Duplicate package: %s-%s [%s]" % p.Name, version, guid) + packageGuidIndex[guid][version] = p + + packageNameIndex = self.PackageXref["NAME"] + name = p.Name + if name not in packageNameIndex: + packageNameIndex[name] = [] + packageNameIndex[name].append(p) + + packagePathIndex = self.PackageXref["PATH"] + path = p.Path + if path in packagePathIndex: + raise Exception("Duplicate package: %s %s" % p.Name, p.Path) + packagePathIndex[path] = p.Path + + ## + ## setup library class cross reference as + ## library class name -> library class object + ## + for lcname in p.LibraryInterfaces: + if lcname in self.LibraryInterfaceXref["NAME"]: + raise Exception("Duplicate library class: %s in package %s" % (lcname, name)) + lcInterface = p.LibraryInterfaces[lcname] + self.LibraryInterfaceXref["NAME"][lcname] = lcInterface + + if lcInterface not in self.LibraryInterfaceXref["PATH"]: + self.LibraryInterfaceXref["PATH"][lcInterface] = [] + self.LibraryInterfaceXref["PATH"][lcInterface].append(lcname) + + ## + ## setup package cross reference as nest-dict + ## guid -> {version -> [module list]} + ## name -> [module list] + ## path -> module + for p in packageList: + p.ParseMsaFile() + + moduleList = p.Modules + for m in moduleList: + name = m.Name + path = m.Path + guid = m.GuidValue + version = m.Version + moduleGuidIndex = self.ModuleXref["GUID"] + if guid not in moduleGuidIndex: + moduleGuidIndex[guid] = {} + else: + print "! Duplicate module GUID found:", guid, path + + if version not in moduleGuidIndex[guid]: + moduleGuidIndex[guid][version] = [] + if m in moduleGuidIndex[guid][version]: + raise Exception("Duplicate modules in the same package: %s-%s [%s]" % (name, version, guid)) + moduleGuidIndex[guid][version].append(m) + + modulePathIndex = self.ModuleXref["PATH"] + path = p.SubPath(m.Path) + if path in modulePathIndex: + raise Exception("Duplicate modules in the same package: %s %s" % (name, path)) + modulePathIndex[path] = m + + moduleNameIndex = self.ModuleXref["NAME"] + if name not in moduleNameIndex: + moduleNameIndex[name] = [] + moduleNameIndex[name].append(m) + + def GetToolDef(self, toolchain, target, arch, toolcode, attr): + return self.ToolConfig[(toolchain, target, arch, toolcode, attr)] + + def Parse(self): + self.ParseConfig() + self.ParseWorkspaceDatabase() + + def SetupBuild(self): + # active archs + self.ActiveArchs = self.TargetConfig["TARGET_ARCH"].split() + if self.ActiveArchs == []: + self.ActiveArchs = self.ActivePlatform.Archs + + # active targets + self.ActiveTargets = self.TargetConfig["TARGET"].split() + if self.ActiveTargets == []: + self.ActiveTargets = self.ActivePlatform.Targets + + + # active modules + for msa in self._Elements["ModuleList"]: + module = self.GetModuleByPath(msa) + if module == "": + raise Exception(msa + " is not in any package!") + self.ActiveModules.append(module) + self.IndividualModuleBuild = True + if self.TargetConfig["MULTIPLE_THREAD"].upper() == "ENABLE": + self.MultiThreadBuild = True + if "MAX_CONCURRENT_THREAD_NUMBER" in self.TargetConfig: + self.ThreadCount = self.TargetConfig["MAX_CONCURRENT_THREAD_NUMBER"] + else: + self.ThreadCount = "1" + + def Postprocess(self): + self.ParsePackage(self._Elements["PackageList"]) + self.SetupCrossRef() + self.ParsePlatform(self._Elements["PlatformList"]) + self.SetupBuild() + +## def SetupEnvironment(self): +## config = BuildConfig.Config(self.SubPath(self._PlatformBuildPath)) +## for name in config: +## self.Environment[name] = config[name] +## +## config = BuildConfig.Config(self.SubPath(self._ModuleBuildPath)) +## for name in config: +## self.Environment[name] = config[name] +## +## multiThread = self.TargetConfig["MULTIPLE_THREAD"].upper() +## threadNumber = self.TargetConfig["MAX_CONCURRENT_THREAD_NUMBER"] +## if multiThread == "" or multiThread == "FALSE": +## self.Environment["MULTIPLE_THREAD"] = False +## self.Environment["MAX_CONCURRENT_THREAD_NUMBER"] = 1 +## else: +## self.Environment["MULTIPLE_THREAD"] = True +## if threadNumber != "": +## self.Environment["MAX_CONCURRENT_THREAD_NUMBER"] = threadNumber +## else: +## self.Environment["MAX_CONCURRENT_THREAD_NUMBER"] = 2 + +class PackageSurfaceArea(FrameworkElement.Package, SurfaceAreaElement): + def __init__(self, workspace, path): + FrameworkElement.Package.__init__(self) + + self.Path = os.path.normpath(path) + self.Dir = os.path.dirname(self.Path) + SurfaceAreaElement.__init__(self, workspace, workspace, None, True, True) + + def _SpdHeader(self, xpath): + dom = XmlElement(self._Root, xpath) + self.Name = XmlElementData(XmlElement(dom, "/SpdHeader/PackageName")) + self.GuidValue = XmlElementData(XmlElement(dom, "/SpdHeader/GuidValue")).upper() + self.Version = XmlElementData(XmlElement(dom, "/SpdHeader/Version")) + + def _PackageDefinitions(self, xpath): + dom = XmlElement(self._Root, xpath) + self.ReadOnly = XmlElementData(XmlElement(dom, "/PackageDefinitions/ReadOnly")) + self.Repackage = XmlElementData(XmlElement(dom, "/PackageDefinitions/RePackage")) + + def _LibraryClassDeclarations(self, xpath): + dom = XmlElement(self._Root, xpath) + lcdList = XmlList(dom, "/LibraryClassDeclarations/LibraryClass") + lcds = [] + for lc in lcdList: + lcds.append(LibraryDeclaration(self._Workspace, self, lc)) + self._Elements["LibraryClassDeclarations"] = lcds + + def _IndustryStdIncludes(self, xpath): + dom = XmlElement(self._Root, xpath) + headerList = XmlList(dom, "/IndustryStdIncludes/IndustryStdHeader") + headers = [] + for h in headerList: + headers.append(IndustryStdHeader(self._Workspace, self, h)) + self._Elements["IndustryStdIncludes"] = headers + + def _MsaFiles(self, xpath): + dom = XmlElement(self._Root, xpath) + msaFileList = XmlList(dom, "/MsaFiles/Filename") + msaFiles = [] + for msa in msaFileList: + filePath = os.path.normpath(XmlElementData(msa)) + msaFiles.append(filePath) + self._Elements["MsaFiles"] = msaFiles + + def _PackageHeaders(self, xpath): + dom = XmlElement(self._Root, xpath) + headerList = XmlList(dom, "/PackageHeaders/IncludePkgHeader") + headers = [] + for h in headerList: + headers.append(PackageHeader(self._Workspace, self, h)) + self._Elements["PackageHeaders"] = headers + + def _GuidDeclarations(self, xpath): + dom = XmlElement(self._Root, xpath) + guidList = XmlList(dom, "/GuidDeclarations/Entry") + guids = [] + for guid in guidList: + guids.append(GuidDeclaration(self._Workspace, self, guid)) + self._Elements["GuidDeclarations"] = guids + + def _ProtocolDeclarations(self, xpath): + dom = XmlElement(self._Root, xpath) + protocolList = XmlList(dom, "/ProtocolDeclarations/Entry") + protocols = [] + for p in protocolList: + protocols.append(ProtocolDeclaration(self._Workspace, self, p)) + self._Elements["ProtocolDeclarations"] = protocols + + def _PpiDeclarations(self, xpath): + dom = XmlElement(self._Root, xpath) + ppiList = XmlList(dom, "/PpiDeclarations/Entry") + ppis = [] + for p in ppiList: + ppis.append(PpiDeclaration(self._Workspace, self, p)) + self._Elements["PpiDeclarations"] = ppis + + def _PcdDeclarations(self, xpath): + dom = XmlElement(self._Root, xpath) + pcdList = XmlList(dom, "/PcdDeclarations/PcdEntry") + pcds = [] + for p in pcdList: + pcds.append(PcdDeclaration(self._Workspace, self, p)) + self._Elements["PcdDeclarations"] = pcds + + def SubPath(self, *relativePathList): + return os.path.normpath(os.path.join(self.Dir, *relativePathList)) + + def Parse(self): + self._Root = xml.dom.minidom.parse(self._Workspace.SubPath(self.Path)) + assert self._Root.documentElement.tagName == "PackageSurfaceArea" + + # print "Parsing...",self.Path + self._SpdHeader("/PackageSurfaceArea/SpdHeader") + self._PackageDefinitions("/PackageSurfaceArea/PackageDefinitions") + self._LibraryClassDeclarations("/PackageSurfaceArea/LibraryClassDeclarations") + self._IndustryStdIncludes("/PackageSurfaceArea/IndustryStdIncludes") + self._MsaFiles("/PackageSurfaceArea/MsaFiles") + self._PackageHeaders("/PackageSurfaceArea/PackageHeaders") + self._GuidDeclarations("/PackageSurfaceArea/GuidDeclarations") + self._ProtocolDeclarations("/PackageSurfaceArea/ProtocolDeclarations") + self._PpiDeclarations("/PackageSurfaceArea/PpiDeclarations") + self._PcdDeclarations("/PackageSurfaceArea/PcdDeclarations") + + def Postprocess(self): + # setup guid, protocol, ppi + for guid in self._Elements["GuidDeclarations"]: + if guid.CName in self.Guids: + print "! Duplicate GUID CName (%s) in package %s" % (guid.CName, self.Path) + self.Guids[guid.CName] = guid + + for protocol in self._Elements["ProtocolDeclarations"]: + if protocol.CName in self.Protocols: + print "! Duplicate Protocol CName (%s) in package %s" % (protocol.CName, self.Path) + self.Protocols[protocol.CName] = protocol + + for ppi in self._Elements["PpiDeclarations"]: + if ppi.CName in self.Ppis: + print "! Duplicate PPI CName (%s) in package (%s)" % (ppi.CName, self.Path) + self.Ppis[ppi.CName] = ppi + + # package header + for inc in self._Elements["PackageHeaders"]: + if inc.ModuleType not in self.PackageIncludes: + self.PackageIncludes[inc.ModuleType] = [] + self.PackageIncludes[inc.ModuleType].append(inc.Path) + + # library class + for lcd in self._Elements["LibraryClassDeclarations"]: + if lcd.Name in self.LibraryInterfaces: + raise "Duplicate library class: " + lcd.Name + self.LibraryInterfaces[lcd.Name] = lcd + + # parse mas files + # self.ParseMsaFile() + # resolve RecommendedInstance + + def ParseMsaFile(self): + for msaFilePath in self._Elements["MsaFiles"]: + self.Modules.append(ModuleSurfaceArea(self._Workspace, self, msaFilePath)) + +class PlatformSurfaceArea(FrameworkElement.Platform, SurfaceAreaElement): + def __init__(self, workspace, path): + FrameworkElement.Platform.__init__(self) + + self.Path = os.path.normpath(path) + self.Dir = os.path.dirname(self.Path) + SurfaceAreaElement.__init__(self, workspace) + + def _PlatformHeader(self, xpath): + dom = XmlElement(self._Root, xpath) + if dom == '': return + self.Name = XmlElementData(XmlElement(dom, "/PlatformHeader/PlatformName")) + self.GuidValue = XmlElementData(XmlElement(dom, "/PlatformHeader/GuidValue")).upper() + self.Version = XmlElementData(XmlElement(dom, "/PlatformHeader/Version")) + + def _PlatformDefinitions(self, xpath): + dom = XmlElement(self._Root, xpath) + if dom == '': return + self.Archs = XmlElementData(XmlElement(dom, "/PlatformDefinitions/SupportedArchitectures")).split() + if self.Archs == []: + raise Exception("No ARCH specified in platform " + self.Path) + self.Targets = XmlElementData(XmlElement(dom, "/PlatformDefinitions/BuildTargets")).split() + self.OutputPath = os.path.normpath(XmlElementData(XmlElement(dom, "/PlatformDefinitions/OutputDirectory"))) + + def _Flash(self, xpath): + dom = XmlElement(self._Root, xpath) + if dom == '': return + + def _FrameworkModules(self, xpath): + dom = XmlElement(self._Root, xpath) + if dom == '': return + moduleList = XmlList(dom, "/FrameworkModules/ModuleSA") + modules = [] + for m in moduleList: + modules.append(PlatformModule(self._Workspace, self, m)) + self._Elements["FrameworkModules"] = modules + + def _DynamicPcdBuildDefinitions(self, xpath): + dom = XmlElement(self._Root, xpath) + if dom == '': return + + def _BuildOptions(self, xpath): + dom = XmlElement(self._Root, xpath) + if dom == '': return + self.BuildOptions = self.GetBuildOptionList(XmlElement(dom, "/BuildOptions/Options")) + # print self.BuildOptions + + def _UserExtensions(self, xpath): + domList = XmlList(self._Root, xpath) + if domList == []: return + for extension in domList: + userId = XmlAttribute(extension, "UserID") + identifier = XmlAttribute(extension, "Identifier") + + if userId == '' or identifier == '': + raise Exception("No UserId or Identifier specified") + if userId != "TianoCore": continue + if identifier not in self.UserExtensions: + self.UserExtensions[identifier] = [] + + contentList = self.UserExtensions[identifier] + for node in extension.childNodes: + # print node.nodeType + contentList.append(node.cloneNode(True)) + + def Parse(self): + self._Root = xml.dom.minidom.parse(self._Workspace.SubPath(self.Path)) + assert self._Root.documentElement.tagName == "PlatformSurfaceArea" + + self._PlatformHeader("/PlatformSurfaceArea/PlatformHeader") + self._PlatformDefinitions("/PlatformSurfaceArea/PlatformDefinitions") + self._Flash("/PlatformSurfaceArea/Flash") + self._FrameworkModules("/PlatformSurfaceArea/FrameworkModules") + self._DynamicPcdBuildDefinitions("/PlatformSurfaceArea/DynamicPcdBuildDefinitions") + self._BuildOptions("/PlatformSurfaceArea/BuildOptions") + self._UserExtensions("/PlatformSurfaceArea/UserExtensions") + + def Postprocess(self): + # summarize all library modules for build + for module in self._Elements["FrameworkModules"]: + for arch in module.Archs: + if arch not in self.Modules: + self.Modules[arch] = [] + self.Modules[arch].append(module) + + if arch not in self.Libraries: + self.Libraries[arch] = [] + for li in module.Libraries: + if li in self.Libraries[arch]: continue + self.Libraries[arch].append(li) + + # FV + for fvName in module.FvBindings: + if fvName not in self.Fvs: + self.Fvs[fvName] = [] + self.Fvs[fvName].append(module) + # build options + # user extension + +## def SetupEnvironment(self): +## self.Environment["PLATFORM"] = self.Name +## self.Environment["PLATFORM_GUID"] = self.GuidValue +## self.Environment["PLATFORM_VERSION"] = self.Version +## self.Environment["PLATFORM_RELATIVE_DIR"] = self.Path +## self.Environment["PLATFORM_OUTPUT_DIR"] = self.OutputPath + +def PrintWorkspace(ws): + print "\nPlatforms:\n" + for guid in ws.PlatformXref["GUID"]: + for ver in ws.PlatformXref["GUID"][guid]: + platform = ws.PlatformXref["GUID"][guid][ver] + print " %s %s-%s" % (guid, platform.Name, ver) + for pm in platform.Modules: + print " %-40s %-10s <%s-%s>" % (pm.Module.Name+"-"+pm.Module.Version, + ListString(pm.Archs), pm.Module.Package.Name, + pm.Module.Package.Version) + for li in pm.Libraries: + print " %-47s <%s-%s>" % (li.Module.Name+"-"+li.Module.Version, + li.Module.Package.Name, li.Module.Package.Version) + print "" + + print "\nPackages:\n" + for guid in ws.PackageXref["GUID"]: + for ver in ws.PackageXref["GUID"][guid]: + print " %s %s-%s" % (guid, ws.PackageXref["GUID"][guid][ver].Name, ver) + + print "\nModules:\n" + for guid in ws.ModuleXref["GUID"]: + for ver in ws.ModuleXref["GUID"][guid]: + for module in ws.ModuleXref["GUID"][guid][ver]: + print " %s %-40s [%s-%s]" % (guid, module.Name+"-"+ver, module.Package.Name, module.Package.Version) + print " Depending on packages:" + for arch in module.IncludePaths: + print " ", arch, ":" + for path in module.IncludePaths[arch]: + print " ", path + print "\n" + + for arch in module.IncludeFiles: + print " ", arch, ":" + for path in module.IncludeFiles[arch]: + print " ", path + print "\n" + + print " Source files:" + for arch in module.SourceFiles: + print " ", arch, ":" + for type in module.SourceFiles[arch]: + for src in module.SourceFiles[arch][type]: + print " %-40s (%s)" % (src.Path, src.Type) + print "\n" + print "\nLibrary Classes:" + for name in ws.LibraryInterfaceXref["NAME"]: + lc = ws.LibraryInterfaceXref["NAME"][name] + pkgPath = os.path.dirname(lc.Package.Path) + print "\n [%s] <%s>" % (lc.Name, pkgPath + os.path.sep + lc.Path) + + print " Produced By:" + for li in lc.Instances: + print " %-40s <%s>" % (li.Name+"-"+li.Version, li.Package.SubPath(li.Path)) + + print " Consumed By:" + for li in lc.Consumers: + print " %-40s <%s>" % (li.Name+"-"+li.Version, li.Package.SubPath(li.Path)) + + print "\nActive Platform:" + for arch in ws.ActivePlatform.Libraries: + print " Library Instances (%s) (%d libraries)" % (arch , len(ws.ActivePlatform.Libraries[arch])) + for li in ws.ActivePlatform.Libraries[arch]: + print " %s-%s (%s-%s)" % (li.Module.Name, li.Module.Version, + li.Module.Package.Name, li.Module.Package.Version) + + for arch in ws.ActivePlatform.Modules: + print " Driver Modules (%s) (%d modules)" % (arch, len(ws.ActivePlatform.Modules[arch])) + for m in ws.ActivePlatform.Modules[arch]: + print " %s-%s (%s-%s)" % (m.Module.Name, m.Module.Version, + m.Module.Package.Name, m.Module.Package.Version) + + for fv in ws.ActivePlatform.Fvs: + print + print " Firmware Volume (%s) (%d modules)" % (fv, len(ws.ActivePlatform.Fvs[fv])) + for m in ws.ActivePlatform.Fvs[fv]: + print " %s-%s (%s-%s)" % (m.Module.Name, m.Module.Version, + m.Module.Package.Name, m.Module.Package.Version) + +# for test +if __name__ == "__main__": + # os.environ["WORKSPACE"] + workspacePath = os.getenv("WORKSPACE", os.getcwd()) + saFile = "" + if len(sys.argv) <= 1: + saFile = os.path.join(workspacePath, "Tools/Conf/FrameworkDatabase.db") + else: + saFile = sys.argv[1] + + print "Parsing ... %s\n" % saFile + + startTime = time.clock() + sa = Workspace(workspacePath, [], []) +## dbak = None +## if os.path.exists("workspace.bak"): +## dbak = shelve.open("workspace.bak", protocol=2) +## sa = dbak.db +## dbak.close() +## else: +## sa = FrameworkDatabase(saFile) +## dbak = shelve.open("workspace.bak", protocol=2) +## dbak.db = sa +## dbak.close() + # sa = PackageSurfaceArea(saFile) + # sa = PlatformSurfaceArea(saFile) + # sa = ModuleSurfaceArea(saFile) + # print sa + + PrintWorkspace(sa) + print "\n[Finished in %fs]" % (time.clock() - startTime) + diff --git a/Tools/Python/buildgen/XmlRoutines.py b/Tools/Python/buildgen/XmlRoutines.py new file mode 100644 index 0000000000..8d659c4372 --- /dev/null +++ b/Tools/Python/buildgen/XmlRoutines.py @@ -0,0 +1,104 @@ +#!/usr/bin/env python + +# Copyright (c) 2007, Intel Corporation +# All rights reserved. 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. + +"""This is an XML API that uses a syntax similar to XPath, but it is written in + standard python so that no extra python packages are required to use it.""" + +import xml.dom.minidom + +def XmlList(Dom, String): + """Get a list of XML Elements using XPath style syntax.""" + if String == "" or Dom == None or not isinstance(Dom, xml.dom.Node): + return [] + + if String[0] == "/": + String = String[1:] + + if Dom.nodeType==Dom.DOCUMENT_NODE: + Dom = Dom.documentElement + + tagList = String.split('/') + nodes = [Dom] + childNodes = [] + index = 0 + end = len(tagList) - 1 + while index <= end: + for node in nodes: + if node.nodeType == node.ELEMENT_NODE and node.tagName == tagList[index]: + if index < end: + childNodes.extend(node.childNodes) + else: + childNodes.append(node) + + nodes = childNodes + childNodes = [] + index += 1 + + return nodes + +def XmlElement (Dom, String): + """Return a single element that matches the String which is XPath style syntax.""" + if String == "" or Dom == None or not isinstance(Dom, xml.dom.Node): + return "" + + if String[0] == "/": + String = String[1:] + + if Dom.nodeType==Dom.DOCUMENT_NODE: + Dom = Dom.documentElement + + tagList = String.split('/') + childNodes = [Dom] + index = 0 + end = len(tagList) - 1 + while index <= end: + for node in childNodes: + if node.nodeType == node.ELEMENT_NODE and node.tagName == tagList[index]: + if index < end: + childNodes = node.childNodes + else: + return node + break + + index += 1 + + return "" + +def XmlElementData (Dom): + """Get the text for this element.""" + if Dom == None or Dom == '' or Dom.firstChild == None: + return '' + + return Dom.firstChild.data.strip(' ') + +def XmlAttribute (Dom, String): + """Return a single attribute that named by String.""" + if Dom == None or Dom == '': + return '' + + try: + return Dom.getAttribute(String).strip(' ') + except: + return '' + +def XmlTopTag(Dom): + """Return the name of the Root or top tag in the XML tree.""" + if Dom == None or Dom == '' or Dom.firstChild == None: + return '' + return Dom.firstChild.nodeName + + +# This acts like the main() function for the script, unless it is 'import'ed into another +# script. +if __name__ == '__main__': + + # Nothing to do here. Could do some unit tests. + pass diff --git a/Tools/Python/buildgen/module_build_path.txt b/Tools/Python/buildgen/module_build_path.txt new file mode 100644 index 0000000000..e5c8ed103d --- /dev/null +++ b/Tools/Python/buildgen/module_build_path.txt @@ -0,0 +1,5 @@ +BIN_DIR=${PLATFORM_BUILD_DIR}/${ARCH} +MODULE_BUILD_DIR=${BIN_DIR}/${PACKAGE_RELATIVE_DIR}/${MODULE_RELATIVE_DIR}/${MODULE_FILE_BASE_NAME} +DEST_DIR_OUTPUT=${MODULE_BUILD_DIR}/OUTPUT +DEST_DIR_DEBUG=${MODULE_BUILD_DIR}/DEBUG + diff --git a/Tools/Python/buildgen/platform_build_path.txt b/Tools/Python/buildgen/platform_build_path.txt new file mode 100644 index 0000000000..1218ac0ff8 --- /dev/null +++ b/Tools/Python/buildgen/platform_build_path.txt @@ -0,0 +1,5 @@ +BUILD_DIR=${WORKSPACE_DIR}/${PLATFORM_OUTPUT_DIR} +PLATFORM_BUILD_DIR=${BUILD_DIR}/${TARGET}_${TOOLCHAIN} +TARGET_DIR=${PLATFORM_BUILD_DIR} +FV_DIR=${TARGET_DIR}/FV +