| ## @file | |
| # Install distribution package. | |
| # | |
| # 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. | |
| # | |
| ## | |
| # Import Modules | |
| # | |
| import os | |
| import os.path | |
| import sys | |
| import glob | |
| import shutil | |
| import traceback | |
| import platform | |
| from optparse import OptionParser | |
| import md5 | |
| import time | |
| import uuid | |
| from PackageFile import * | |
| import Common.EdkLogger as EdkLogger | |
| from Common.BuildToolError import * | |
| from Common.Misc import * | |
| from Common.XmlParser import * | |
| from CommonDataClass.DistributionPackageClass import * | |
| from Common.DecClassObjectLight import Dec | |
| from Common.InfClassObjectLight import Inf | |
| from PackageFile import * | |
| # Version and Copyright | |
| VersionNumber = "0.1" | |
| __version__ = "%prog Version " + VersionNumber | |
| __copyright__ = "Copyright (c) 2008, Intel Corporation All rights reserved." | |
| ## Check environment variables | |
| # | |
| # Check environment variables that must be set for build. Currently they are | |
| # | |
| # WORKSPACE The directory all packages/platforms start from | |
| # EDK_TOOLS_PATH The directory contains all tools needed by the build | |
| # PATH $(EDK_TOOLS_PATH)/Bin/<sys> must be set in PATH | |
| # | |
| # If any of above environment variable is not set or has error, the build | |
| # will be broken. | |
| # | |
| def CheckEnvVariable(): | |
| # check WORKSPACE | |
| if "WORKSPACE" not in os.environ: | |
| EdkLogger.error("MkPkg", ATTRIBUTE_NOT_AVAILABLE, "Environment variable not found", | |
| ExtraData="WORKSPACE") | |
| WorkspaceDir = os.path.normpath(os.environ["WORKSPACE"]) | |
| if not os.path.exists(WorkspaceDir): | |
| EdkLogger.error("MkPkg", FILE_NOT_FOUND, "WORKSPACE doesn't exist", ExtraData="%s" % WorkspaceDir) | |
| elif ' ' in WorkspaceDir: | |
| EdkLogger.error("MkPkg", FORMAT_NOT_SUPPORTED, "No space is allowed in WORKSPACE path", | |
| ExtraData=WorkspaceDir) | |
| os.environ["WORKSPACE"] = WorkspaceDir | |
| ## Parse command line options | |
| # | |
| # Using standard Python module optparse to parse command line option of this tool. | |
| # | |
| # @retval Opt A optparse.Values object containing the parsed options | |
| # @retval Args Target of build command | |
| # | |
| def MyOptionParser(): | |
| UsageString = "%prog -m <module_file> -p <package_file> [-o distribution_file] " + \ | |
| "[-x xml-file-header] [-t tools-directory] [-f misc-files] [-q | -v] [-h]" | |
| Parser = OptionParser(description=__copyright__,version=__version__,prog="MkPkg",usage=UsageString) | |
| Parser.add_option("-?", action="help", help="show this help message and exit") | |
| Parser.add_option("-o", "--output-file", action="store", type="string", dest="DistributionFile", | |
| help="Specify the distribution file to be created.") | |
| Parser.add_option("-f", "--misc-files", action="append", type="string", dest="MiscFiles", | |
| help="Specify any misc files.") | |
| Parser.add_option("-x", "--xml-file-header", action="store", type=None, dest="TemplateFile", | |
| help="Specify the xml file which includes header information for creating the distribution file.") | |
| Parser.add_option("-t", "--tools-directory", action="store", type=None, dest="ToolsDir", | |
| help="Specify the directory name of tools.") | |
| Parser.add_option("-m", "--module", action="append", type="string", dest="ModuleFileList", | |
| help="The inf file of module to be distributed standalone.") | |
| Parser.add_option("-p", "--package", action="append", type="string", dest="PackageFileList", | |
| help="The dec file of package to be distributed.") | |
| Parser.add_option("-q", "--quiet", action="store_const", dest="LogLevel", const=EdkLogger.QUIET, | |
| help="Disable all messages except FATAL ERRORS.") | |
| Parser.add_option("-v", "--verbose", action="store_const", dest="LogLevel", const=EdkLogger.VERBOSE, | |
| help="Turn on verbose output") | |
| Parser.add_option("-d", "--debug", action="store", type="int", dest="LogLevel", | |
| help="Enable debug messages at specified level.") | |
| Parser.set_defaults(LogLevel=EdkLogger.INFO) | |
| (Opt, Args)=Parser.parse_args() | |
| # error check | |
| if not Opt.ModuleFileList and not Opt.PackageFileList: | |
| EdkLogger.error("MkPkg", OPTION_NOT_SUPPORTED, ExtraData="At least one package file or module file must be specified") | |
| if Opt.TemplateFile: | |
| if not os.path.exists(Opt.TemplateFile): | |
| EdkLogger.error( | |
| "\nMkPkg", | |
| FILE_NOT_FOUND, | |
| "Template file [%s] not found" % Opt.TemplateFile | |
| ) | |
| return Opt | |
| ## Tool entrance method | |
| # | |
| # This method mainly dispatch specific methods per the command line options. | |
| # If no error found, return zero value so the caller of this tool can know | |
| # if it's executed successfully or not. | |
| # | |
| # @retval 0 Tool was successful | |
| # @retval 1 Tool failed | |
| # | |
| def Main(): | |
| EdkLogger.Initialize() | |
| Options = MyOptionParser() | |
| try: | |
| if Options.LogLevel < EdkLogger.DEBUG_9: | |
| EdkLogger.SetLevel(Options.LogLevel + 1) | |
| else: | |
| EdkLogger.SetLevel(Options.LogLevel) | |
| CheckEnvVariable() | |
| WorkspaceDir = os.environ["WORKSPACE"] | |
| # Init DistributionFile | |
| if not Options.DistributionFile: | |
| Options.DistributionFile = "DistributionPackage.zip" | |
| # Check Tools Dir | |
| if Options.ToolsDir: | |
| if not os.path.isdir(os.path.normpath(os.path.join(WorkspaceDir, Options.ToolsDir))): | |
| EdkLogger.error( | |
| "\nMkPkg", | |
| FILE_NOT_FOUND, | |
| "Tools directory [%s] not found" % Options.ToolsDir | |
| ) | |
| # Check misc files | |
| if Options.MiscFiles: | |
| for Item in Options.MiscFiles: | |
| FullPath = os.path.normpath(os.path.join(WorkspaceDir, Item)) | |
| if not os.path.isfile(FullPath): | |
| EdkLogger.error( | |
| "\nMkPkg", | |
| FILE_NOT_FOUND, | |
| "Misc file [%s] not found" % Item | |
| ) | |
| #Check package file existing and valid | |
| if Options.PackageFileList: | |
| for Item in Options.PackageFileList: | |
| (Name, Ext) = os.path.splitext(Item) | |
| if Ext.upper() != '.DEC': | |
| EdkLogger.error( | |
| "\nMkPkg", | |
| OPTION_VALUE_INVALID, | |
| "[%s] is not a valid package name" % Item | |
| ) | |
| Path = os.path.normpath(os.path.join(WorkspaceDir, Item)) | |
| if not os.path.exists(Path): | |
| EdkLogger.error( | |
| "\nMkPkg", | |
| FILE_NOT_FOUND, | |
| "[%s] not found" % Item | |
| ) | |
| #Check module file existing and valid | |
| if Options.ModuleFileList: | |
| for Item in Options.ModuleFileList: | |
| (Name, Ext) = os.path.splitext(Item) | |
| if Ext.upper() != '.INF': | |
| EdkLogger.error( | |
| "\nMkPkg", | |
| OPTION_VALUE_INVALID, | |
| "[%s] is not a valid module name" % Item | |
| ) | |
| Path = os.path.normpath(os.path.join(WorkspaceDir, Item)) | |
| if not os.path.exists(Path): | |
| EdkLogger.error( | |
| "\nMkPkg", | |
| FILE_NOT_FOUND, | |
| "[%s] not found" % Item | |
| ) | |
| ContentFile = PackageFile("content.zip", "w") | |
| DistPkg = DistributionPackageClass() | |
| DistPkg.GetDistributionPackage(WorkspaceDir, Options.PackageFileList, Options.ModuleFileList) | |
| DistPkgXml = DistributionPackageXml() | |
| for Item in DistPkg.PackageSurfaceArea: | |
| ContentFile.Pack(os.path.dirname(os.path.normpath(os.path.join(WorkspaceDir,Item[2])))) | |
| for Item in DistPkg.ModuleSurfaceArea: | |
| ContentFile.Pack(os.path.dirname(os.path.normpath(os.path.join(WorkspaceDir,Item[2])))) | |
| # Add tools files and information | |
| if Options.ToolsDir: | |
| ToolsFiles = MiscFileClass() | |
| ToolsRoot = os.path.normpath(os.path.join(WorkspaceDir, Options.ToolsDir)) | |
| ContentFile.Pack(ToolsRoot) | |
| ToolsFileList = GetFiles(ToolsRoot, ['CVS', '.svn']) | |
| for Item in ToolsFileList: | |
| OriPath = Item[len(WorkspaceDir)+1:] | |
| FileObj = FileClass() | |
| FileObj.Filename = OriPath | |
| (Name, Ext) = os.path.splitext(OriPath) | |
| if Ext.upper() in ['EXE', 'COM', 'EFI']: | |
| FileObj.Executable = 'True' | |
| ToolsFiles.Files.append(FileObj) | |
| DistPkg.Tools = ToolsFiles | |
| # Add misc files and information | |
| if Options.MiscFiles: | |
| MiscFiles = MiscFileClass() | |
| for Item in Options.MiscFiles: | |
| ContentFile.PackFile(Item) | |
| FileObj = FileClass() | |
| FileObj.Filename = Item | |
| (Name, Ext) = os.path.splitext(Item) | |
| if Ext.upper() in ['EXE', 'COM', 'EFI']: | |
| FileObj.Executable = 'True' | |
| MiscFiles.Files.append(FileObj) | |
| DistPkg.MiscellaneousFiles = MiscFiles | |
| print "Compressing Distribution Package File ..." | |
| ContentFile.Close() | |
| # Add temp distribution header | |
| if Options.TemplateFile: | |
| TempXML = DistributionPackageXml() | |
| DistPkg.Header = TempXML.FromXml(Options.TemplateFile).Header | |
| # Add init dp information | |
| else: | |
| DistPkg.Header.Name = 'Distribution Package' | |
| DistPkg.Header.Guid = str(uuid.uuid4()) | |
| DistPkg.Header.Version = '1.0' | |
| # Add Md5Sigature | |
| Md5Sigature = md5.new(open(str(ContentFile)).read()) | |
| DistPkg.Header.Signature = Md5Sigature.hexdigest() | |
| # Add current Date | |
| DistPkg.Header.Date = str(time.strftime("%Y-%m-%dT%H:%M:%S", time.localtime())) | |
| # Finish final dp file | |
| DistPkgFile = PackageFile(Options.DistributionFile, "w") | |
| DistPkgFile.PackFile(str(ContentFile)) | |
| DistPkgFile.PackData(DistPkgXml.ToXml(DistPkg), "dist.pkg") | |
| DistPkgFile.Close() | |
| print "DONE" | |
| except FatalError, X: | |
| if Options and Options.LogLevel < EdkLogger.DEBUG_9: | |
| EdkLogger.quiet("(Python %s on %s) " % (platform.python_version(), sys.platform) + traceback.format_exc()) | |
| ReturnCode = X.args[0] | |
| except KeyboardInterrupt: | |
| ReturnCode = ABORT_ERROR | |
| if Options and Options.LogLevel < EdkLogger.DEBUG_9: | |
| EdkLogger.quiet("(Python %s on %s) " % (platform.python_version(), sys.platform) + traceback.format_exc()) | |
| except: | |
| EdkLogger.error( | |
| "\nMkPkg", | |
| CODE_ERROR, | |
| "Unknown fatal error when creating [%s]" % Options.DistributionFile, | |
| ExtraData="\n(Please send email to dev@buildtools.tianocore.org for help, attaching following call stack trace!)\n", | |
| RaiseError=False | |
| ) | |
| EdkLogger.quiet("(Python %s on %s) " % (platform.python_version(), sys.platform) + traceback.format_exc()) | |
| ReturnCode = CODE_ERROR | |
| finally: | |
| Progressor.Abort() | |
| if __name__ == '__main__': | |
| sys.exit(Main()) | |