package; //import openfl.text.Font; //import openfl.utils.ByteArray; //import openfl.utils.CompressionAlgorithm; import haxe.Json; import haxe.Serializer; import haxe.Unserializer; import haxe.io.Path; import haxe.rtti.Meta; import lime.system.CFFI; import lime.tools.helpers.*; import lime.tools.platforms.*; import lime.project.*; import sys.io.File; import sys.io.Process; import sys.FileSystem; import utils.publish.*; import utils.CreateTemplate; import utils.JavaExternGenerator; import utils.PlatformSetup; class CommandLineTools { public static var commandName = "lime"; public static var defaultLibrary = "lime"; public static var defaultLibraryName = "Lime"; private var additionalArguments:Array ; private var command:String; private var debug:Bool; private var includePaths:Array ; private var overrides:HXProject; private var project:HXProject; private var projectDefines:Map ; private var targetFlags:Map ; private var traceEnabled:Bool; private var userDefines:Map ; private var version:String; private var words:Array ; public function new () { additionalArguments = new Array (); command = ""; debug = false; includePaths = new Array (); projectDefines = new Map (); targetFlags = new Map (); traceEnabled = true; userDefines = new Map (); words = new Array (); overrides = new HXProject (); overrides.architectures = []; PathHelper.haxelibOverrides.set ("lime-tools", PathHelper.combine (PathHelper.getHaxelib (new Haxelib ("lime")), "tools")); processArguments (); version = getVersion (); if (targetFlags.exists ("openfl")) { LogHelper.accentColor = "\x1b[36;1m"; commandName = "openfl"; defaultLibrary = "openfl"; defaultLibraryName = "OpenFL"; } if (LogHelper.verbose && command != "") { displayInfo (); Sys.println (""); } switch (command) { case "": displayInfo (true); case "help": displayHelp (); case "setup": platformSetup (); case "document": document (); case "generate": generate (); case "compress": compress (); case "create": createTemplate (); case "install", "remove", "upgrade": updateLibrary (); case "clean", "update", "display", "build", "run", "rerun", /*"install",*/ "uninstall", "trace", "test", "deploy": if (words.length < 1 || words.length > 2) { LogHelper.error ("Incorrect number of arguments for command '" + command + "'"); return; } var project = initializeProject (); buildProject (project); case "rebuild": if (words.length < 1 || words.length > 2) { LogHelper.error ("Incorrect number of arguments for command '" + command + "'"); return; } if (words.length < 2) { if (targetFlags.exists ("openfl")) { words.unshift ("openfl"); } else { words.unshift ("lime"); } } var targets = words[1].split (","); var haxelib = null; var path = null; var project = null; if (!FileSystem.exists (words[0])) { if (FileSystem.exists (PathHelper.tryFullPath (words[0]))) { path = PathHelper.combine (PathHelper.tryFullPath (words[0]), "project"); } else { haxelib = new Haxelib (words[0]); } } else { if (FileSystem.isDirectory (words[0])) { if (FileSystem.exists (PathHelper.combine (words[0], "Build.xml"))) { path = words[0]; } else { path = PathHelper.combine (words[0], "project/Build.xml"); } } else { path = words[0]; } var haxelibPath = PathHelper.getHaxelib (new Haxelib (words[0])); if (!FileSystem.exists (path) && haxelibPath != null) { haxelib = new Haxelib (words[0]); } } if (haxelib != null) { PathHelper.getHaxelib (haxelib, true); } for (targetName in targets) { var target = null; switch (targetName) { case "cpp": target = PlatformHelper.hostPlatform; targetFlags.set ("cpp", ""); case "neko": target = PlatformHelper.hostPlatform; targetFlags.set ("neko", ""); case "nodejs": target = PlatformHelper.hostPlatform; targetFlags.set ("nodejs", ""); case "cs": target = PlatformHelper.hostPlatform; targetFlags.set ("cs", ""); case "iphone", "iphoneos": target = Platform.IOS; case "iphonesim": target = Platform.IOS; targetFlags.set ("simulator", ""); case "firefox", "firefoxos": target = Platform.FIREFOX; overrides.haxedefs.set ("firefoxos", ""); case "appletv", "appletvos": target = Platform.TVOS; case "appletvsim": target = Platform.TVOS; targetFlags.set ("simulator", ""); case "mac", "macos": target = Platform.MAC; default: target = cast targetName.toLowerCase (); } HXProject._command = command; HXProject._debug = debug; HXProject._target = target; HXProject._targetFlags = targetFlags; var project = null; if (haxelib != null) { userDefines.set ("rebuild", 1); project = HXProject.fromHaxelib (haxelib, userDefines); if (project == null) { project = new HXProject (); project.config.set ("project.rebuild.path", PathHelper.combine (PathHelper.getHaxelib (haxelib), "project")); } else { project.config.set ("project.rebuild.path", PathHelper.combine (PathHelper.getHaxelib (haxelib), project.config.get ("project.rebuild.path"))); } } else { //project = HXProject.fromPath (path); if (project == null) { project = new HXProject (); if (FileSystem.isDirectory (path)) { project.config.set ("project.rebuild.path", path); } else { project.config.set ("project.rebuild.path", Path.directory (path)); project.config.set ("project.rebuild.file", Path.withoutDirectory (path)); } } } // this needs to be improved var rebuildPath = project.config.get ("project.rebuild.path"); var rebuildFile = project.config.get ("project.rebuild.file"); project.merge (overrides); for (haxelib in overrides.haxelibs) { var includeProject = HXProject.fromHaxelib (haxelib, project.defines); if (includeProject != null) { for (ndll in includeProject.ndlls) { if (ndll.haxelib == null) { ndll.haxelib = haxelib; } } project.merge (includeProject); } } project.config.set ("project.rebuild.path", rebuildPath); project.config.set ("project.rebuild.file", rebuildFile); initializeProject (project, targetName); buildProject (project); if (LogHelper.verbose) { LogHelper.println (""); } } case "publish": if (words.length < 1 || words.length > 2) { LogHelper.error ("Incorrect number of arguments for command '" + command + "'"); return; } publishProject (); case "installer", "copy-if-newer": // deprecated? default: LogHelper.error ("'" + command + "' is not a valid command"); } } #if (neko && (haxe_210 || haxe3)) public static function __init__ ():Void { var args = Sys.args (); if (args.length > 0 && args[0].toLowerCase () == "rebuild") { CFFI.enabled = false; } for (arg in args) { if (arg == "-nocffi" || arg == "-rebuild") { CFFI.enabled = false; } } var process = new Process ("haxelib", [ "path", "lime" ]); var path = ""; var lines = new Array (); try { while (true) { var length = lines.length; var line = StringTools.trim (process.stdout.readLine ()); if (length > 0 && (line == "-D lime" || StringTools.startsWith (line, "-D lime="))) { path = StringTools.trim (lines[length - 1]); } lines.push (line); } } catch (e:Dynamic) { } if (path == "") { for (line in lines) { if (line != "" && line.substr (0, 1) != "-") { try { if (FileSystem.exists (line)) { path = line; } } catch (e:Dynamic) {} } } } if (path == "") { if (FileSystem.exists ("tools.n")) { path = PathHelper.combine (Sys.getCwd (), "../"); } else if (FileSystem.exists ("run.n")) { path = Sys.getCwd (); } } process.close (); path += "/ndll/"; switch (PlatformHelper.hostPlatform) { case WINDOWS: untyped $loader.path = $array (path + "Windows/", $loader.path); case MAC: //if (PlatformHelper.hostArchitecture == Architecture.X64) { untyped $loader.path = $array (path + "Mac64/", $loader.path); //} else { // untyped $loader.path = $array (path + "Mac/", $loader.path); //} case LINUX: var arguments = Sys.args (); var raspberryPi = false; for (argument in arguments) { if (argument == "-rpi") raspberryPi = true; } if (raspberryPi || PlatformHelper.hostArchitecture == Architecture.ARMV6 || PlatformHelper.hostArchitecture == Architecture.ARMV7) { untyped $loader.path = $array (path + "RPi/", $loader.path); } else if (PlatformHelper.hostArchitecture == Architecture.X64) { untyped $loader.path = $array (path + "Linux64/", $loader.path); } else { untyped $loader.path = $array (path + "Linux/", $loader.path); } default: } } #end private function buildProject (project:HXProject, command:String = "") { if (command == "") { command = project.command.toLowerCase (); } if (project.targetHandlers.exists (Std.string (project.target))) { if (command == "build" || command == "test") { CommandHelper.executeCommands (project.preBuildCallbacks); } LogHelper.info ("", LogHelper.accentColor + "Using target platform: " + Std.string (project.target).toUpperCase () + "\x1b[0m"); var handler = project.targetHandlers.get (Std.string (project.target)); var projectData = Serializer.run (project); var temporaryFile = PathHelper.getTemporaryFile (); File.saveContent (temporaryFile, projectData); var targetDir = PathHelper.getHaxelib (new Haxelib (handler)); var exePath = Path.join ([targetDir, "run.exe"]); var exeExists = FileSystem.exists (exePath); var args = [ command, temporaryFile ]; if (LogHelper.verbose) args.push ("-verbose"); if (!LogHelper.enableColor) args.push ("-nocolor"); if (!traceEnabled) args.push ("-notrace"); if (additionalArguments.length > 0) { args.push ("-args"); args = args.concat (additionalArguments); } if (exeExists) { ProcessHelper.runCommand ("", exePath, args); } else { ProcessHelper.runCommand ("", "haxelib", [ "run", handler ].concat (args)); } try { FileSystem.deleteFile (temporaryFile); } catch (e:Dynamic) {} if (command == "build" || command == "test") { CommandHelper.executeCommands (project.postBuildCallbacks); } } else { var platform:PlatformTarget = null; switch (project.target) { case ANDROID: platform = new AndroidPlatform (command, project, targetFlags); case BLACKBERRY: //platform = new BlackBerryPlatform (command, project, targetFlags); case IOS: platform = new IOSPlatform (command, project, targetFlags); case TIZEN: //platform = new TizenPlatform (command, project, targetFlags); case WEBOS: //platform = new WebOSPlatform (command, project, targetFlags); case WINDOWS: platform = new WindowsPlatform (command, project, targetFlags); case MAC: platform = new MacPlatform (command, project, targetFlags); case LINUX: platform = new LinuxPlatform (command, project, targetFlags); case FLASH: platform = new FlashPlatform (command, project, targetFlags); case HTML5: platform = new HTML5Platform (command, project, targetFlags); case FIREFOX: platform = new FirefoxPlatform (command, project, targetFlags); case EMSCRIPTEN: platform = new EmscriptenPlatform (command, project, targetFlags); case TVOS: platform = new TVOSPlatform (command, project, targetFlags); default: } if (platform != null) { platform.traceEnabled = traceEnabled; platform.execute (additionalArguments); } else { LogHelper.error ("\"" + Std.string (project.target) + "\" is an unknown target"); } } } private function compress () { if (words.length > 0) { //var bytes = new ByteArray (); //bytes.writeUTFBytes (words[0]); //bytes.compress (CompressionAlgorithm.LZMA); //Sys.print (bytes.toString ()); //File.saveBytes (words[0] + ".compress", bytes); } } private function createTemplate () { LogHelper.info ("", LogHelper.accentColor + "Running command: CREATE\x1b[0m"); if (words.length > 0) { var colonIndex = words[0].indexOf (":"); var projectName = null; var sampleName = null; if (colonIndex == -1) { projectName = words[0]; if (words.length > 1) { sampleName = words[1]; } } else { projectName = words[0].substring (0, colonIndex); sampleName = words[0].substr (colonIndex + 1); } if (projectName == "project" || sampleName == "project") { CreateTemplate.createProject (words, userDefines, overrides); } else if (projectName == "extension" || sampleName == "extension") { CreateTemplate.createExtension (words, userDefines); } else { if (sampleName == null) { var sampleExists = false; var defines = new Map (); defines.set ("create", 1); var project = HXProject.fromHaxelib (new Haxelib (defaultLibrary), defines); for (samplePath in project.samplePaths) { if (FileSystem.exists (PathHelper.combine (samplePath, projectName))) { sampleExists = true; } } if (sampleExists) { CreateTemplate.createSample (words, userDefines); } else if (PathHelper.getHaxelib (new Haxelib (projectName)) != "") { CreateTemplate.listSamples (projectName, userDefines); } else if (projectName == "" || projectName == null) { CreateTemplate.listSamples (defaultLibrary, userDefines); } else { CreateTemplate.listSamples (null, userDefines); } } else { CreateTemplate.createSample (words, userDefines); } } } else { CreateTemplate.listSamples (defaultLibrary, userDefines); } } private function displayHelp ():Void { displayInfo (); LogHelper.println (""); LogHelper.println (" " + LogHelper.accentColor + "Usage:\x1b[0m \x1b[1m" + commandName + "\x1b[0m setup \x1b[3;37m(target)\x1b[0m"); LogHelper.println (" " + LogHelper.accentColor + "Usage:\x1b[0m \x1b[1m" + commandName + "\x1b[0m clean|update|build|run|test|display \x1b[3;37m\x1b[0m (target) \x1b[3;37m[options]\x1b[0m"); LogHelper.println (" " + LogHelper.accentColor + "Usage:\x1b[0m \x1b[1m" + commandName + "\x1b[0m create (template) \x1b[3;37m(directory)\x1b[0m"); LogHelper.println (" " + LogHelper.accentColor + "Usage:\x1b[0m \x1b[1m" + commandName + "\x1b[0m rebuild (target)\x1b[3;37m,(target),...\x1b[0m"); LogHelper.println (" " + LogHelper.accentColor + "Usage:\x1b[0m \x1b[1m" + commandName + "\x1b[0m install|remove|upgrade "); LogHelper.println (" " + LogHelper.accentColor + "Usage:\x1b[0m \x1b[1m" + commandName + "\x1b[0m help"); LogHelper.println (""); LogHelper.println (" " + LogHelper.accentColor + "Commands:" + LogHelper.resetColor); LogHelper.println (""); LogHelper.println (" \x1b[1msetup\x1b[0m -- Setup " + defaultLibraryName + " or a specific platform"); LogHelper.println (" \x1b[1mclean\x1b[0m -- Remove the target build directory if it exists"); LogHelper.println (" \x1b[1mupdate\x1b[0m -- Copy assets for the specified project/target"); LogHelper.println (" \x1b[1mbuild\x1b[0m -- Compile and package for the specified project/target"); LogHelper.println (" \x1b[1mrun\x1b[0m -- Install and run for the specified project/target"); LogHelper.println (" \x1b[1mtest\x1b[0m -- Update, build and run in one command"); LogHelper.println (" \x1b[1mdeploy\x1b[0m -- Archive and upload builds"); LogHelper.println (" \x1b[1mcreate\x1b[0m -- Create a new project or extension using templates"); LogHelper.println (" \x1b[1mrebuild\x1b[0m -- Recompile native binaries for libraries"); LogHelper.println (" \x1b[1mdisplay\x1b[0m -- Display information for the specified project/target"); LogHelper.println (" \x1b[1minstall\x1b[0m -- Install a library from haxelib, plus dependencies"); LogHelper.println (" \x1b[1mremove\x1b[0m -- Remove a library from haxelib"); LogHelper.println (" \x1b[1mupgrade\x1b[0m -- Upgrade a library from haxelib"); LogHelper.println (" \x1b[1mhelp\x1b[0m -- Show this information"); LogHelper.println (""); LogHelper.println (" " + LogHelper.accentColor + "Targets:" + LogHelper.resetColor); LogHelper.println (""); LogHelper.println (" \x1b[1mandroid\x1b[0m -- Create an Android application"); LogHelper.println (" \x1b[1mblackberry\x1b[0m -- Create a BlackBerry application"); LogHelper.println (" \x1b[1memscripten\x1b[0m -- Create an Emscripten application"); LogHelper.println (" \x1b[1mflash\x1b[0m -- Create a Flash SWF application"); LogHelper.println (" \x1b[1mhtml5\x1b[0m -- Create an HTML5 canvas application"); LogHelper.println (" \x1b[1mios\x1b[0m -- Create an iOS application"); LogHelper.println (" \x1b[1mlinux\x1b[0m -- Create a Linux application"); LogHelper.println (" \x1b[1mmac\x1b[0m -- Create a Mac OS X application"); LogHelper.println (" \x1b[1mtizen\x1b[0m -- Create a Tizen application"); LogHelper.println (" \x1b[1mtvos\x1b[0m -- Create a tvOS application"); LogHelper.println (" \x1b[1mwebos\x1b[0m -- Create a webOS application"); LogHelper.println (" \x1b[1mwindows\x1b[0m -- Create a Windows application"); LogHelper.println (""); LogHelper.println (" " + LogHelper.accentColor + "Options:" + LogHelper.resetColor); LogHelper.println (""); LogHelper.println (" \x1b[1m-D\x1b[0;3mvalue\x1b[0m -- Specify a define to use when processing other commands"); LogHelper.println (" \x1b[1m-debug\x1b[0m -- Use debug configuration instead of release"); LogHelper.println (" \x1b[1m-verbose\x1b[0m -- Print additional information (when available)"); LogHelper.println (" \x1b[1m-clean\x1b[0m -- Add a \"clean\" action before running the current command"); LogHelper.println (" \x1b[1m-nocolor\x1b[0m -- Disable ANSI format codes in output"); LogHelper.println (" \x1b[1m-xml\x1b[0m -- Generate XML type information, useful for documentation"); LogHelper.println (" \x1b[1m-args\x1b[0m ... -- Add additional arguments when using \"run\" or \"test\""); LogHelper.println (" \x1b[3m(windows|mac|linux)\x1b[0m \x1b[1m-neko\x1b[0m -- Build with Neko instead of C++"); LogHelper.println (" \x1b[3m(mac|linux)\x1b[0m \x1b[1m-32\x1b[0m -- Compile for 32-bit instead of the OS default"); LogHelper.println (" \x1b[3m(mac|linux)\x1b[0m \x1b[1m-64\x1b[0m -- Compile for 64-bit instead of the OS default"); LogHelper.println (" \x1b[3m(ios|blackberry|tizen|tvos|webos)\x1b[0m \x1b[1m-simulator\x1b[0m -- Target the device simulator"); LogHelper.println (" \x1b[3m(ios)\x1b[0m \x1b[1m-simulator -ipad\x1b[0m -- Build/test for the iPad Simulator"); LogHelper.println (" \x1b[3m(android)\x1b[0m \x1b[1m-emulator\x1b[0m -- Target the device emulator"); LogHelper.println (" \x1b[3m(html5)\x1b[0m \x1b[1m-minify\x1b[0m -- Minify output using the Google Closure compiler"); LogHelper.println (" \x1b[3m(html5)\x1b[0m \x1b[1m-minify -yui\x1b[0m -- Minify output using the YUI compressor"); LogHelper.println (" \x1b[3m(flash)\x1b[0m \x1b[1m-web\x1b[0m -- Make html page with embeded swf using the SWFObject js library"); LogHelper.println (""); LogHelper.println (" " + LogHelper.accentColor + "Project Overrides:" + LogHelper.resetColor); LogHelper.println (""); LogHelper.println (" \x1b[1m--app-\x1b[0;3moption=value\x1b[0m -- Override a project setting"); LogHelper.println (" \x1b[1m--meta-\x1b[0;3moption=value\x1b[0m -- Override a project setting"); LogHelper.println (" \x1b[1m--window-\x1b[0;3moption=value\x1b[0m -- Override a project setting"); LogHelper.println (" \x1b[1m--dependency\x1b[0;3m=value\x1b[0m -- Add an additional value"); LogHelper.println (" \x1b[1m--haxedef\x1b[0;3m=value\x1b[0m -- Add an additional value"); LogHelper.println (" \x1b[1m--haxeflag\x1b[0;3m=value\x1b[0m -- Add an additional value"); LogHelper.println (" \x1b[1m--haxelib\x1b[0;3m=value\x1b[0m -- Add an additional value"); LogHelper.println (" \x1b[1m--haxelib-\x1b[0;3mname=value\x1b[0m -- Override the path to a haxelib"); LogHelper.println (" \x1b[1m--source\x1b[0;3m=value\x1b[0m -- Add an additional value"); LogHelper.println (" \x1b[1m--certificate-\x1b[0;3moption=value\x1b[0m -- Override a project setting"); } private function displayInfo (showHint:Bool = false):Void { if (PlatformHelper.hostPlatform == Platform.WINDOWS) { LogHelper.println (""); } if (targetFlags.exists ("openfl")) { LogHelper.println ("\x1b[37m .d88 88b. \x1b[0m\x1b[1;36m888888b 888 \x1b[0m"); LogHelper.println ("\x1b[37md88P\" \"Y88b \x1b[0m\x1b[1;36m888 888 \x1b[0m"); LogHelper.println ("\x1b[37m888 888 \x1b[0m\x1b[1;36m888 888 \x1b[0m"); LogHelper.println ("\x1b[37m888 888 88888b. .d88b. 88888b. \x1b[0m\x1b[1;36m8888888 888 \x1b[0m"); LogHelper.println ("\x1b[37m888 888 888 \"88b d8P Y8b 888 \"88b \x1b[0m\x1b[1;36m888 888 \x1b[0m"); LogHelper.println ("\x1b[37m888 888 888 888 88888888 888 888 \x1b[0m\x1b[1;36m888 888 \x1b[0m"); LogHelper.println ("\x1b[37mY88b. .d88P 888 d88P Y8b. 888 888 \x1b[0m\x1b[1;36m888 888 \x1b[0m"); LogHelper.println ("\x1b[37m \"Y88 88P\" 88888P\" \"Y8888 888 888 \x1b[0m\x1b[1;36m888 \"Y888P \x1b[0m"); LogHelper.println ("\x1b[37m 888 "); LogHelper.println ("\x1b[37m 888 \x1b[0m"); LogHelper.println (""); LogHelper.println ("\x1b[1mOpenFL Command-Line Tools\x1b[0;1m (" + getVersion (new Haxelib ("openfl")) + "-L" + StringHelper.generateUUID (5, null, StringHelper.generateHashCode (version)) + ")\x1b[0m"); } else { LogHelper.println ("\x1b[32;1m ___ \x1b[0m"); LogHelper.println ("\x1b[32m/\x1b[1m\\_ \\ __ \x1b[0m"); LogHelper.println ("\x1b[32m\\//\x1b[1m\\ \\ \x1b[0m\x1b[32m/\x1b[1m\\\x1b[0m\x1b[32m_\x1b[1m\\ ___ ___ __ \x1b[0m"); LogHelper.println ("\x1b[32m \\ \x1b[1m\\ \\ \x1b[0m\x1b[32m\\/\x1b[1m\\ \\ /' __` __`\\ /'__`\\ \x1b[0m"); LogHelper.println ("\x1b[32m \\\x1b[1m_\\ \\_\x1b[0m\x1b[32m\\ \x1b[1m\\ \\\x1b[0m\x1b[32m/\x1b[1m\\ \\\x1b[0m\x1b[32m/\x1b[1m\\ \\\x1b[0m\x1b[32m/\x1b[1m\\ \\\x1b[0m\x1b[32m/\x1b[1m\\ __/ \x1b[0m"); LogHelper.println ("\x1b[32m /\x1b[1m\\____\\\x1b[0m\x1b[32m\\ \x1b[1m\\_\\ \\_\\ \\_\\ \\_\\ \\____\\\x1b[0m"); LogHelper.println ("\x1b[32m \\/____/ \\/_/\\/_/\\/_/\\/_/\\/____/\x1b[0m"); LogHelper.println (""); LogHelper.println ("\x1b[1mLime Command-Line Tools\x1b[0;1m (" + version + ")\x1b[0m"); } if (showHint) { LogHelper.println ("Use \x1b[3m" + commandName + " setup\x1b[0m to configure platforms or \x1b[3m" + commandName + " help\x1b[0m for more commands"); } } private function document ():Void { } private function findProjectFile (path:String):String { if (FileSystem.exists (PathHelper.combine (path, "project.hxp"))) { return PathHelper.combine (path, "project.hxp"); } else if (FileSystem.exists (PathHelper.combine (path, "project.lime"))) { return PathHelper.combine (path, "project.lime"); } else if (FileSystem.exists (PathHelper.combine (path, "project.nmml"))) { return PathHelper.combine (path, "project.nmml"); } else if (FileSystem.exists (PathHelper.combine (path, "project.xml"))) { return PathHelper.combine (path, "project.xml"); } else { var files = FileSystem.readDirectory (path); var matches = new Map > (); matches.set ("hxp", []); matches.set ("lime", []); matches.set ("nmml", []); matches.set ("xml", []); for (file in files) { var path = PathHelper.combine (path, file); if (FileSystem.exists (path) && !FileSystem.isDirectory (path)) { var extension = Path.extension (file); if ((extension == "lime" && file != "include.lime") || (extension == "nmml" && file != "include.nmml") || (extension == "xml" && file != "include.xml") || extension == "hxp") { matches.get (extension).push (path); } } } if (matches.get ("hxp").length > 0) { return matches.get ("hxp")[0]; } if (matches.get ("lime").length > 0) { return matches.get ("lime")[0]; } if (matches.get ("nmml").length > 0) { return matches.get ("nmml")[0]; } if (matches.get ("xml").length > 0) { return matches.get ("xml")[0]; } } return ""; } private function generate ():Void { if (targetFlags.exists ("font-hash")) { var sourcePath = words[0]; var glyphs = "32-255"; ProcessHelper.runCommand (Path.directory (sourcePath), "neko", [ PathHelper.getHaxelib (new Haxelib ("lime")) + "/templates/bin/hxswfml.n", "ttf2hash2", Path.withoutDirectory (sourcePath), Path.withoutDirectory (sourcePath) + ".hash", "-glyphs", glyphs ]); } else if (targetFlags.exists ("font-details")) { //var sourcePath = words[0]; //var details = Font.load (sourcePath); //var json = Json.stringify (details); //Sys.print (json); } else if (targetFlags.exists ("java-externs")) { var config = getHXCPPConfig (); var sourcePath = words[0]; var targetPath = words[1]; new JavaExternGenerator (config, sourcePath, targetPath); } } private function getBuildNumber (project:HXProject, increment:Bool = true):Void { if (project.meta.buildNumber == null) { var versionFile = PathHelper.combine (project.app.path, ".build"); var version = 1; try { if (FileSystem.exists (versionFile)) { var previousVersion = Std.parseInt (File.getBytes (versionFile).toString ()); if (previousVersion != null) { version = previousVersion; if (increment) { version ++; } } } } catch (e:Dynamic) {} project.meta.buildNumber = Std.string (version); if (increment) { try { PathHelper.mkdir (project.app.path); var output = File.write (versionFile, false); output.writeString (Std.string (version)); output.close (); } catch (e:Dynamic) {} } } } public static function getHXCPPConfig ():HXProject { var environment = Sys.environment (); var config = ""; if (environment.exists ("HXCPP_CONFIG")) { config = environment.get ("HXCPP_CONFIG"); } else { var home = ""; if (environment.exists ("HOME")) { home = environment.get ("HOME"); } else if (environment.exists ("USERPROFILE")) { home = environment.get ("USERPROFILE"); } else { LogHelper.warn ("HXCPP config might be missing (Environment has no \"HOME\" variable)"); return null; } config = home + "/.hxcpp_config.xml"; if (PlatformHelper.hostPlatform == Platform.WINDOWS) { config = config.split ("/").join ("\\"); } } if (FileSystem.exists (config)) { LogHelper.info ("", LogHelper.accentColor + "Reading HXCPP config: " + config + LogHelper.resetColor); return new ProjectXMLParser (config); } else { LogHelper.warn ("", "Could not read HXCPP config: " + config); } return null; } private function getVersion (haxelib:Haxelib = null):String { if (haxelib == null) { haxelib = new Haxelib ("lime"); } var json = Json.parse (File.getContent (PathHelper.getHaxelib (haxelib, true) + "/haxelib.json")); return json.version; } private function initializeProject (project:HXProject = null, targetName:String = ""):HXProject { LogHelper.info ("", LogHelper.accentColor + "Initializing project..." + LogHelper.resetColor); var projectFile = ""; if (project == null) { if (words.length == 2) { if (FileSystem.exists (words[0])) { if (FileSystem.isDirectory (words[0])) { projectFile = findProjectFile (words[0]); } else { projectFile = words[0]; } } if (targetName == "") { targetName = words[1].toLowerCase (); } } else { projectFile = findProjectFile (Sys.getCwd ()); if (targetName == "") { targetName = words[0].toLowerCase (); } } if (projectFile == "") { LogHelper.error ("You must have a \"project.xml\" file or specify another valid project file when using the '" + command + "' command"); return null; } else { LogHelper.info ("", LogHelper.accentColor + "Using project file: " + projectFile + LogHelper.resetColor); } } var target = null; switch (targetName) { case "cpp": target = PlatformHelper.hostPlatform; targetFlags.set ("cpp", ""); case "neko": target = PlatformHelper.hostPlatform; targetFlags.set ("neko", ""); case "java": target = PlatformHelper.hostPlatform; targetFlags.set ("java", ""); case "nodejs": target = PlatformHelper.hostPlatform; targetFlags.set ("nodejs", ""); case "cs": target = PlatformHelper.hostPlatform; targetFlags.set ("cs", ""); case "iphone", "iphoneos": target = Platform.IOS; case "iphonesim": target = Platform.IOS; targetFlags.set ("simulator", ""); case "firefox", "firefoxos": target = Platform.FIREFOX; overrides.haxedefs.set ("firefoxos", ""); case "mac", "macos": target = Platform.MAC; overrides.haxedefs.set ("macos", ""); default: target = cast targetName.toLowerCase (); } var config = getHXCPPConfig (); if (config != null) { for (define in config.defines.keys ()) { if (define == define.toUpperCase ()) { var value = config.defines.get (define); switch (define) { case "ANT_HOME": if (value == "/usr") { value = "/usr/share/ant"; } if (FileSystem.exists (value)) { Sys.putEnv (define, value); } case "JAVA_HOME": if (FileSystem.exists (value)) { Sys.putEnv (define, value); } default: Sys.putEnv (define, value); } } } } if (PlatformHelper.hostPlatform == Platform.WINDOWS) { if (Sys.getEnv ("JAVA_HOME") != null) { var javaPath = PathHelper.combine (Sys.getEnv ("JAVA_HOME"), "bin"); if (PlatformHelper.hostPlatform == Platform.WINDOWS) { Sys.putEnv ("PATH", javaPath + ";" + Sys.getEnv ("PATH")); } else { Sys.putEnv ("PATH", javaPath + ":" + Sys.getEnv ("PATH")); } } } if (project == null) { HXProject._command = command; HXProject._debug = debug; HXProject._target = target; HXProject._targetFlags = targetFlags; HXProject._userDefines = userDefines; try { Sys.setCwd (Path.directory (projectFile)); } catch (e:Dynamic) {} if (Path.extension (projectFile) == "lime" || Path.extension (projectFile) == "nmml" || Path.extension (projectFile) == "xml") { project = new ProjectXMLParser (Path.withoutDirectory (projectFile), userDefines, includePaths); } else if (Path.extension (projectFile) == "hxp") { project = HXProject.fromFile (projectFile, userDefines, includePaths); if (project != null) { project.command = command; project.debug = debug; project.target = target; project.targetFlags = targetFlags; } else { LogHelper.error ("Could not process \"" + projectFile + "\""); return null; } } } if (project == null || (command != "rebuild" && project.sources.length == 0 && !FileSystem.exists (project.app.main + ".hx"))) { LogHelper.error ("You must have a \"project.xml\" file or specify another valid project file when using the '" + command + "' command"); return null; } project.merge (config); project.haxedefs.set ("tools", version); /*if (userDefines.exists ("nme")) { project.haxedefs.set ("nme_install_tool", 1); project.haxedefs.set ("nme_ver", version); project.haxedefs.set ("nme" + version.split (".")[0], 1); project.config.cpp.buildLibrary = "hxcpp"; project.config.cpp.requireBuild = false; }*/ project.merge (overrides); if (overrides.architectures.length > 0) { project.architectures = overrides.architectures; } for (key in projectDefines.keys ()) { var components = key.split ("-"); var field = components.shift ().toLowerCase (); var attribute = ""; if (components.length > 0) { for (i in 1...components.length) { components[i] = components[i].substr (0, 1).toUpperCase () + components[i].substr (1).toLowerCase (); } attribute = components.join (""); } if (field == "template" && attribute == "path") { project.templatePaths.push (projectDefines.get (key)); } else if (field == "config") { project.config.set (attribute, projectDefines.get (key)); } else { if (Reflect.hasField (project, field)) { var fieldValue = Reflect.field (project, field); if (Reflect.hasField (fieldValue, attribute)) { if (Std.is (Reflect.field (fieldValue, attribute), String)) { Reflect.setField (fieldValue, attribute, projectDefines.get (key)); } else if (Std.is (Reflect.field (fieldValue, attribute), Float)) { Reflect.setField (fieldValue, attribute, Std.parseFloat (projectDefines.get (key))); } else if (Std.is (Reflect.field (fieldValue, attribute), Bool)) { Reflect.setField (fieldValue, attribute, (projectDefines.get (key).toLowerCase () == "true" || projectDefines.get (key) == "1")); } } } else { targetFlags.set (key, projectDefines.get (key)); } } } StringMapHelper.copyKeys (userDefines, project.haxedefs); getBuildNumber (project, (project.command == "build" || project.command == "test")); return project; } public static function main ():Void { new CommandLineTools (); } private function platformSetup ():Void { LogHelper.info ("", LogHelper.accentColor + "Running command: SETUP" + LogHelper.resetColor); if (words.length == 0) { PlatformSetup.run ("", userDefines, targetFlags); } else if (words.length == 1) { PlatformSetup.run (words[0], userDefines, targetFlags); } else { LogHelper.error ("Incorrect number of arguments for command 'setup'"); return; } } private function processArguments ():Void { var arguments = Sys.args (); var runFromHaxelib = false; if (arguments.length > 0) { // When the command-line tools are called from haxelib, // the last argument is the project directory and the // path to Lime is the current working directory var lastArgument = ""; for (i in 0...arguments.length) { lastArgument = arguments.pop (); if (lastArgument.length > 0) break; } lastArgument = new Path (lastArgument).toString (); if (((StringTools.endsWith (lastArgument, "/") && lastArgument != "/") || StringTools.endsWith (lastArgument, "\\")) && !StringTools.endsWith (lastArgument, ":\\")) { lastArgument = lastArgument.substr (0, lastArgument.length - 1); } if (FileSystem.exists (lastArgument) && FileSystem.isDirectory (lastArgument)) { Sys.setCwd (lastArgument); runFromHaxelib = true; } else { arguments.push (lastArgument); } } if (!runFromHaxelib) { if (FileSystem.exists ("tools.n")) { PathHelper.haxelibOverrides.set ("lime", PathHelper.combine (Sys.getCwd (), "../")); } else if (FileSystem.exists ("run.n")) { PathHelper.haxelibOverrides.set ("lime", Sys.getCwd ()); } } var catchArguments = false; var catchHaxeFlag = false; for (argument in arguments) { var equals = argument.indexOf ("="); if (catchHaxeFlag) { overrides.haxeflags.push (argument); catchHaxeFlag = false; } else if (catchArguments) { additionalArguments.push (argument); } else if (equals > 0) { var argValue = argument.substr (equals + 1); // if quotes remain on the argValue we need to strip them off // otherwise the compiler really dislikes the result! var r = ~/^['"](.*)['"]$/; if (r.match(argValue)) { argValue = r.matched(1); } if (argument.substr (0, 2) == "-D") { userDefines.set (argument.substr (2, equals - 2), argValue); } else if (argument.substr (0, 2) == "--") { // this won't work because it assumes there is only ever one of these. //projectDefines.set (argument.substr (2, equals - 2), argValue); var field = argument.substr (2, equals - 2); if (field == "haxedef") { overrides.haxedefs.set (argValue, 1); } else if (field == "haxeflag") { overrides.haxeflags.push (argValue); } else if (field == "haxelib") { var name = argValue; var version = ""; if (name.indexOf (":") > -1) { version = name.substr (name.indexOf (":") + 1); name = name.substr (0, name.indexOf (":")); } var i = 0; overrides.haxelibs.push (new Haxelib (name, version)); } else if (StringTools.startsWith (field, "haxelib-")) { var name = field.substr (8); PathHelper.haxelibOverrides.set (name, PathHelper.tryFullPath (argValue)); } else if (field == "source") { overrides.sources.push (argValue); } else if (field == "dependency") { overrides.dependencies.push (new Dependency (argValue, "")); } else if (StringTools.startsWith (field, "certificate-")) { if (overrides.certificate == null) { overrides.certificate = new Keystore (); } field = StringTools.replace (field, "certificate-", ""); if (field == "alias-password") field = "aliasPassword"; if (Reflect.hasField (overrides.certificate, field)) { Reflect.setField (overrides.certificate, field, argValue); } } else if (StringTools.startsWith (field, "app-") || StringTools.startsWith (field, "meta-") || StringTools.startsWith (field, "window-")) { var split = field.split ("-"); var fieldName = split[0]; var property = split[1]; for (i in 2...split.length) { property += split[i].substr (0, 1).toUpperCase () + split[i].substr (1, split[i].length - 1); } if (field == "window-allow-high-dpi") property = "allowHighDPI"; var fieldReference = Reflect.field (overrides, fieldName); if (Reflect.hasField (fieldReference, property)) { var propertyReference = Reflect.field (fieldReference, property); if (Std.is (propertyReference, Bool)) { Reflect.setField (fieldReference, property, argValue == "true"); } else if (Std.is (propertyReference, Int)) { Reflect.setField (fieldReference, property, Std.parseInt (argValue)); } else if (Std.is (propertyReference, Float)) { Reflect.setField (fieldReference, property, Std.parseFloat (argValue)); } else if (Std.is (propertyReference, String)) { Reflect.setField (fieldReference, property, argValue); } } } else if (field == "build-library") { overrides.config.set ("cpp.buildLibrary", argValue); } else if (field == "device") { targetFlags.set ("device", argValue); } else { projectDefines.set (field, argValue); } } else { userDefines.set (argument.substr (0, equals), argValue); } } else if (argument.substr (0, 2) == "-D") { userDefines.set (argument.substr (2), ""); } else if (argument.substr (0, 2) == "-I") { includePaths.push (argument.substr (2)); } else if (argument == "-args") { catchArguments = true; } else if (argument.substr (0, 1) == "-") { if (argument.substr (1, 1) == "-") { overrides.haxeflags.push (argument); if (argument == "--remap" || argument == "--connect") { catchHaxeFlag = true; } } else { if (argument.substr (0, 4) == "-arm") { try { var name = argument.substr (1).toUpperCase (); var value = Type.createEnum (Architecture, name); if (value != null) { overrides.architectures.push (value); } } catch (e:Dynamic) {} } else if (argument == "-64") { overrides.architectures.push (Architecture.X64); } else if (argument == "-32") { overrides.architectures.push (Architecture.X86); } else if (argument == "-v" || argument == "-verbose") { argument = "-verbose"; LogHelper.verbose = true; } else if (argument == "-dryrun") { ProcessHelper.dryRun = true; } else if (argument == "-notrace") { traceEnabled = false; } else if (argument == "-debug") { debug = true; } else if (argument == "-nocolor") { LogHelper.enableColor = false; } targetFlags.set (argument.substr (1), ""); } } else if (command.length == 0) { command = argument; } else { words.push (argument); } } } private function publishProject () { switch (words[words.length - 1]) { case "firefox": var project = initializeProject (null, "firefox"); LogHelper.info ("", LogHelper.accentColor + "Using publishing target: FIREFOX MARKETPLACE" + LogHelper.resetColor); //if (FirefoxMarketplace.isValid (project)) { // //buildProject (project, "build"); // //LogHelper.info ("", "\n" + LogHelper.accentColor + "Running command: PUBLISH" + LogHelper.resetColor); // //FirefoxMarketplace.publish (project); // //} } } private function updateLibrary ():Void { if ((words.length < 1 && command != "upgrade") || words.length > 1) { LogHelper.error ("Incorrect number of arguments for command '" + command + "'"); return; } LogHelper.info ("", LogHelper.accentColor + "Running command: " + command.toUpperCase () + LogHelper.resetColor); var name = defaultLibrary; if (words.length > 0) { name = words[0]; } var haxelib = new Haxelib (name); var path = PathHelper.getHaxelib (haxelib); switch (command) { case "install": if (path == null || path == "") { PlatformSetup.installHaxelib (haxelib); } else { PlatformSetup.updateHaxelib (haxelib); } PlatformSetup.setupHaxelib (haxelib); case "remove": if (path != null && path != "") { ProcessHelper.runCommand ("", "haxelib", [ "remove", name ]); } case "upgrade": if (path != null && path != "") { PlatformSetup.updateHaxelib (haxelib); PlatformSetup.setupHaxelib (haxelib); } else { LogHelper.warn ("\"" + haxelib.name + "\" is not a valid haxelib, or has not been installed"); } } } }