#!/usr/bin/env python ################################################################################ # # qooxdoo - the new era of web development # # http://qooxdoo.org # # Copyright: # 2006-2008 1&1 Internet AG, Germany, http://www.1und1.de # # License: # LGPL: http://www.gnu.org/licenses/lgpl.html # EPL: http://www.eclipse.org/org/documents/epl-v10.php # See the LICENSE file in the project's top-level directory for details. # # Authors: # * Sebastian Werner (wpbasti) # * Andreas Ecker (ecker) # * Fabian Jakobs (fjakobs) # * Alessandro Sala (asala) # ################################################################################ import sys, re, os, optparse, math # reconfigure path to import own modules from modules subfolder sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(sys.argv[0])), "modules")) import config, tokenizer, loader, api, tree, treegenerator, settings, variants, resources import filetool, stringoptimizer, optparseext, privateoptimizer, variableoptimizer, compiler import migrator, textutil, graph, variantoptimizer, basecalloptimizer import obfuscator, accessorobfuscator def getparser(): parser = optparse.OptionParser("usage: %prog [options]", option_class=optparseext.ExtendAction) ################################################################################# # GENERAL ################################################################################# # From/To File parser.add_option("--from-file", dest="fromFile", metavar="FILENAME", help="Read options from FILENAME.") parser.add_option("--export-to-file", dest="exportToFile", metavar="FILENAME", help="Store options to FILENAME.") # Directories (Lists, Match using index) parser.add_option("--class-path", action="extend", dest="classPath", metavar="DIRECTORY", type="string", default=[], help="Define a class path.") parser.add_option("--class-uri", action="extend", dest="classUri", metavar="PATH", type="string", default=[], help="Define a script path for the source version.") parser.add_option("--class-encoding", action="extend", dest="classEncoding", metavar="ENCODING", type="string", default=[], help="Define the encoding for a class path.") parser.add_option("--resource-input", action="extend", dest="resourceInput", metavar="DIRECTORY", type="string", default=[], help="Define a resource input directory.") parser.add_option("--resource-output", action="extend", dest="resourceOutput", metavar="DIRECTORY", type="string", default=[], help="Define a resource output directory.") # Available Actions parser.add_option("--generate-compiled-script", action="store_true", dest="generateCompiledScript", default=False, help="Compile source files.") parser.add_option("--generate-source-script", action="store_true", dest="generateSourceScript", default=False, help="Generate source version.") parser.add_option("--generate-api-documentation", action="store_true", dest="generateApiDocumentation", default=False, help="Generate API documentation.") parser.add_option("--copy-resources", action="store_true", dest="copyResources", default=False, help="Copy resource files.") parser.add_option("--fix-source", action="store_true", dest="fixSource", default=False, help="Fix source files") parser.add_option("--pretty-print", action="store_true", dest="prettyPrint", default=False, help="Pretty print source code.") parser.add_option("--migrate-source", action="store_true", dest="migrateSource", default=False, help="Migrate existing code to new version.") # Debug Actions parser.add_option("--store-tokens", action="store_true", dest="storeTokens", default=False, help="Store tokenized content of source files. (Debugging)") parser.add_option("--store-tree", action="store_true", dest="storeTree", default=False, help="Store tree content of source files. (Debugging)") parser.add_option("--print-files", action="store_true", dest="printFiles", default=False, help="Output known files. (Debugging)") parser.add_option("--print-modules", action="store_true", dest="printModules", default=False, help="Output known modules. (Debugging)") parser.add_option("--print-files-without-modules", action="store_true", dest="printFilesWithoutModules", default=False, help="Output files which have no module connection. (Debugging)") parser.add_option("--print-includes", action="store_true", dest="printIncludes", default=False, help="Output sorted file list. (Debugging)") parser.add_option("--print-includes-file", dest="printIncludesFile", default=False, help="Save sorted include list to a file. (Debugging)") parser.add_option("--print-dependencies", action="store_true", dest="printDependencies", default=False, help="Output dependencies of files. (Debugging)") parser.add_option("--dependencies-graphviz-file", dest="depDotFile", metavar="FILENAME", help="Save dependencies as graphviz dot file. (Debugging)") # Output files parser.add_option("--source-script-file", dest="sourceScriptFile", metavar="FILENAME", help="Name of output file from source build process.") parser.add_option("--source-template-input-file", dest="sourceTemplateInputFile", metavar="FILENAME", help="Name of a template file to patch") parser.add_option("--source-template-output-file", dest="sourceTemplateOutputFile", metavar="FILENAME", help="Name of the resulting file to store the modified template to.") parser.add_option("--source-template-replace", dest="sourceTemplateReplace", default="", metavar="CODE", help="Content of the template which should be replaced with the script block.") parser.add_option("--compiled-script-file", dest="compiledScriptFile", metavar="FILENAME", help="Name of output file from compiler.") parser.add_option("--api-documentation-json-file", dest="apiDocumentationJsonFile", metavar="FILENAME", help="Name of JSON API file.") parser.add_option("--api-documentation-xml-file", dest="apiDocumentationXmlFile", metavar="FILENAME", help="Name of XML API file.") parser.add_option("--api-separate-files", action="store_true", dest="apiSeparateFiles", default=False, help="Output each class documentation into a separate file.") parser.add_option("--api-documentation-index-file", dest="apiDocumentationIndexFile", metavar="FILENAME", help="Name of API search index file.") # Encoding parser.add_option("--script-output-encoding", dest="scriptOutputEncoding", default="utf-8", metavar="ENCODING", help="Defines the encoding used for script output files.") parser.add_option("--xml-output-encoding", dest="xmlOutputEncoding", default="utf-8", metavar="ENCODING", help="Defines the encoding used for XML output files.") ################################################################################# # OPTIONS ################################################################################# # General options parser.add_option("-q", "--quiet", action="store_false", dest="verbose", default=False, help="Quiet output mode.") parser.add_option("-v", "--verbose", action="store_true", dest="verbose", help="Verbose output mode.") parser.add_option("--version", dest="version", default="0.0", metavar="VERSION", help="Version number of qooxdoo") parser.add_option("--package-id", dest="packageId", default="", metavar="ID", help="Defines a package ID (required for string optimization etc.)") parser.add_option("--disable-internal-check", action="store_true", dest="disableInternalCheck", default=False, help="Disable check of modifications to internal files.") # Options for source and compiled version parser.add_option("--use-setting", action="extend", dest="useSetting", type="string", metavar="NAMESPACE.KEY:VALUE", default=[], help="Define a setting.") parser.add_option("--use-variant", action="extend", dest="useVariant", type="string", metavar="NAMESPACE.KEY:VALUE", default=[], help="Optimize for the given variant.") parser.add_option("--add-new-lines", action="store_true", dest="addNewLines", default=False, help="Keep newlines in compiled files.") parser.add_option("--add-require", action="extend", dest="addRequire", metavar="CLASS1:CLASS2", type="string", default=[], help="Define that CLASS1 requires CLASS2.") parser.add_option("--add-use", action="extend", dest="addUse", metavar="CLASS1:CLASS2", type="string", default=[], help="Define that CLASS1 uses CLASS2.") # Options for compiled version parser.add_option("--add-file-ids", action="store_true", dest="addFileIds", default=False, help="Add file IDs to compiled output.") parser.add_option("--optimize-strings", action="store_true", dest="optimizeStrings", default=False, help="Optimize strings. Increase mshtml performance.") parser.add_option("--optimize-variables", action="store_true", dest="optimizeVariables", default=False, help="Optimize variables. Reducing size.") parser.add_option("--optimize-variables-skip-prefix", action="store", dest="optimizeVariablesSkipPrefix", metavar="PREFIX", default="", help="Skip optimization of variables beginning with PREFIX [default: optimize all variables].") parser.add_option("--optimize-base-call", action="store_true", dest="optimizeBaseCall", default=False, help="Optimize call to 'this.base'. Optimizing runtime of super class calls.") parser.add_option("--optimize-private", action="store_true", dest="optimizePrivate", default=False, help="Optimize private members. Reducing size and testing private.") parser.add_option("--obfuscate", action="store_true", dest="obfuscate", default=False, help="Enable obfuscation") parser.add_option("--obfuscate-accessors", action="store_true", dest="obfuscateAccessors", default=False, help="Enable accessor obfuscation") # Options for pretty printing compiler.addCommandLineOptions(parser) # Options for resource copying parser.add_option("--enable-resource-filter", action="store_true", dest="enableResourceFilter", default=False, help="Enable filtering of resource files used by classes (based on #embed).") # Options for token/tree storage parser.add_option("--token-output-directory", dest="tokenOutputDirectory", metavar="DIRECTORY", help="Define output directory for tokenizer result of the incoming JavaScript files. (Debugging)") parser.add_option("--tree-output-directory", dest="treeOutputDirectory", metavar="DIRECTORY", help="Define output directory for generated tree of the incoming JavaScript files. (Debugging)") # Cache Directory parser.add_option("--cache-directory", dest="cacheDirectory", metavar="DIRECTORY", help="If this is defined the loader trys to use cache to optimize the performance.") # Options for migration support parser.add_option("--migration-target", dest="migrationTarget", metavar="VERSION", help="Define the target for migration of source code.") parser.add_option("--migration-input", action="extend", dest="migrationInput", metavar="DIRECTORY", type="string", default=[], help="Define additional directories for to directories to migrate e.g. HTML files, ...") ################################################################################# # INCLUDE/EXCLUDE ################################################################################# # Include/Exclude parser.add_option("-i", "--include", action="extend", dest="include", metavar="ID", type="string", default=[], help="Include ID") parser.add_option("-e", "--exclude", action="extend", dest="exclude", metavar="ID", type="string", default=[], help="Exclude ID") parser.add_option("--include-without-dependencies", action="extend", dest="includePure", metavar="ID", type="string", default=[], help="Include ID") parser.add_option("--exclude-without-dependencies", action="extend", dest="excludePure", metavar="ID", type="string", default=[], help="Exclude ID") return parser def argparser(cmdlineargs): # Parse arguments parser = getparser() (options, args) = parser.parse_args(cmdlineargs) if options.generateSourceScript and ( options.obfuscateAccessors or options.optimizeStrings or options.optimizeVariables or options.optimizeVariablesSkipPrefix or options.optimizeBaseCall or options.optimizePrivate or options.obfuscate ): parser.error("The option --generate-source-script cannot be used with source code optimizations!") # Export to file if options.exportToFile != None: print print " EXPORTING:" print "----------------------------------------------------------------------------" print " * Translating options..." optionString = "# Exported configuration from build.py\n\n" ignoreValue = True lastWasKey = False for arg in cmdlineargs: if arg == "--export-to-file": ignoreValue = True elif arg.startswith("--"): if lastWasKey: optionString += "\n" optionString += arg[2:] ignoreValue = False lastWasKey = True elif arg.startswith("-"): print " - Could not export short argument: %s" % arg optionString += "\n# Ignored short argument %s\n" % arg ignoreValue = True elif not ignoreValue: optionString += " = %s\n" % arg ignoreValue = True lastWasKey = False print " * Export to file: %s" % options.exportToFile filetool.save(options.exportToFile, optionString) sys.exit(0) # Read from file elif options.fromFile != None: print print " INITIALIZATION:" print "----------------------------------------------------------------------------" print " * Reading configuration..." # Convert file content into arguments fileargs = {} fileargpos = 0 fileargid = "default" currentfileargs = [] fileargs[fileargid] = currentfileargs alternativeFormatBegin = re.compile("\s*\[\s*") alternativeFormatEnd = re.compile("\s*\]\s*=\s*") emptyLine = re.compile("^\s*$") for line in file(options.fromFile).read().split("\n"): line = line.strip() if emptyLine.match(line) or line.startswith("#") or line.startswith("//"): continue # Translating... line = alternativeFormatBegin.sub(" = ", line) line = alternativeFormatEnd.sub(":", line) # Splitting line line = line.split("=") # Extract key element key = line.pop(0).strip() # Separate packages if key == "package": fileargpos += 1 fileargid = line[0].strip() print " - Found package: %s" % fileargid currentfileargs = [] fileargs[fileargid] = currentfileargs continue currentfileargs.append("--%s" % key) if len(line) > 0: value = line[0].strip() currentfileargs.append(value) # Parse defaultargs = fileargs["default"] if len(fileargs) > 1: (fileDb, moduleDb) = load(getparser().parse_args(defaultargs)[0]) for filearg in fileargs: if filearg == "default": continue print print print print print " PACKAGE: %s" % filearg print "----------------------------------------------------------------------------" combinedargs = [] combinedargs.extend(defaultargs) combinedargs.extend(fileargs[filearg]) options = getparser().parse_args(combinedargs)[0] execute(fileDb, moduleDb, options, filearg) else: options = getparser().parse_args(defaultargs)[0] (fileDb, moduleDb) = load(options) execute(fileDb, moduleDb, options, "") else: print print " INITIALIZATION:" print "----------------------------------------------------------------------------" print " * Processing arguments..." (fileDb, moduleDb) = load(options) execute(fileDb, moduleDb, options, options.packageId) def main(): if len(sys.argv[1:]) == 0: basename = os.path.basename(sys.argv[0]) print "usage: %s [options]" % basename print "Try '%s -h' or '%s --help' to show the help message." % (basename, basename) sys.exit(1) argparser(sys.argv[1:]) def load(options): ###################################################################### # SOURCE LOADER ###################################################################### print print " SOURCE LOADER:" print "----------------------------------------------------------------------------" if options.classPath == None or len(options.classPath) == 0: if len(options.migrationInput) == 0: basename = os.path.basename(sys.argv[0]) print "You must define at least one class path!" print "usage: %s [options]" % basename print "Try '%s -h' or '%s --help' to show the help message." % (basename, basename) sys.exit(1) (fileDb, moduleDb) = loader.indexAll(options) ###################################################################### # DEBUG OUTPUT JOBS ###################################################################### if options.printFiles: print print " OUTPUT OF KNOWN FILES:" print "----------------------------------------------------------------------------" print " * These are all known files:" for fileEntry in fileDb: print " - %s (%s)" % (fileEntry, fileDb[fileEntry]["path"]) if options.printModules: print print " OUTPUT OF KNOWN MODULES:" print "----------------------------------------------------------------------------" print " * These are all known modules:" for moduleEntry in moduleDb: print " * %s" % moduleEntry for fileEntry in moduleDb[moduleEntry]: print " - %s" % fileEntry if options.printFilesWithoutModules: print print " OUTPUT OF FILES WHICH HAVE NO MODULE CONNECTION:" print "----------------------------------------------------------------------------" print " * These are all files without a module connection:" for fileEntry in fileDb: fileFound = False for moduleEntry in moduleDb: for moduleFile in moduleDb[moduleEntry]: if moduleFile == fileEntry: fileFound = True break if not fileFound: print " - %s" % fileEntry return fileDb, moduleDb def execute(fileDb, moduleDb, options, pkgid="", names=[]): ###################################################################### # SORT OF INCLUDE LIST ###################################################################### print print " GENERATE CLASS INCLUDE LIST:" print "----------------------------------------------------------------------------" sortedIncludeList = loader.getSortedList(options, fileDb, moduleDb) if options.printIncludes: print print " PRINT OF INCLUDE ORDER:" print "----------------------------------------------------------------------------" print " * The files will be included in this order:" for fileId in sortedIncludeList: print " - %s" % fileId if options.printIncludesFile: includeFile = open(options.printIncludesFile, "w") for fileId in sortedIncludeList: includeFile.write(fileId + "\n") includeFile.close() if options.printDependencies: print print " OUTPUT OF DEPENDENCIES:" print "----------------------------------------------------------------------------" print " * These are all included files with their dependencies:" for fileId in sortedIncludeList: print " - %s" % fileId if len(fileDb[fileId]["loadtimeDeps"]) > 0: print " - Loadtime: " for depEntry in fileDb[fileId]["loadtimeDeps"]: print " - %s" % depEntry if len(fileDb[fileId]["runtimeDeps"]) > 0: print " - Runtime: " for depEntry in fileDb[fileId]["runtimeDeps"]: print " - %s" % depEntry if len(fileDb[fileId]["optionalDeps"]) > 0: print " - Optional: " for depEntry in fileDb[fileId]["optionalDeps"]: print " - %s" % depEntry ###################################################################### # GRAPHVIZ OUTPUT ###################################################################### if options.depDotFile: graph.store(fileDb, sortedIncludeList, options) ###################################################################### # SOURCE MIGRATION ###################################################################### if options.migrateSource: print print " SOURCE MIGRATION:" print "----------------------------------------------------------------------------" print " * Migrate Source Code..." migrator.handle(fileDb, options, options.migrationTarget, options.migrationInput, options.verbose) # Return after migration: Ignore other jobs return ###################################################################### # GENERATION OF FIXED CODE ###################################################################### if options.fixSource: print print " FIX SOURCE CODE:" print "----------------------------------------------------------------------------" if options.verbose: print " * Fixing code..." else: print " * Fixing code: ", for fileId in sortedIncludeList: if options.verbose: print " - Reading %s" % fileId fileEntry = fileDb[fileId] filePath = fileEntry["path"] fileEncoding = fileEntry["encoding"] fileContent = filetool.read(filePath, fileEncoding) fixedContent = textutil.removeTrailingSpaces(textutil.tab2Space(textutil.any2Unix(fileContent), 2)) if fixedContent != fileContent: if options.verbose: print " - Storing modifications..." else: sys.stdout.write("!") sys.stdout.flush() filetool.save(filePath, fixedContent, fileEncoding) elif not options.verbose: sys.stdout.write(".") sys.stdout.flush() if not options.verbose: print # Return after fixing: Ignore other jobs return ###################################################################### # GENERATION OF PRETTY PRINTED CODE ###################################################################### if options.prettyPrint: print print " GENERATION OF PRETTY PRINTED CODE:" print "----------------------------------------------------------------------------" if options.verbose: print " * Pretty printing..." else: print " * Pretty printing: ", for fileId in sortedIncludeList: if options.verbose: print " - Compiling %s" % fileId else: sys.stdout.write(".") sys.stdout.flush() prettyFileContent = compiler.compile(loader.getTree(fileDb, fileId, options), options) if not prettyFileContent.endswith("\n"): prettyFileContent += "\n" filetool.save(fileDb[fileId]["path"], prettyFileContent) if not options.verbose: print # Return after pretty print: Ignore other jobs return ###################################################################### # INLINE CODE ###################################################################### inlineSourceCode = [] inlineCompiledCode = [] ###################################################################### # SUPPORT FOR VARIANTS ###################################################################### if len(options.useVariant) > 0 and not options.generateSourceScript: print print " VARIANT OPTIMIZATION:" print "----------------------------------------------------------------------------" variantMap = {} for variant in options.useVariant: keyValue = variant.split(":") if len(keyValue) != 2: print " * Error: Variants must be specified as key value pair separated by ':'!" sys.exit(1) variantMap[keyValue[0]] = keyValue[1] if options.verbose: print " * Optimizing for variant setup..." else: print " * Optimizing for variant setup: ", for fileId in sortedIncludeList: if options.verbose: print " - %s" % fileId else: sys.stdout.write(".") sys.stdout.flush() if variantoptimizer.search(loader.getTree(fileDb, fileId, options), variantMap, fileId, options.verbose): if options.verbose: print " - Modified!" if not options.verbose: print ###################################################################### # BASE CALL OPTIMIZATION ###################################################################### if options.optimizeBaseCall: print print " BASE CALL OPTIMIZATION:" print "----------------------------------------------------------------------------" if options.verbose: print " * Optimizing this.base calls..." else: print " * Optimizing this.base calls: ", counter = 0 for fileId in sortedIncludeList: if options.verbose: print " - %s" % fileId else: sys.stdout.write(".") sys.stdout.flush() counter += basecalloptimizer.patch(loader.getTree(fileDb, fileId, options)) if not options.verbose: print print " * Optimized %s calls" % counter ###################################################################### # ACCESSOR OBFUSCATION ###################################################################### if options.obfuscateAccessors: print print " ACCESSOR OBFUSCATION:" print "----------------------------------------------------------------------------" if options.verbose: print " * Obfuscating..." else: print " * Obfuscating: ", for fileId in sortedIncludeList: if options.verbose: print " - %s" % fileId else: sys.stdout.write(".") sys.stdout.flush() accessorobfuscator.process(loader.getTree(fileDb, fileId, options), options.verbose) if not options.verbose: print ###################################################################### # STRING OPTIMIZATION ###################################################################### if options.optimizeStrings: print print " STRING OPTIMIZATION:" print "----------------------------------------------------------------------------" if options.verbose: print " * Searching strings..." else: print " * Searching strings: ", stringMap = {} for fileId in sortedIncludeList: if options.verbose: print " - %s" % fileId else: sys.stdout.write(".") sys.stdout.flush() localMap = stringoptimizer.search(loader.getTree(fileDb, fileId, options), options.verbose) for value in localMap: if value in stringMap: stringMap[value] += localMap[value] else: stringMap[value] = localMap[value] if not options.verbose: print counter = 0 for value in stringMap: counter += stringMap[value] stringList = stringoptimizer.sort(stringMap) print " * Found %s string instances (%s unique)" % (counter, len(stringMap)) if options.verbose: print " * Replacing strings..." else: print " * Replacing strings: ", for fileId in sortedIncludeList: if options.verbose: print " - %s" % fileId else: sys.stdout.write(".") sys.stdout.flush() stringoptimizer.replace(loader.getTree(fileDb, fileId, options), stringList, "$" + pkgid, options.verbose) if not options.verbose: print print " * Generating replacement..." inlineCompiledCode.append(stringoptimizer.replacement(stringList, "$" + pkgid)) ###################################################################### # LOCAL VARIABLE OPTIMIZATION ###################################################################### if options.optimizeVariables or options.obfuscate: print print " LOCAL VARIABLE OPTIMIZATION:" print "----------------------------------------------------------------------------" if options.verbose: print " * Optimizing variables..." else: print " * Optimizing variables: ", counter = 0 for fileId in sortedIncludeList: if options.verbose: print " - %s" % fileId else: sys.stdout.write(".") sys.stdout.flush() counter += variableoptimizer.search( loader.getTree(fileDb, fileId, options), [], 0, 0, "$", skipPrefix = options.optimizeVariablesSkipPrefix, verbose = options.verbose ) if not options.verbose: print print " * Optimized %s variables" % counter ###################################################################### # PRIVATE MEMBER OPTIMIZATION ###################################################################### if options.optimizePrivate: print print " PRIVATE MEMBER OPTIMIZATION:" print "----------------------------------------------------------------------------" if options.verbose: print " * Optimizing private members..." else: print " * Optimizing private members: ", counter = 0 for fileId in sortedIncludeList: if options.verbose: print " - %s" % fileId else: sys.stdout.write(".") sys.stdout.flush() counter += privateoptimizer.patch("",loader.getTree(fileDb, fileId, options), {}, "$", options.verbose) if not options.verbose: print print " * Optimized %s keys" % counter ###################################################################### # OBFUSCATION ###################################################################### if options.obfuscate: print print " OBFUSCATION:" print "----------------------------------------------------------------------------" if options.verbose: print " * Searching for assignments..." else: print " * Searching for assignments: ", identifiers = {} for fileId in sortedIncludeList: if options.verbose: print " - %s" % fileId else: sys.stdout.write(".") sys.stdout.flush() obfuscator.search(loader.getTree(fileDb, fileId, options), identifiers, options.verbose) for fileId in sortedIncludeList: if options.verbose: print " - %s" % fileId else: sys.stdout.write(".") sys.stdout.flush() obfuscator.patch(loader.getTree(fileDb, fileId, options), identifiers, options.verbose) if not options.verbose: print ###################################################################### # TOKEN STORAGE ###################################################################### if options.storeTokens: print print " TOKEN STORAGE:" print "----------------------------------------------------------------------------" if options.tokenOutputDirectory == None: print " * You must define the token output directory!" sys.exit(1) if options.verbose: print " * Storing tokens..." else: print " * Storing tokens: ", for fileId in sortedIncludeList: tokenString = tokenizer.convertTokensToString(loader.getTokens(fileDb, fileId, options)) if options.verbose: print " * Writing tokens for %s (%s KB)..." % (fileIdm, len(tokenString) / 1000.0) else: sys.stdout.write(".") sys.stdout.flush() filetool.save(os.path.join(filetool.normalize(options.tokenOutputDirectory), fileId + config.TOKENEXT), tokenString) if not options.verbose: print ###################################################################### # TREE STORAGE ###################################################################### if options.storeTree: print print " TREE STORAGE:" print "----------------------------------------------------------------------------" if options.treeOutputDirectory == None: print " * You must define the tree output directory!" sys.exit(1) if options.verbose: print " * Storing tree..." else: print " * Storing tree: ", for fileId in sortedIncludeList: treeString = "\n" + tree.nodeToXmlString(loader.getTree(fileDb, fileId, options)) if options.verbose: print " * Writing tree for %s (%s KB)..." % (fileId, len(treeString) / 1000.0) else: sys.stdout.write(".") sys.stdout.flush() filetool.save(os.path.join(filetool.normalize(options.treeOutputDirectory), fileId + config.XMLEXT), treeString) if not options.verbose: print ###################################################################### # GENERATION OF API ###################################################################### if options.generateApiDocumentation: print print " GENERATION OF API:" print "----------------------------------------------------------------------------" if options.apiDocumentationJsonFile == None and options.apiDocumentationXmlFile == None: print " * You must define one of JSON or XML API documentation file!" docTree = None if options.verbose: print " * Generating API tree..." else: print " * Generating API tree: ", hasDocError = False for fileId in sortedIncludeList: if options.verbose: print " - %s" % fileId else: sys.stdout.write(".") sys.stdout.flush() (docTree, error) = api.createDoc(loader.getTree(fileDb, fileId, options), docTree) hasDocError = hasDocError or error if hasDocError: print print " * Building API failed!!" sys.exit(0) if not options.verbose: print if docTree: print " * Finalizing tree..." api.postWorkPackage(docTree, docTree) if options.addNewLines: childPrefix = " " newLine = "\n" else: childPrefix = "" newLine = "" if options.apiDocumentationXmlFile != None: print " * Writing XML API file to %s" % options.apiDocumentationXmlFile if options.apiSeparateFiles: packages = api.packagesToXmlString(docTree, "", childPrefix, newLine) filetool.save(options.apiDocumentationXmlFile, packages, options.scriptOutputEncoding) for cls in api.classNodeIterator(docTree): classContent = "\n" classContent += tree.nodeToXmlString(cls, "", childPrefix, newLine) fileName = os.path.join(os.path.dirname(options.apiDocumentationXmlFile), cls.get("fullName") + ".xml") filetool.save(fileName, classContent, options.xmlOutputEncoding) else: xmlContent = "\n" xmlContent += tree.nodeToXmlString(docTree, "", childPrefix, newLine) filetool.save(options.apiDocumentationXmlFile, xmlContent, options.xmlOutputEncoding) if options.apiDocumentationJsonFile != None: print " * Writing JSON API file to %s" % options.apiDocumentationJsonFile if options.apiSeparateFiles: packages = api.packagesToJsonString(docTree, "", childPrefix, newLine) filetool.save(options.apiDocumentationJsonFile, packages, options.scriptOutputEncoding) for cls in api.classNodeIterator(docTree): classContent = tree.nodeToJsonString(cls, "", childPrefix, newLine) fileName = os.path.join(os.path.dirname(options.apiDocumentationJsonFile), cls.get("fullName") + ".js") filetool.save(fileName, classContent, options.scriptOutputEncoding) else: jsonContent = tree.nodeToJsonString(docTree, "", childPrefix, newLine) filetool.save(options.apiDocumentationJsonFile, jsonContent, options.scriptOutputEncoding) # create search index if options.apiDocumentationIndexFile != None: print " * Generating API index..." jsonContent = tree.nodeToIndexString(docTree, "", childPrefix, newLine) print " * Writing API search index to %s" % options.apiDocumentationIndexFile filetool.save(options.apiDocumentationIndexFile, jsonContent, options.scriptOutputEncoding) ###################################################################### # CREATE COPY OF RESOURCES ###################################################################### if options.copyResources: print print " CREATE COPY OF RESOURCES:" print "----------------------------------------------------------------------------" resources.copy(options, sortedIncludeList, fileDb) ###################################################################### # GENERATION OF SETTINGS ###################################################################### if options.generateSourceScript or options.generateCompiledScript: print print " INCLUSION OF SETTINGS:" print "----------------------------------------------------------------------------" if options.generateSourceScript: print " * Processing settings of source version..." settingsArr = options.useSetting[:] settingsArr.append("qx.version:%s" % options.version) settingsArr.append("qx.isSource:true") inlineSourceCode.append(settings.generate(settingsArr, options.addNewLines)) if options.generateCompiledScript: print " * Processing settings of compiled version..." settingsArr = options.useSetting[:] settingsArr.append("qx.version:%s" % options.version) settingsArr.append("qx.isSource:false") inlineCompiledCode.append(settings.generate(settingsArr, options.addNewLines)) ###################################################################### # GENERATION OF VARIANTS ###################################################################### if options.generateSourceScript or options.generateCompiledScript: print print " INCLUSION OF VARIANTS:" print "----------------------------------------------------------------------------" if options.generateSourceScript: print " * Processing variants of source version..." variantsArr = options.useVariant[:] inlineSourceCode.append(variants.generate(variantsArr, options.addNewLines)) if options.generateCompiledScript: print " * Processing variants of compiled version..." variantsArr = options.useVariant[:] inlineCompiledCode.append(variants.generate(variantsArr, options.addNewLines)) ###################################################################### # GENERATION OF SOURCE VERSION ###################################################################### if options.generateSourceScript: print print " GENERATION OF SOURCE SCRIPT:" print "----------------------------------------------------------------------------" if options.sourceScriptFile == None and (options.sourceTemplateInputFile == None or options.sourceTemplateOutputFile == None): print " * You must define at least one source script file or template input/output." sys.exit(1) if options.sourceScriptFile: options.sourceScriptFile = os.path.normpath(options.sourceScriptFile) if options.sourceTemplateInputFile: options.sourceTemplateInputFile = os.path.normpath(options.sourceTemplateInputFile) if options.sourceTemplateOutputFile: options.sourceTemplateOutputFile = os.path.normpath(options.sourceTemplateOutputFile) print " * Generating script block..." # Handling line feed setting sourceLineFeed = ""; if options.addNewLines: sourceLineFeed = "\n"; # Generating script block scriptBlocks = "" scriptBlocks += '' % "".join(inlineSourceCode) for fileId in sortedIncludeList: if fileDb[fileId]["meta"]: continue if fileDb[fileId]["classUri"] == None: print " * Missing class URI definition for class path %s." % fileDb[fileId]["classPath"] sys.exit(1) scriptBlocks += '' % (os.path.join(fileDb[fileId]["classUri"], fileDb[fileId]["pathId"].replace(".", '/')), config.JSEXT) scriptBlocks += sourceLineFeed # Writing includer if options.sourceScriptFile != None: print " * Storing includer as %s..." % options.sourceScriptFile sourceScript = "document.write('%s');" % scriptBlocks.replace("'", "\\'") if options.addNewLines: sourceScript = sourceScript.replace("\n", "\\\n") filetool.save(options.sourceScriptFile, sourceScript, options.scriptOutputEncoding) # Patching template if options.sourceTemplateInputFile != None and options.sourceTemplateOutputFile != None: print " * Patching template: %s => %s" % (options.sourceTemplateInputFile, options.sourceTemplateOutputFile) tmpl = filetool.read(options.sourceTemplateInputFile) res = tmpl.replace(options.sourceTemplateReplace, scriptBlocks) filetool.save(options.sourceTemplateOutputFile, res, options.scriptOutputEncoding) ###################################################################### # GENERATION OF COMPILED VERSION ###################################################################### if options.generateCompiledScript: print print " GENERATION OF COMPILED SCRIPT:" print "----------------------------------------------------------------------------" buildLineFeed = ""; if options.addNewLines: buildLineFeed = "\n"; compiledOutput = "".join(inlineCompiledCode) if options.compiledScriptFile == None: print " * You must define the compiled script file!" sys.exit(1) if options.verbose: print " * Compiling..." else: print " * Compiling: ", for fileId in sortedIncludeList: if fileDb[fileId]["meta"]: continue if options.verbose: print " - Compiling %s" % fileId else: sys.stdout.write(".") sys.stdout.flush() if options.prettyPrint: options.prettyPrint = False # make sure it's disabled compiledFileContent = compiler.compile(loader.getTree(fileDb, fileId, options), options, options.addNewLines, options.verbose) if options.addFileIds: compiledOutput += "\n\n\n/* ID: " + fileId + " */\n" + compiledFileContent + "\n" else: compiledOutput += compiledFileContent if not compiledOutput.endswith(";") and not compiledOutput.endswith("\n"): compiledOutput += ";" if not options.verbose: print print " * Storing output as %s..." % options.compiledScriptFile filetool.save(options.compiledScriptFile, compiledOutput, options.scriptOutputEncoding) ###################################################################### # MAIN LOOP ###################################################################### if __name__ == '__main__': try: main() except KeyboardInterrupt: print print " * Keyboard Interrupt" sys.exit(1)