diff --git a/include.xml b/include.xml
index 843899872..848526af6 100644
--- a/include.xml
+++ b/include.xml
@@ -44,6 +44,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tools/platforms/AIRPlatform.hx b/tools/platforms/AIRPlatform.hx
new file mode 100644
index 000000000..bd3935dad
--- /dev/null
+++ b/tools/platforms/AIRPlatform.hx
@@ -0,0 +1,353 @@
+package;
+
+
+import haxe.io.Path;
+import hxp.project.AssetType;
+import hxp.project.HXProject;
+import hxp.project.Icon;
+import hxp.project.Platform;
+import hxp.project.PlatformType;
+import hxp.helpers.AIRHelper;
+import hxp.helpers.DeploymentHelper;
+import hxp.helpers.FileHelper;
+import hxp.helpers.FlashHelper;
+import hxp.helpers.IconHelper;
+import hxp.helpers.PathHelper;
+import hxp.helpers.PlatformHelper;
+import hxp.helpers.LogHelper;
+import hxp.helpers.ZipHelper;
+import sys.io.File;
+import sys.FileSystem;
+
+
+class AIRPlatform extends FlashPlatform {
+
+
+ private var iconData:Array;
+ private var targetPlatform:Platform;
+ private var targetPlatformType:PlatformType;
+
+
+ public function new (command:String, _project:HXProject, targetFlags:Map) {
+
+ super (command, _project, targetFlags);
+
+ targetDirectory = PathHelper.combine (project.app.path, project.config.getString ("air.output-directory", "air"));
+
+ if (targetFlags.exists ("android")) {
+
+ targetPlatform = Platform.ANDROID;
+ targetPlatformType = MOBILE;
+
+ } else if (targetFlags.exists ("ios")) {
+
+ targetPlatform = Platform.IOS;
+ targetPlatformType = MOBILE;
+
+ } else if (targetFlags.exists ("windows")) {
+
+ targetPlatform = Platform.WINDOWS;
+ targetPlatformType = DESKTOP;
+
+ } else if (targetFlags.exists ("mac")) {
+
+ targetPlatform = Platform.MAC;
+ targetPlatformType = DESKTOP;
+
+ } else {
+
+ targetPlatform = PlatformHelper.hostPlatform;
+ targetPlatformType = DESKTOP;
+
+ }
+
+ }
+
+
+ public override function build ():Void {
+
+ super.build ();
+
+ if (!project.defines.exists ("AIR_SDK")) {
+
+ LogHelper.error ("You must define AIR_SDK with the path to your AIR SDK");
+
+ }
+
+ // TODO: Should we package on desktop in "deploy" command instead?
+
+ if (targetPlatformType != DESKTOP) {
+
+ var files = [ project.app.file + ".swf" ];
+ for (asset in project.assets) {
+
+ if (asset.embed == false && asset.type != TEMPLATE) {
+
+ files.push (asset.targetPath);
+
+ }
+
+ }
+
+ for (icon in iconData) {
+
+ files.push (icon.path);
+
+ }
+
+ var targetPath = switch (targetPlatform) {
+
+ case ANDROID: "bin/" + project.app.file + ".apk";
+ case IOS: "bin/" + project.app.file + ".ipa";
+ default: "bin/" + project.app.file + ".air";
+
+ }
+
+ AIRHelper.build (project, targetDirectory, targetPlatform, targetPath, "application.xml", files, "bin");
+
+ }
+
+ }
+
+
+ public override function clean ():Void {
+
+ if (FileSystem.exists (targetDirectory)) {
+
+ PathHelper.removeDirectory (targetDirectory);
+
+ }
+
+ }
+
+
+ public override function deploy ():Void {
+
+ if (targetFlags.exists ("gdrive") || targetFlags.exists ("zip")) {
+
+ DeploymentHelper.deploy (project, targetFlags, targetDirectory, "AIR");
+
+ } else {
+
+ var rootDirectory = targetDirectory + "/bin";
+ var paths = PathHelper.readDirectory (rootDirectory, [ project.app.file + ".apk", project.app.file + ".ipa", project.app.file + ".air" ]);
+ var files = [];
+
+ for (path in paths) {
+
+ files.push (path.substr (rootDirectory.length + 1));
+
+ }
+
+ var name = project.meta.title + " (" + project.meta.version + " build " + project.meta.buildNumber + ")";
+
+ switch (targetPlatform) {
+
+ case WINDOWS:
+
+ name += " (Windows)";
+
+ case MAC:
+
+ name += " (macOS)";
+
+ case IOS:
+
+ name += " (iOS).ipa";
+
+ case ANDROID:
+
+ name += " (Android).apk";
+
+ default:
+
+ }
+
+ var outputPath = "dist/" + name;
+
+ PathHelper.mkdir (targetDirectory + "/dist");
+
+ outputPath = AIRHelper.build (project, targetDirectory, targetPlatform, outputPath, "application.xml", files, "bin");
+
+ if (targetPlatformType == DESKTOP) {
+
+ ZipHelper.compress (PathHelper.combine (targetDirectory, outputPath), PathHelper.combine (targetDirectory, "dist/" + name + ".zip"));
+
+ }
+
+ }
+
+ }
+
+
+ public override function install ():Void {
+
+ // TODO: Make separate install step
+
+ }
+
+
+ public override function run ():Void {
+
+ AIRHelper.run (project, targetDirectory, targetPlatform, "application.xml", "bin");
+
+ }
+
+
+ public override function trace ():Void {
+
+ AIRHelper.trace (project, targetDirectory, targetPlatform, "application.xml", "bin");
+
+ }
+
+
+ public override function uninstall ():Void {
+
+ AIRHelper.uninstall (project, targetDirectory, targetPlatform, "application.xml", "bin");
+
+ }
+
+
+ public override function update ():Void {
+
+ var destination = targetDirectory + "/bin/";
+ PathHelper.mkdir (destination);
+
+ // project = project.clone ();
+
+ embedded = FlashHelper.embedAssets (project, targetDirectory);
+
+ var context = generateContext ();
+ context.OUTPUT_DIR = targetDirectory;
+ context.AIR_SDK_VERSION = project.config.getString ("air.sdk-version", "28.0");
+
+ var buildNumber = Std.string (context.APP_BUILD_NUMBER);
+
+ if (buildNumber.length <= 3) {
+
+ context.APP_BUILD_NUMBER_SPLIT = buildNumber;
+
+ } else {
+
+ var major = null;
+
+ var patch = buildNumber.substr (-3);
+ buildNumber = buildNumber.substr (0, -3);
+
+ var minor = buildNumber.substr (-Std.int (Math.min (buildNumber.length, 3)));
+ buildNumber = buildNumber.substr (0, -minor.length);
+
+ if (buildNumber.length > 0) {
+
+ major = buildNumber.substr (-Std.int (Math.min (buildNumber.length, 3)));
+ buildNumber = buildNumber.substr (0, -major.length);
+
+ }
+
+ var buildNumberSplit = minor + "." + patch;
+ if (major != null) buildNumberSplit = major + "." + buildNumberSplit;
+
+ context.APP_BUILD_NUMBER_SPLIT = buildNumberSplit;
+
+ if (buildNumber.length > 0) {
+
+ LogHelper.warn ("Application build number " + buildNumber + buildNumberSplit + " exceeds 9 digits");
+
+ }
+
+ }
+
+ var iconSizes = [ 16, 29, 32, 36, 40, 48, 50, 57, 58, 60, 72, 75, 76, 80, 87, 96, 100, 114, 120, 128, 144, 152, 167, 180, 192, 512, 1024 ];
+ var icons = project.icons;
+ iconData = [];
+
+ if (icons.length == 0) {
+
+ icons = [ new Icon (PathHelper.findTemplate (project.templatePaths, "default/icon.svg")) ];
+
+ }
+
+ for (size in iconSizes) {
+
+ if (IconHelper.createIcon (icons, size, size, targetDirectory + "/bin/_res/icon-" + size + ".png")) {
+
+ iconData.push ({ size: size, path: "_res/icon-" + size + ".png" });
+
+ }
+
+ }
+
+ if (iconData.length > 0) context.icons = iconData;
+
+ context.extensions = new Array();
+
+ for (dependency in project.dependencies) {
+
+ if (StringTools.endsWith(dependency.path, ".ane")) {
+
+ var extension:Dynamic = { name: dependency.name };
+ context.extensions.push(extension);
+ context.HAXE_FLAGS += "\n-swf-lib " + dependency.path;
+
+ }
+
+ }
+
+ FileHelper.recursiveSmartCopyTemplate (project, "haxe", targetDirectory + "/haxe", context);
+ FileHelper.recursiveSmartCopyTemplate (project, "air/hxml", targetDirectory + "/haxe", context);
+ FileHelper.recursiveSmartCopyTemplate (project, "air/template", targetDirectory, context);
+
+ if (embedded) {
+
+ var files = [ "debug.hxml", "release.hxml", "final.hxml" ];
+ var path, hxml, lines, output;
+
+ for (file in files) {
+
+ path = targetDirectory + "/haxe/" + file;
+ hxml = File.getContent (path);
+
+ if (hxml.indexOf ("-swf-header") > -1) {
+
+ lines = ~/[\r\n]+/g.split (hxml);
+ output = [];
+
+ for (line in lines) {
+
+ if (line.indexOf ("-swf-header") > -1) continue;
+ output.push (line);
+
+ }
+
+ if (output.length < lines.length) {
+
+ File.saveContent (path, output.join ("\n"));
+
+ }
+
+ }
+
+ }
+
+ }
+
+ for (asset in project.assets) {
+
+ if (asset.type == AssetType.TEMPLATE || asset.embed == false /*|| !usesLime*/) {
+
+ var path = PathHelper.combine (destination, asset.targetPath);
+
+ PathHelper.mkdir (Path.directory (path));
+ FileHelper.copyAsset (asset, path, context);
+
+ }
+
+ }
+
+ }
+
+
+ @ignore public override function rebuild ():Void {}
+
+
+}
\ No newline at end of file
diff --git a/tools/platforms/AndroidPlatform.hx b/tools/platforms/AndroidPlatform.hx
new file mode 100644
index 000000000..29a070571
--- /dev/null
+++ b/tools/platforms/AndroidPlatform.hx
@@ -0,0 +1,481 @@
+package;
+
+
+import haxe.io.Path;
+import haxe.Template;
+import hxp.helpers.AndroidHelper;
+import hxp.helpers.ArrayHelper;
+import hxp.helpers.CPPHelper;
+import hxp.helpers.DeploymentHelper;
+import hxp.helpers.FileHelper;
+import hxp.helpers.IconHelper;
+import hxp.helpers.LogHelper;
+import hxp.helpers.PathHelper;
+import hxp.helpers.ProcessHelper;
+import hxp.helpers.WatchHelper;
+import hxp.project.Architecture;
+import hxp.project.AssetType;
+import hxp.project.Haxelib;
+import hxp.project.HXProject;
+import hxp.project.Icon;
+import hxp.project.PlatformTarget;
+import sys.io.File;
+import sys.FileSystem;
+
+
+class AndroidPlatform extends PlatformTarget {
+
+
+ private var deviceID:String;
+
+
+ public function new (command:String, _project:HXProject, targetFlags:Map) {
+
+ super (command, _project, targetFlags);
+
+ if (command != "display" && command != "clean") {
+
+ // project = project.clone ();
+
+ if (!project.environment.exists ("ANDROID_SETUP")) {
+
+ LogHelper.error ("You need to run \"lime setup android\" before you can use the Android target");
+
+ }
+
+ AndroidHelper.initialize (project);
+
+ if (deviceID == null && project.targetFlags.exists ("device")) {
+
+ deviceID = project.targetFlags.get ("device") + ":5555";
+
+ }
+
+ }
+
+ targetDirectory = PathHelper.combine (project.app.path, project.config.getString ("android.output-directory", "android"));
+
+ }
+
+
+ public override function build ():Void {
+
+ var destination = targetDirectory + "/bin";
+ var hxml = targetDirectory + "/haxe/" + buildType + ".hxml";
+ var sourceSet = destination + "/app/src/main";
+
+ var hasARMV5 = (ArrayHelper.containsValue (project.architectures, Architecture.ARMV5) || ArrayHelper.containsValue (project.architectures, Architecture.ARMV6));
+ var hasARMV7 = ArrayHelper.containsValue (project.architectures, Architecture.ARMV7);
+ var hasX86 = ArrayHelper.containsValue (project.architectures, Architecture.X86);
+
+ var architectures = [];
+
+ if (hasARMV5) architectures.push (Architecture.ARMV5);
+ if (hasARMV7 || (!hasARMV5 && !hasX86)) architectures.push (Architecture.ARMV7);
+ if (hasX86) architectures.push (Architecture.X86);
+
+ for (architecture in architectures) {
+
+ var haxeParams = [ hxml, "-D", "android", "-D", "PLATFORM=android-14" ];
+ var cppParams = [ "-Dandroid", "-DPLATFORM=android-14" ];
+ var path = sourceSet + "/jniLibs/armeabi";
+ var suffix = ".so";
+
+ if (architecture == Architecture.ARMV7) {
+
+ haxeParams.push ("-D");
+ haxeParams.push ("HXCPP_ARMV7");
+ cppParams.push ("-DHXCPP_ARMV7");
+
+ if (hasARMV5) {
+
+ path = sourceSet + "/jniLibs/armeabi-v7a";
+
+ }
+
+ suffix = "-v7.so";
+
+ } else if (architecture == Architecture.X86) {
+
+ haxeParams.push ("-D");
+ haxeParams.push ("HXCPP_X86");
+ cppParams.push ("-DHXCPP_X86");
+ path = sourceSet + "/jniLibs/x86";
+ suffix = "-x86.so";
+
+ }
+
+ for (ndll in project.ndlls) {
+
+ FileHelper.copyLibrary (project, ndll, "Android", "lib", suffix, path, project.debug, ".so");
+
+ }
+
+ ProcessHelper.runCommand ("", "haxe", haxeParams);
+
+ if (noOutput) return;
+
+ CPPHelper.compile (project, targetDirectory + "/obj", cppParams);
+
+ FileHelper.copyIfNewer (targetDirectory + "/obj/libApplicationMain" + (project.debug ? "-debug" : "") + suffix, path + "/libApplicationMain.so");
+
+ }
+
+ if (!ArrayHelper.containsValue (project.architectures, Architecture.ARMV7) || !hasARMV5) {
+
+ if (FileSystem.exists (sourceSet + "/jniLibs/armeabi-v7a")) {
+
+ PathHelper.removeDirectory (sourceSet + "/jniLibs/armeabi-v7a");
+
+ }
+
+ }
+
+ if (!hasX86) {
+
+ if (FileSystem.exists (sourceSet + "/jniLibs/x86")) {
+
+ PathHelper.removeDirectory (sourceSet + "/jniLibs/x86");
+
+ }
+
+ }
+
+ if (noOutput) return;
+
+ AndroidHelper.build (project, destination);
+
+ }
+
+
+ public override function clean ():Void {
+
+ if (FileSystem.exists (targetDirectory)) {
+
+ PathHelper.removeDirectory (targetDirectory);
+
+ }
+
+ }
+
+
+ public override function deploy ():Void {
+
+ DeploymentHelper.deploy (project, targetFlags, targetDirectory, "Android");
+
+ }
+
+
+ public override function display ():Void {
+
+ Sys.println (getDisplayHXML ());
+
+ }
+
+
+ private function getDisplayHXML ():String {
+
+ var hxml = PathHelper.findTemplate (project.templatePaths, "android/hxml/" + buildType + ".hxml");
+
+ var context = project.templateContext;
+ context.CPP_DIR = targetDirectory + "/obj";
+ context.OUTPUT_DIR = targetDirectory;
+
+ var template = new Template (File.getContent (hxml));
+
+ return template.execute (context) + "\n-D display";
+
+ }
+
+
+ public override function install ():Void {
+
+ var build = "-debug";
+
+ if (project.keystore != null) {
+
+ build = "-release";
+
+ }
+
+ var outputDirectory = null;
+
+ if (project.config.exists ("android.gradle-build-directory")) {
+
+ outputDirectory = PathHelper.combine (project.config.getString ("android.gradle-build-directory"), project.app.file + "/app/outputs/apk");
+
+ } else {
+
+ outputDirectory = PathHelper.combine (FileSystem.fullPath (targetDirectory), "bin/app/build/outputs/apk");
+
+ }
+
+ var apkPath = PathHelper.combine (outputDirectory, project.app.file + build + ".apk");
+
+ deviceID = AndroidHelper.install (project, apkPath, deviceID);
+
+ }
+
+
+ public override function rebuild ():Void {
+
+ var armv5 = (command == "rebuild" || ArrayHelper.containsValue (project.architectures, Architecture.ARMV5) || ArrayHelper.containsValue (project.architectures, Architecture.ARMV6));
+ var armv7 = (command == "rebuild" || ArrayHelper.containsValue (project.architectures, Architecture.ARMV7));
+ var x86 = (command == "rebuild" || ArrayHelper.containsValue (project.architectures, Architecture.X86));
+
+ var commands = [];
+
+ if (armv5) commands.push ([ "-Dandroid", "-DPLATFORM=android-14" ]);
+ if (armv7) commands.push ([ "-Dandroid", "-DHXCPP_ARMV7", "-DHXCPP_ARM7", "-DPLATFORM=android-14" ]);
+ if (x86) commands.push ([ "-Dandroid", "-DHXCPP_X86", "-DPLATFORM=android-14" ]);
+
+ CPPHelper.rebuild (project, commands);
+
+ }
+
+
+ public override function run ():Void {
+
+ AndroidHelper.run (project.meta.packageName + "/" + project.meta.packageName + ".MainActivity", deviceID);
+
+ }
+
+
+ public override function trace ():Void {
+
+ AndroidHelper.trace (project, project.debug, deviceID);
+
+ }
+
+
+ public override function uninstall ():Void {
+
+ AndroidHelper.uninstall (project.meta.packageName, deviceID);
+
+ }
+
+
+ public override function update ():Void {
+
+ // project = project.clone ();
+
+ for (asset in project.assets) {
+
+ if (asset.embed && asset.sourcePath == "") {
+
+ var path = PathHelper.combine (targetDirectory + "/obj/tmp", asset.targetPath);
+ PathHelper.mkdir (Path.directory (path));
+ FileHelper.copyAsset (asset, path);
+ asset.sourcePath = path;
+
+ }
+
+ }
+
+ //initialize (project);
+
+ var destination = targetDirectory + "/bin";
+ var sourceSet = destination + "/app/src/main";
+ PathHelper.mkdir (sourceSet);
+ PathHelper.mkdir (sourceSet + "/res/drawable-ldpi/");
+ PathHelper.mkdir (sourceSet + "/res/drawable-mdpi/");
+ PathHelper.mkdir (sourceSet + "/res/drawable-hdpi/");
+ PathHelper.mkdir (sourceSet + "/res/drawable-xhdpi/");
+
+ for (asset in project.assets) {
+
+ if (asset.type != AssetType.TEMPLATE) {
+
+ var targetPath = "";
+
+ switch (asset.type) {
+
+ default:
+ //case SOUND, MUSIC:
+
+ //var extension = Path.extension (asset.sourcePath);
+ //asset.flatName += ((extension != "") ? "." + extension : "");
+
+ //asset.resourceName = asset.flatName;
+ targetPath = PathHelper.combine (sourceSet + "/assets/", asset.resourceName);
+
+ //asset.resourceName = asset.id;
+ //targetPath = sourceSet + "/res/raw/" + asset.flatName + "." + Path.extension (asset.targetPath);
+
+ //default:
+
+ //asset.resourceName = asset.flatName;
+ //targetPath = sourceSet + "/assets/" + asset.resourceName;
+
+ }
+
+ FileHelper.copyAssetIfNewer (asset, targetPath);
+
+ }
+
+ }
+
+ if (project.targetFlags.exists ("xml")) {
+
+ project.haxeflags.push ("-xml " + targetDirectory + "/types.xml");
+
+ }
+
+ var context = project.templateContext;
+
+ context.CPP_DIR = targetDirectory + "/obj";
+ context.OUTPUT_DIR = targetDirectory;
+ context.ANDROID_INSTALL_LOCATION = project.config.getString ("android.install-location", "auto");
+ context.ANDROID_MINIMUM_SDK_VERSION = project.config.getInt ("android.minimum-sdk-version", 9);
+ context.ANDROID_TARGET_SDK_VERSION = project.config.getInt ("android.target-sdk-version", 19);
+ context.ANDROID_EXTENSIONS = project.config.getArrayString ("android.extension");
+ context.ANDROID_PERMISSIONS = project.config.getArrayString ("android.permission", [ "android.permission.WAKE_LOCK", "android.permission.INTERNET", "android.permission.VIBRATE", "android.permission.ACCESS_NETWORK_STATE" ]);
+ context.ANDROID_GRADLE_VERSION = project.config.getString ("android.gradle-version", "2.10");
+ context.ANDROID_GRADLE_PLUGIN = project.config.getString ("android.gradle-plugin", "2.1.0");
+ context.ANDROID_LIBRARY_PROJECTS = [];
+
+ if (!project.environment.exists ("ANDROID_SDK") || !project.environment.exists ("ANDROID_NDK_ROOT")) {
+
+ var command = "lime";
+ var toolsBase = Type.resolveClass ("CommandLineTools");
+ if (toolsBase != null)
+ command = Reflect.field (toolsBase, "commandName");
+
+ LogHelper.error ("You must define ANDROID_SDK and ANDROID_NDK_ROOT to target Android, please run '" + command + " setup android' first");
+ Sys.exit (1);
+
+ }
+
+ if (project.config.exists ("android.gradle-build-directory")) {
+
+ context.ANDROID_GRADLE_BUILD_DIRECTORY = project.config.getString ("android.gradle-build-directory");
+
+ }
+
+ if (project.config.exists ("android.build-tools-version")) {
+
+ context.ANDROID_BUILD_TOOLS_VERSION = project.config.getString ("android.build-tools-version");
+
+ } else {
+
+ context.ANDROID_BUILD_TOOLS_VERSION = AndroidHelper.getBuildToolsVersion (project);
+
+ }
+
+ var escaped = ~/([ #!=\\:])/g;
+ context.ANDROID_SDK_ESCAPED = escaped.replace(context.ENV_ANDROID_SDK, "\\$1");
+ context.ANDROID_NDK_ROOT_ESCAPED = escaped.replace(context.ENV_ANDROID_NDK_ROOT, "\\$1");
+
+ if (Reflect.hasField (context, "KEY_STORE")) context.KEY_STORE = StringTools.replace (context.KEY_STORE, "\\", "\\\\");
+ if (Reflect.hasField (context, "KEY_STORE_ALIAS")) context.KEY_STORE_ALIAS = StringTools.replace (context.KEY_STORE_ALIAS, "\\", "\\\\");
+ if (Reflect.hasField (context, "KEY_STORE_PASSWORD")) context.KEY_STORE_PASSWORD = StringTools.replace (context.KEY_STORE_PASSWORD, "\\", "\\\\");
+ if (Reflect.hasField (context, "KEY_STORE_ALIAS_PASSWORD")) context.KEY_STORE_ALIAS_PASSWORD = StringTools.replace (context.KEY_STORE_ALIAS_PASSWORD, "\\", "\\\\");
+
+ var index = 1;
+
+ for (dependency in project.dependencies) {
+
+ if (dependency.path != "" && FileSystem.exists (dependency.path) && FileSystem.isDirectory (dependency.path) && (FileSystem.exists (PathHelper.combine (dependency.path, "project.properties")) || FileSystem.exists (PathHelper.combine (dependency.path, "build.gradle")))) {
+
+ var name = dependency.name;
+ if (name == "") name = "project" + index;
+
+ context.ANDROID_LIBRARY_PROJECTS.push ({ name: name, index: index, path: "deps/" + name, source: dependency.path });
+ index++;
+
+ }
+
+ }
+
+ var iconTypes = [ "ldpi", "mdpi", "hdpi", "xhdpi", "xxhdpi", "xxxhdpi" ];
+ var iconSizes = [ 36, 48, 72, 96, 144, 192 ];
+ var icons = project.icons;
+
+ if (icons.length == 0) {
+
+ icons = [ new Icon (PathHelper.findTemplate (project.templatePaths, "default/icon.svg")) ];
+
+ }
+
+ for (i in 0...iconTypes.length) {
+
+ if (IconHelper.createIcon (icons, iconSizes[i], iconSizes[i], sourceSet + "/res/drawable-" + iconTypes[i] + "/icon.png")) {
+
+ context.HAS_ICON = true;
+
+ }
+
+ }
+
+ IconHelper.createIcon (icons, 732, 412, sourceSet + "/res/drawable-xhdpi/ouya_icon.png");
+
+ var packageDirectory = project.meta.packageName;
+ packageDirectory = sourceSet + "/java/" + packageDirectory.split (".").join ("/");
+ PathHelper.mkdir (packageDirectory);
+
+ for (javaPath in project.javaPaths) {
+
+ try {
+
+ if (FileSystem.isDirectory (javaPath)) {
+
+ FileHelper.recursiveCopy (javaPath, sourceSet + "/java", context, true);
+
+ } else {
+
+ if (Path.extension (javaPath) == "jar") {
+
+ FileHelper.copyIfNewer (javaPath, destination + "/app/libs/" + Path.withoutDirectory (javaPath));
+
+ } else {
+
+ FileHelper.copyIfNewer (javaPath, sourceSet + "/java/" + Path.withoutDirectory (javaPath));
+
+ }
+
+ }
+
+ } catch (e:Dynamic) {}
+
+ // throw"Could not find javaPath " + javaPath +" required by extension.";
+
+ //}
+
+ }
+
+ for (library in context.ANDROID_LIBRARY_PROJECTS) {
+
+ FileHelper.recursiveCopy (library.source, destination + "/deps/" + library.name, context, true);
+
+ }
+
+ FileHelper.recursiveSmartCopyTemplate (project, "android/template", destination, context);
+ FileHelper.copyFileTemplate (project.templatePaths, "android/MainActivity.java", packageDirectory + "/MainActivity.java", context);
+ FileHelper.recursiveSmartCopyTemplate (project, "haxe", targetDirectory + "/haxe", context);
+ FileHelper.recursiveSmartCopyTemplate (project, "android/hxml", targetDirectory + "/haxe", context);
+
+ for (asset in project.assets) {
+
+ if (asset.type == AssetType.TEMPLATE) {
+
+ var targetPath = PathHelper.combine (destination, asset.targetPath);
+ PathHelper.mkdir (Path.directory (targetPath));
+ FileHelper.copyAsset (asset, targetPath, context);
+
+ }
+
+ }
+
+ }
+
+
+ public override function watch ():Void {
+
+ var dirs = WatchHelper.processHXML (project, getDisplayHXML ());
+ var command = WatchHelper.getCurrentCommand ();
+ WatchHelper.watch (project, command, dirs);
+
+ }
+
+
+}
\ No newline at end of file
diff --git a/tools/platforms/EmscriptenPlatform.hx b/tools/platforms/EmscriptenPlatform.hx
new file mode 100644
index 000000000..fe2ff167e
--- /dev/null
+++ b/tools/platforms/EmscriptenPlatform.hx
@@ -0,0 +1,374 @@
+package;
+
+
+import haxe.io.Path;
+import haxe.Json;
+import haxe.Template;
+import hxp.helpers.CPPHelper;
+import hxp.helpers.DeploymentHelper;
+import hxp.helpers.FileHelper;
+import hxp.helpers.HTML5Helper;
+import hxp.helpers.LogHelper;
+import hxp.helpers.PathHelper;
+import hxp.helpers.ProcessHelper;
+import hxp.project.AssetType;
+import hxp.project.Haxelib;
+import hxp.project.HXProject;
+import hxp.project.PlatformTarget;
+import sys.io.File;
+import sys.FileSystem;
+
+
+class EmscriptenPlatform extends PlatformTarget {
+
+
+ private var outputFile:String;
+
+
+ public function new (command:String, _project:HXProject, targetFlags:Map) {
+
+ super (command, _project, targetFlags);
+
+ targetDirectory = PathHelper.combine (project.app.path, project.config.getString ("emscripten.output-directory", "emscripten"));
+ outputFile = targetDirectory + "/bin/" + project.app.file + ".js";
+
+ }
+
+
+ public override function build ():Void {
+
+ var sdkPath = null;
+
+ if (project.defines.exists ("EMSCRIPTEN_SDK")) {
+
+ sdkPath = project.defines.get ("EMSCRIPTEN_SDK");
+
+ } else if (project.environment.exists ("EMSCRIPTEN_SDK")) {
+
+ sdkPath = project.environment.get ("EMSCRIPTEN_SDK");
+
+ }
+
+ if (sdkPath == null) {
+
+ LogHelper.error ("You must define EMSCRIPTEN_SDK with the path to your Emscripten SDK");
+
+ }
+
+ var hxml = targetDirectory + "/haxe/" + buildType + ".hxml";
+ var args = [ hxml, "-D", "emscripten", "-D", "webgl", "-D", "static_link"];
+
+ if (LogHelper.verbose) {
+
+ args.push ("-D");
+ args.push ("verbose");
+
+ }
+
+ ProcessHelper.runCommand ("", "haxe", args);
+
+ if (noOutput) return;
+
+ CPPHelper.compile (project, targetDirectory + "/obj", [ "-Demscripten", "-Dwebgl", "-Dstatic_link" ]);
+
+ project.path (sdkPath);
+
+ ProcessHelper.runCommand ("", "emcc", [ targetDirectory + "/obj/Main.cpp", "-o", targetDirectory + "/obj/Main.o" ], true, false, true);
+
+ args = [ "Main.o" ];
+
+ for (ndll in project.ndlls) {
+
+ var path = PathHelper.getLibraryPath (ndll, "Emscripten", "lib", ".a", project.debug);
+ args.push (path);
+
+ }
+
+ var json = Json.parse (File.getContent (PathHelper.getHaxelib (new Haxelib ("hxcpp"), true) + "/haxelib.json"));
+ var prefix = "";
+
+ if (Std.parseFloat (json.version) > 3.1) {
+
+ prefix = "lib";
+
+ }
+
+ args = args.concat ([ prefix + "ApplicationMain" + (project.debug ? "-debug" : "") + ".a", "-o", "ApplicationMain.o" ]);
+ ProcessHelper.runCommand (targetDirectory + "/obj", "emcc", args, true, false, true);
+
+ args = [ "ApplicationMain.o" ];
+
+ if (project.targetFlags.exists ("webassembly") || project.targetFlags.exists ("wasm")) {
+
+ args.push ("-s");
+ args.push ("WASM=1");
+
+ } else {
+
+ args.push ("-s");
+ args.push ("ASM_JS=1");
+
+ }
+
+ args.push ("-s");
+ args.push ("NO_EXIT_RUNTIME=1");
+
+ args.push ("-s");
+ args.push ("USE_SDL=2");
+
+ for (dependency in project.dependencies) {
+
+ if (dependency.name != "") {
+
+ args.push ("-l" + dependency.name);
+
+ }
+
+ }
+
+ if (project.targetFlags.exists ("final")) {
+
+ args.push ("-s");
+ args.push ("DISABLE_EXCEPTION_CATCHING=0");
+ args.push ("-O3");
+
+ } else if (!project.debug) {
+
+ args.push ("-s");
+ args.push ("DISABLE_EXCEPTION_CATCHING=0");
+ //args.push ("-s");
+ //args.push ("OUTLINING_LIMIT=70000");
+ args.push ("-O2");
+
+ } else {
+
+ args.push ("-s");
+ args.push ("DISABLE_EXCEPTION_CATCHING=2");
+ args.push ("-s");
+ args.push ("ASSERTIONS=1");
+ args.push ("-O1");
+
+ }
+
+ args.push ("-s");
+ args.push ("ALLOW_MEMORY_GROWTH=1");
+
+ if (project.targetFlags.exists ("minify")) {
+
+ // 02 enables minification
+
+ //args.push ("--minify");
+ //args.push ("1");
+ //args.push ("--closure");
+ //args.push ("1");
+
+ }
+
+ //args.push ("--memory-init-file");
+ //args.push ("1");
+ //args.push ("--jcache");
+ //args.push ("-g");
+
+ if (FileSystem.exists (targetDirectory + "/obj/assets")) {
+
+ args.push ("--preload-file");
+ args.push ("assets");
+
+ }
+
+ if (LogHelper.verbose) {
+
+ args.push ("-v");
+
+ }
+
+ //if (project.targetFlags.exists ("compress")) {
+ //
+ //args.push ("--compression");
+ //args.push (PathHelper.findTemplate (project.templatePaths, "bin/utils/lzma/compress.exe") + "," + PathHelper.findTemplate (project.templatePaths, "resources/lzma-decoder.js") + ",LZMA.decompress");
+ //args.push ("haxelib run openfl compress," + PathHelper.findTemplate (project.templatePaths, "resources/lzma-decoder.js") + ",LZMA.decompress");
+ //args.push ("-o");
+ //args.push ("../bin/index.html");
+ //
+ //} else {
+
+ args.push ("-o");
+ args.push ("../bin/" + project.app.file + ".js");
+
+ //}
+
+ //args.push ("../bin/index.html");
+
+ ProcessHelper.runCommand (targetDirectory + "/obj", "emcc", args, true, false, true);
+
+ if (project.targetFlags.exists ("minify")) {
+
+ HTML5Helper.minify (project, targetDirectory + "/bin/" + project.app.file + ".js");
+
+ }
+
+ if (project.targetFlags.exists ("compress")) {
+
+ if (FileSystem.exists (targetDirectory + "/bin/" + project.app.file + ".data")) {
+
+ //var byteArray = ByteArray.readFile (targetDirectory + "/bin/" + project.app.file + ".data");
+ //byteArray.compress (CompressionAlgorithm.GZIP);
+ //File.saveBytes (targetDirectory + "/bin/" + project.app.file + ".data.compress", byteArray);
+
+ }
+
+ //var byteArray = ByteArray.readFile (targetDirectory + "/bin/" + project.app.file + ".js");
+ //byteArray.compress (CompressionAlgorithm.GZIP);
+ //File.saveBytes (targetDirectory + "/bin/" + project.app.file + ".js.compress", byteArray);
+
+ } else {
+
+ File.saveContent (targetDirectory + "/bin/.htaccess", "SetOutputFilter DEFLATE");
+
+ }
+
+ }
+
+
+ public override function clean ():Void {
+
+ if (FileSystem.exists (targetDirectory)) {
+
+ PathHelper.removeDirectory (targetDirectory);
+
+ }
+
+ }
+
+
+ public override function deploy ():Void {
+
+ DeploymentHelper.deploy (project, targetFlags, targetDirectory, "Emscripten");
+
+ }
+
+
+ public override function display ():Void {
+
+ var hxml = PathHelper.findTemplate (project.templatePaths, "emscripten/hxml/" + buildType + ".hxml");
+
+ var context = project.templateContext;
+ context.OUTPUT_DIR = targetDirectory;
+ context.OUTPUT_FILE = outputFile;
+
+ var template = new Template (File.getContent (hxml));
+
+ Sys.println (template.execute (context));
+ Sys.println ("-D display");
+
+ }
+
+
+ public override function rebuild ():Void {
+
+ CPPHelper.rebuild (project, [[ "-Demscripten", "-Dstatic_link" ]]);
+
+ }
+
+
+ public override function run ():Void {
+
+ HTML5Helper.launch (project, targetDirectory + "/bin");
+
+ }
+
+
+ public override function update ():Void {
+
+ // project = project.clone ();
+
+ for (asset in project.assets) {
+
+ if (asset.embed && asset.sourcePath == "") {
+
+ var path = PathHelper.combine (targetDirectory + "/obj/tmp", asset.targetPath);
+ PathHelper.mkdir (Path.directory (path));
+ FileHelper.copyAsset (asset, path);
+ asset.sourcePath = path;
+
+ }
+
+ }
+
+ for (asset in project.assets) {
+
+ asset.resourceName = "assets/" + asset.resourceName;
+
+ }
+
+ var destination = targetDirectory + "/bin/";
+ PathHelper.mkdir (destination);
+
+ //for (asset in project.assets) {
+ //
+ //if (asset.type == AssetType.FONT) {
+ //
+ //project.haxeflags.push (HTML5Helper.generateFontData (project, asset));
+ //
+ //}
+ //
+ //}
+
+ if (project.targetFlags.exists ("xml")) {
+
+ project.haxeflags.push ("-xml " + targetDirectory + "/types.xml");
+
+ }
+
+ var context = project.templateContext;
+
+ context.WIN_FLASHBACKGROUND = StringTools.hex (project.window.background, 6);
+ context.OUTPUT_DIR = targetDirectory;
+ context.OUTPUT_FILE = outputFile;
+ context.CPP_DIR = targetDirectory + "/obj";
+ context.USE_COMPRESSION = project.targetFlags.exists ("compress");
+
+ for (asset in project.assets) {
+
+ var path = PathHelper.combine (targetDirectory + "/obj/assets", asset.targetPath);
+
+ if (asset.type != AssetType.TEMPLATE) {
+
+ //if (asset.type != AssetType.FONT) {
+
+ PathHelper.mkdir (Path.directory (path));
+ FileHelper.copyAssetIfNewer (asset, path);
+
+ //}
+
+ }
+
+ }
+
+ FileHelper.recursiveSmartCopyTemplate (project, "emscripten/template", destination, context);
+ FileHelper.recursiveSmartCopyTemplate (project, "haxe", targetDirectory + "/haxe", context);
+ FileHelper.recursiveSmartCopyTemplate (project, "emscripten/hxml", targetDirectory + "/haxe", context);
+ FileHelper.recursiveSmartCopyTemplate (project, "emscripten/cpp", targetDirectory + "/obj", context);
+
+ for (asset in project.assets) {
+
+ var path = PathHelper.combine (destination, asset.targetPath);
+
+ if (asset.type == AssetType.TEMPLATE) {
+
+ PathHelper.mkdir (Path.directory (path));
+ FileHelper.copyAsset (asset, path, context);
+
+ }
+
+ }
+
+ }
+
+
+ @ignore public override function install ():Void {}
+ @ignore public override function trace ():Void {}
+ @ignore public override function uninstall ():Void {}
+
+
+}
diff --git a/tools/platforms/FlashPlatform.hx b/tools/platforms/FlashPlatform.hx
new file mode 100644
index 000000000..069bf9304
--- /dev/null
+++ b/tools/platforms/FlashPlatform.hx
@@ -0,0 +1,295 @@
+package;
+
+
+import haxe.io.Path;
+import haxe.Json;
+import haxe.Template;
+import hxp.helpers.CompatibilityHelper;
+import hxp.helpers.DeploymentHelper;
+import hxp.helpers.FileHelper;
+import hxp.helpers.FlashHelper;
+import hxp.helpers.HTML5Helper;
+import hxp.helpers.LogHelper;
+import hxp.helpers.PathHelper;
+import hxp.helpers.PlatformHelper;
+import hxp.helpers.ProcessHelper;
+import hxp.helpers.WatchHelper;
+import hxp.project.AssetType;
+import hxp.project.Haxelib;
+import hxp.project.HXProject;
+import hxp.project.Platform;
+import hxp.project.PlatformTarget;
+import sys.io.File;
+import sys.FileSystem;
+
+#if neko
+import neko.vm.Thread;
+#end
+
+
+class FlashPlatform extends PlatformTarget {
+
+
+ private var embedded:Bool;
+ private var logLength:Int = 0;
+
+
+ public function new (command:String, _project:HXProject, targetFlags:Map) {
+
+ super (command, _project, targetFlags);
+
+ targetDirectory = PathHelper.combine (project.app.path, project.config.getString ("flash.output-directory", "flash"));
+
+ }
+
+
+ public override function build ():Void {
+
+ ProcessHelper.runCommand ("", "haxe", [ targetDirectory + "/haxe/" + buildType + ".hxml" ]);
+
+ }
+
+
+ public override function clean ():Void {
+
+ var targetPath = targetDirectory + "";
+
+ if (FileSystem.exists (targetPath)) {
+
+ PathHelper.removeDirectory (targetPath);
+
+ }
+
+ }
+
+
+ public override function deploy ():Void {
+
+ DeploymentHelper.deploy (project, targetFlags, targetDirectory, "Flash");
+
+ }
+
+
+ public override function display ():Void {
+
+ Sys.println (getDisplayHXML ());
+
+ }
+
+
+ private function generateContext ():Dynamic {
+
+ // project = project.clone ();
+
+ if (project.targetFlags.exists ("xml")) {
+
+ project.haxeflags.push ("-xml " + targetDirectory + "/types.xml");
+
+ }
+
+ if (LogHelper.verbose) {
+
+ project.haxedefs.set ("verbose", 1);
+
+ }
+
+ var context = project.templateContext;
+ context.WIN_FLASHBACKGROUND = project.window.background != null ? StringTools.hex (project.window.background, 6) : "0xFFFFFF";
+ var assets:Array = cast context.assets;
+
+ for (asset in assets) {
+
+ var assetType:AssetType = Reflect.field (AssetType, asset.type.toUpperCase ());
+
+ switch (assetType) {
+
+ case MUSIC : asset.flashClass = "flash.media.Sound";
+ case SOUND : asset.flashClass = "flash.media.Sound";
+ case IMAGE : asset.flashClass = "flash.display.BitmapData";
+ case FONT : asset.flashClass = "flash.text.Font";
+ default: asset.flashClass = "flash.utils.ByteArray";
+
+ }
+
+ }
+
+ return context;
+
+ }
+
+
+ private function getDisplayHXML ():String {
+
+ var hxml = PathHelper.findTemplate (project.templatePaths, "flash/hxml/" + buildType + ".hxml");
+
+ var context = project.templateContext;
+ context.WIN_FLASHBACKGROUND = StringTools.hex (project.window.background, 6);
+ context.OUTPUT_DIR = targetDirectory;
+
+ var template = new Template (File.getContent (hxml));
+
+ return template.execute (context) + "\n-D display";
+
+ }
+
+
+ public override function run ():Void {
+
+ if (traceEnabled) {
+
+ FlashHelper.enableLogging ();
+ logLength = FlashHelper.getLogLength ();
+
+ }
+
+ if (project.app.url != null && project.app.url != "") {
+
+ ProcessHelper.openURL (project.app.url);
+
+ } else {
+
+ var destination = targetDirectory + "/bin";
+ var targetPath = project.app.file + ".swf";
+
+ if (project.targetFlags.exists ("web")) {
+
+ HTML5Helper.launch (project, targetDirectory + "/bin");
+
+ } else {
+
+ if (traceEnabled) {
+
+ #if neko Thread.create (function () { #end
+
+ FlashHelper.run (project, destination, targetPath);
+ //Sys.exit (0);
+
+ #if neko }); #end
+
+ Sys.sleep (0.1);
+
+ } else {
+
+ FlashHelper.run (project, destination, targetPath);
+
+ }
+
+ }
+
+ }
+
+ }
+
+
+ public override function trace ():Void {
+
+ FlashHelper.enableLogging ();
+ FlashHelper.tailLog (logLength);
+
+ }
+
+
+ public override function update ():Void {
+
+ var destination = targetDirectory + "/bin/";
+ PathHelper.mkdir (destination);
+
+ // project = project.clone ();
+
+ embedded = FlashHelper.embedAssets (project, targetDirectory);
+
+ var context = generateContext ();
+ context.OUTPUT_DIR = targetDirectory;
+
+ FileHelper.recursiveSmartCopyTemplate (project, "haxe", targetDirectory + "/haxe", context);
+ FileHelper.recursiveSmartCopyTemplate (project, "flash/hxml", targetDirectory + "/haxe", context);
+ FileHelper.recursiveSmartCopyTemplate (project, "flash/haxe", targetDirectory + "/haxe", context, true, false);
+
+ if (project.targetFlags.exists ("web") || project.app.url != "") {
+
+ PathHelper.mkdir (destination);
+ FileHelper.recursiveSmartCopyTemplate (project, "flash/templates/web", destination, generateContext ());
+
+ }
+
+ if (embedded) {
+
+ var files = [ "debug.hxml", "release.hxml", "final.hxml" ];
+ var path, hxml, lines, output;
+
+ for (file in files) {
+
+ path = targetDirectory + "/haxe/" + file;
+ hxml = File.getContent (path);
+
+ if (hxml.indexOf ("-swf-header") > -1) {
+
+ lines = ~/[\r\n]+/g.split (hxml);
+ output = [];
+
+ for (line in lines) {
+
+ if (line.indexOf ("-swf-header") > -1) continue;
+ output.push (line);
+
+ }
+
+ if (output.length < lines.length) {
+
+ File.saveContent (path, output.join ("\n"));
+
+ }
+
+ }
+
+ }
+
+ }
+
+ for (asset in project.assets) {
+
+ if (asset.type == AssetType.TEMPLATE || asset.embed == false /*|| !usesLime*/) {
+
+ var path = PathHelper.combine (destination, asset.targetPath);
+
+ PathHelper.mkdir (Path.directory (path));
+ FileHelper.copyAsset (asset, path, context);
+
+ }
+
+ }
+
+ }
+
+
+ /*private function getIcon (size:Int, targetPath:String):Void {
+
+ var icon = icons.findIcon (size, size);
+
+ if (icon != "") {
+
+ FileHelper.copyIfNewer (icon, targetPath);
+
+ } else {
+
+ icons.updateIcon (size, size, targetPath);
+
+ }
+
+ }*/
+
+
+ public override function watch ():Void {
+
+ var dirs = WatchHelper.processHXML (project, getDisplayHXML ());
+ var command = WatchHelper.getCurrentCommand ();
+ WatchHelper.watch (project, command, dirs);
+
+ }
+
+
+ @ignore public override function install ():Void {}
+ @ignore public override function rebuild ():Void {}
+ @ignore public override function uninstall ():Void {}
+
+}
\ No newline at end of file
diff --git a/tools/platforms/HTML5Platform.hx b/tools/platforms/HTML5Platform.hx
new file mode 100644
index 000000000..ade6f0894
--- /dev/null
+++ b/tools/platforms/HTML5Platform.hx
@@ -0,0 +1,496 @@
+package;
+
+
+import haxe.io.Path;
+import haxe.Template;
+// import lime.text.Font;
+import hxp.helpers.DeploymentHelper;
+import hxp.helpers.ElectronHelper;
+import hxp.helpers.FileHelper;
+import hxp.helpers.HTML5Helper;
+import hxp.helpers.IconHelper;
+import hxp.helpers.LogHelper;
+import hxp.helpers.ModuleHelper;
+import hxp.helpers.PathHelper;
+import hxp.helpers.ProcessHelper;
+import hxp.helpers.WatchHelper;
+import hxp.project.AssetType;
+import hxp.project.HXProject;
+import hxp.project.Icon;
+import hxp.project.PlatformTarget;
+import sys.io.File;
+import sys.FileSystem;
+
+
+class HTML5Platform extends PlatformTarget {
+
+
+ private var dependencyPath:String;
+ private var outputFile:String;
+
+
+ public function new (command:String, _project:HXProject, targetFlags:Map ) {
+
+ super (command, _project, targetFlags);
+
+ initialize (command, _project);
+
+ }
+
+
+ public override function build ():Void {
+
+ ModuleHelper.buildModules (project, targetDirectory + "/obj", targetDirectory + "/bin");
+
+ if (project.app.main != null) {
+
+ var type = "release";
+
+ if (project.debug) {
+
+ type = "debug";
+
+ } else if (project.targetFlags.exists ("final")) {
+
+ type = "final";
+
+ }
+
+ var hxml = targetDirectory + "/haxe/" + type + ".hxml";
+ ProcessHelper.runCommand ("", "haxe", [ hxml ] );
+
+ if (noOutput) return;
+
+ HTML5Helper.encodeSourceMappingURL (targetDirectory + "/bin/" + project.app.file + ".js");
+
+ if (project.targetFlags.exists ("webgl")) {
+
+ FileHelper.copyFile (targetDirectory + "/obj/ApplicationMain.js", outputFile);
+
+ }
+
+ if (project.modules.iterator ().hasNext ()) {
+
+ ModuleHelper.patchFile (outputFile);
+
+ }
+
+ if (project.targetFlags.exists ("minify") || type == "final") {
+
+ HTML5Helper.minify (project, targetDirectory + "/bin/" + project.app.file + ".js");
+
+ }
+
+ }
+
+ }
+
+
+ public override function clean ():Void {
+
+ if (FileSystem.exists (targetDirectory)) {
+
+ PathHelper.removeDirectory (targetDirectory);
+
+ }
+
+ }
+
+
+ public override function deploy ():Void {
+
+ var name = "HTML5";
+
+ if (targetFlags.exists ("electron")) {
+
+ name = "Electron";
+
+ }
+
+ DeploymentHelper.deploy (project, targetFlags, targetDirectory, name);
+
+ }
+
+
+ public override function display ():Void {
+
+ Sys.println (getDisplayHXML ());
+
+ }
+
+
+ private function getDisplayHXML ():String {
+
+ var type = "html5";
+
+ if (targetFlags.exists ("electron")) {
+
+ type = "electron";
+
+ }
+
+ var hxml = PathHelper.findTemplate (project.templatePaths, type + "/hxml/" + buildType + ".hxml");
+
+ var context = project.templateContext;
+ context.OUTPUT_DIR = targetDirectory;
+ context.OUTPUT_FILE = outputFile;
+
+ var template = new Template (File.getContent (hxml));
+
+ return template.execute (context) + "\n-D display";
+
+ }
+
+
+ private function initialize (command:String, project:HXProject):Void {
+
+ if (targetFlags.exists ("electron")) {
+
+ targetDirectory = PathHelper.combine (project.app.path, project.config.getString ("electron.output-directory", "electron"));
+
+ } else {
+
+ targetDirectory = PathHelper.combine (project.app.path, project.config.getString ("html5.output-directory", "html5"));
+
+ }
+
+ dependencyPath = project.config.getString ("html5.dependency-path", "lib");
+
+ if (targetFlags.exists ("electron")) {
+
+ dependencyPath = project.config.getString ("html5.dependency-path", dependencyPath);
+
+ }
+
+ outputFile = targetDirectory + "/bin/" + project.app.file + ".js";
+
+ }
+
+
+ public override function run ():Void {
+
+ if (targetFlags.exists ("electron")) {
+
+ ElectronHelper.launch (project, targetDirectory + "/bin");
+
+ } else {
+
+ HTML5Helper.launch (project, targetDirectory + "/bin");
+
+ }
+
+ }
+
+
+ public override function update ():Void {
+
+ // project = project.clone ();
+
+ var destination = targetDirectory + "/bin/";
+ PathHelper.mkdir (destination);
+
+ var webfontDirectory = targetDirectory + "/obj/webfont";
+ var useWebfonts = true;
+
+ for (haxelib in project.haxelibs) {
+
+ if (haxelib.name == "openfl-html5-dom" || haxelib.name == "openfl-bitfive") {
+
+ useWebfonts = false;
+
+ }
+
+ }
+
+ var fontPath;
+
+ for (asset in project.assets) {
+
+ if (asset.type == AssetType.FONT && asset.targetPath != null) {
+
+ if (useWebfonts) {
+
+ fontPath = PathHelper.combine (webfontDirectory, Path.withoutDirectory (asset.targetPath));
+
+ if (!FileSystem.exists (fontPath)) {
+
+ PathHelper.mkdir (webfontDirectory);
+ FileHelper.copyFile (asset.sourcePath, fontPath);
+
+ var originalPath = asset.sourcePath;
+ asset.sourcePath = fontPath;
+
+ HTML5Helper.generateWebfonts (project, asset);
+
+ var ext = "." + Path.extension (asset.sourcePath);
+ var source = Path.withoutExtension (asset.sourcePath);
+ var extensions = [ ext, ".eot", ".woff", ".svg" ];
+
+ for (extension in extensions) {
+
+ if (!FileSystem.exists (source + extension)) {
+
+ if (extension != ".eot" && extension != ".svg") {
+
+ LogHelper.warn ("Could not generate *" + extension + " web font for \"" + originalPath + "\"");
+
+ }
+
+ }
+
+ }
+
+ }
+
+ asset.sourcePath = fontPath;
+ asset.targetPath = Path.withoutExtension (asset.targetPath);
+
+ } else {
+
+ project.haxeflags.push (HTML5Helper.generateFontData (project, asset));
+
+ }
+
+ }
+
+ }
+
+ if (project.targetFlags.exists ("xml")) {
+
+ project.haxeflags.push ("-xml " + targetDirectory + "/types.xml");
+
+ }
+
+ if (LogHelper.verbose) {
+
+ project.haxedefs.set ("verbose", 1);
+
+ }
+
+ ModuleHelper.updateProject (project);
+
+ var libraryNames = new Map ();
+
+ for (asset in project.assets) {
+
+ if (asset.library != null && !libraryNames.exists (asset.library)) {
+
+ libraryNames[asset.library] = true;
+
+ }
+
+ }
+
+ //for (library in libraryNames.keys ()) {
+ //
+ //project.haxeflags.push ("-resource " + targetDirectory + "/obj/manifest/" + library + ".json@__ASSET_MANIFEST__" + library);
+ //
+ //}
+
+ //project.haxeflags.push ("-resource " + targetDirectory + "/obj/manifest/default.json@__ASSET_MANIFEST__default");
+
+ var context = project.templateContext;
+
+ context.WIN_FLASHBACKGROUND = project.window.background != null ? StringTools.hex (project.window.background, 6) : "";
+ context.OUTPUT_DIR = targetDirectory;
+ context.OUTPUT_FILE = outputFile;
+
+ if (project.targetFlags.exists ("webgl")) {
+
+ context.CPP_DIR = targetDirectory + "/obj";
+
+ }
+
+ context.favicons = [];
+
+ var icons = project.icons;
+
+ if (icons.length == 0) {
+
+ icons = [ new Icon (PathHelper.findTemplate (project.templatePaths, "default/icon.svg")) ];
+
+ }
+
+ //if (IconHelper.createWindowsIcon (icons, PathHelper.combine (destination, "favicon.ico"))) {
+ //
+ //context.favicons.push ({ rel: "icon", type: "image/x-icon", href: "./favicon.ico" });
+ //
+ //}
+
+ if (IconHelper.createIcon (icons, 192, 192, PathHelper.combine (destination, "favicon.png"))) {
+
+ context.favicons.push ({ rel: "shortcut icon", type: "image/png", href: "./favicon.png" });
+
+ }
+
+ context.linkedLibraries = [];
+
+ for (dependency in project.dependencies) {
+
+ if (StringTools.endsWith (dependency.name, ".js")) {
+
+ context.linkedLibraries.push (dependency.name);
+
+ } else if (StringTools.endsWith (dependency.path, ".js") && FileSystem.exists (dependency.path)) {
+
+ var name = Path.withoutDirectory (dependency.path);
+
+ context.linkedLibraries.push ("./" + dependencyPath + "/" + name);
+ FileHelper.copyIfNewer (dependency.path, PathHelper.combine (destination, PathHelper.combine (dependencyPath, name)));
+
+ }
+
+ }
+
+ for (asset in project.assets) {
+
+ var path = PathHelper.combine (destination, asset.targetPath);
+
+ if (asset.type != AssetType.TEMPLATE) {
+
+ if (/*asset.embed != true &&*/ asset.type != AssetType.FONT) {
+
+ PathHelper.mkdir (Path.directory (path));
+ FileHelper.copyAssetIfNewer (asset, path);
+
+ } else if (asset.type == AssetType.FONT && useWebfonts) {
+
+ PathHelper.mkdir (Path.directory (path));
+ var ext = "." + Path.extension (asset.sourcePath);
+ var source = Path.withoutExtension (asset.sourcePath);
+
+ var hasFormat = [ false, false, false, false ];
+ var extensions = [ ext, ".eot", ".svg", ".woff" ];
+ var extension;
+
+ for (i in 0...extensions.length) {
+
+ extension = extensions[i];
+
+ if (FileSystem.exists (source + extension)) {
+
+ FileHelper.copyIfNewer (source + extension, path + extension);
+ hasFormat[i] = true;
+
+ }
+
+ }
+
+ var shouldEmbedFont = false;
+
+ for (embedded in hasFormat) {
+ if (embedded) shouldEmbedFont = true;
+ }
+
+ var embeddedAssets:Array = cast context.assets;
+ for (embeddedAsset in embeddedAssets) {
+
+ if (embeddedAsset.type == "font" && embeddedAsset.sourcePath == asset.sourcePath) {
+
+ // var font = Font.fromFile (asset.sourcePath);
+
+ // embeddedAsset.ascender = font.ascender;
+ // embeddedAsset.descender = font.descender;
+ // embeddedAsset.height = font.height;
+ // embeddedAsset.numGlyphs = font.numGlyphs;
+ // embeddedAsset.underlinePosition = font.underlinePosition;
+ // embeddedAsset.underlineThickness = font.underlineThickness;
+ // embeddedAsset.unitsPerEM = font.unitsPerEM;
+
+ embeddedAsset.ascender = 0;
+ embeddedAsset.descender = 0;
+ embeddedAsset.height = 0;
+ embeddedAsset.numGlyphs = 0;
+ embeddedAsset.underlinePosition = 0;
+ embeddedAsset.underlineThickness = 0;
+ embeddedAsset.unitsPerEM = 0;
+ embeddedAsset.fontName = "sans";
+
+ if (shouldEmbedFont) {
+
+ var urls = [];
+ if (hasFormat[1]) urls.push ("url('" + embeddedAsset.targetPath + ".eot?#iefix') format('embedded-opentype')");
+ if (hasFormat[3]) urls.push ("url('" + embeddedAsset.targetPath + ".woff') format('woff')");
+ urls.push ("url('" + embeddedAsset.targetPath + ext + "') format('truetype')");
+ if (hasFormat[2]) urls.push ("url('" + embeddedAsset.targetPath + ".svg#" + StringTools.urlEncode (embeddedAsset.fontName) + "') format('svg')");
+
+ var fontFace = "\t\t@font-face {\n";
+ fontFace += "\t\t\tfont-family: '" + embeddedAsset.fontName + "';\n";
+ // if (hasFormat[1]) fontFace += "\t\t\tsrc: url('" + embeddedAsset.targetPath + ".eot');\n";
+ fontFace += "\t\t\tsrc: " + urls.join (",\n\t\t\t") + ";\n";
+ fontFace += "\t\t\tfont-weight: normal;\n";
+ fontFace += "\t\t\tfont-style: normal;\n";
+ fontFace += "\t\t}\n";
+
+ embeddedAsset.cssFontFace = fontFace;
+
+ }
+ break;
+
+ }
+
+ }
+
+ }
+
+ }
+
+ }
+
+ FileHelper.recursiveSmartCopyTemplate (project, "html5/template", destination, context);
+
+ if (project.app.main != null) {
+
+ FileHelper.recursiveSmartCopyTemplate (project, "haxe", targetDirectory + "/haxe", context);
+ FileHelper.recursiveSmartCopyTemplate (project, "html5/haxe", targetDirectory + "/haxe", context, true, false);
+ FileHelper.recursiveSmartCopyTemplate (project, "html5/hxml", targetDirectory + "/haxe", context);
+
+ }
+
+ if (targetFlags.exists ("electron")) {
+
+ FileHelper.recursiveSmartCopyTemplate (project, "electron/template", destination, context);
+
+ if (project.app.main != null) {
+
+ FileHelper.recursiveSmartCopyTemplate (project, "electron/haxe", targetDirectory + "/haxe", context, true, false);
+ FileHelper.recursiveSmartCopyTemplate (project, "electron/hxml", targetDirectory + "/haxe", context);
+
+ }
+
+ }
+
+ for (asset in project.assets) {
+
+ var path = PathHelper.combine (destination, asset.targetPath);
+
+ if (asset.type == AssetType.TEMPLATE) {
+
+ PathHelper.mkdir (Path.directory (path));
+ FileHelper.copyAsset (asset, path, context);
+
+ }
+
+ }
+
+ }
+
+
+ public override function watch ():Void {
+
+ // TODO: Use a custom live reload HTTP server for test/run instead
+
+ var dirs = WatchHelper.processHXML (project, getDisplayHXML ());
+ var command = WatchHelper.getCurrentCommand ();
+ WatchHelper.watch (project, command, dirs);
+
+ }
+
+
+ @ignore public override function install ():Void {}
+ @ignore public override function rebuild ():Void {}
+ @ignore public override function trace ():Void {}
+ @ignore public override function uninstall ():Void {}
+
+
+}
\ No newline at end of file
diff --git a/tools/platforms/IOSPlatform.hx b/tools/platforms/IOSPlatform.hx
new file mode 100644
index 000000000..70f5e64a6
--- /dev/null
+++ b/tools/platforms/IOSPlatform.hx
@@ -0,0 +1,775 @@
+package;
+
+
+//import openfl.display.BitmapData;
+import haxe.io.Path;
+import haxe.Json;
+import haxe.Template;
+import hxp.helpers.ArrayHelper;
+import hxp.helpers.CPPHelper;
+import hxp.helpers.DeploymentHelper;
+import hxp.helpers.FileHelper;
+import hxp.helpers.IconHelper;
+import hxp.helpers.IOSHelper;
+import hxp.helpers.LogHelper;
+import hxp.helpers.PathHelper;
+import hxp.helpers.PlatformHelper;
+import hxp.helpers.ProcessHelper;
+import hxp.helpers.StringHelper;
+import hxp.helpers.WatchHelper;
+import lime.graphics.Image;
+import hxp.project.Architecture;
+import hxp.project.Asset;
+import hxp.project.AssetType;
+import hxp.project.Haxelib;
+import hxp.project.HXProject;
+import hxp.project.Icon;
+import hxp.project.Keystore;
+import hxp.project.NDLL;
+import hxp.project.Platform;
+import hxp.project.PlatformTarget;
+import sys.io.File;
+import sys.FileSystem;
+
+
+class IOSPlatform extends PlatformTarget {
+
+
+ public function new (command:String, _project:HXProject, targetFlags:Map ) {
+
+ super (command, _project, targetFlags);
+
+ targetDirectory = PathHelper.combine (project.app.path, project.config.getString ("ios.output-directory", "ios"));
+
+ }
+
+
+ public override function build ():Void {
+
+ if (project.targetFlags.exists ("xcode") && PlatformHelper.hostPlatform == Platform.MAC) {
+
+ ProcessHelper.runCommand ("", "open", [ targetDirectory + "/" + project.app.file + ".xcodeproj" ] );
+
+ } else {
+
+ IOSHelper.build (project, targetDirectory);
+
+ if (noOutput) return;
+
+ if (!project.targetFlags.exists ("simulator")) {
+
+ IOSHelper.sign (project, targetDirectory + "/bin");
+
+ }
+
+ }
+
+ }
+
+
+ public override function clean ():Void {
+
+ if (FileSystem.exists (targetDirectory)) {
+
+ PathHelper.removeDirectory (targetDirectory);
+
+ }
+
+ }
+
+
+ public override function deploy ():Void {
+
+ IOSHelper.deploy (project, targetDirectory);
+
+ }
+
+
+ public override function display ():Void {
+
+ Sys.println (getDisplayHXML ());
+
+ }
+
+
+ private function generateContext ():Dynamic {
+
+ //project = project.clone ();
+
+ project.sources.unshift ("");
+ project.sources = PathHelper.relocatePaths (project.sources, PathHelper.combine (targetDirectory, project.app.file + "/haxe"));
+ //project.dependencies.push ("stdc++");
+
+ if (project.targetFlags.exists ("xml")) {
+
+ project.haxeflags.push ("-xml " + targetDirectory + "/types.xml");
+
+ }
+
+ if (project.targetFlags.exists ("final")) {
+
+ project.haxedefs.set ("final", "");
+
+ }
+
+ if (!project.config.exists ("ios.identity")) {
+
+ project.config.set ("ios.identity", "iPhone Developer");
+
+ }
+
+ IOSHelper.getIOSVersion (project);
+ project.haxedefs.set ("IPHONE_VER", project.environment.get ("IPHONE_VER"));
+
+ project.haxedefs.set ("HXCPP_CPP11", "1");
+
+ if (project.config.getString ("ios.compiler") == "llvm" || project.config.getString ("ios.compiler", "clang") == "clang") {
+
+ project.haxedefs.set ("HXCPP_CLANG", "1");
+ project.haxedefs.set ("OBJC_ARC", "1");
+
+ }
+
+ var context = project.templateContext;
+
+ context.HAS_ICON = false;
+ context.HAS_LAUNCH_IMAGE = false;
+ context.OBJC_ARC = false;
+ context.KEY_STORE_IDENTITY = project.config.getString ("ios.identity");
+
+ if (project.config.exists ("ios.provisioning-profile")) {
+
+ context.IOS_PROVISIONING_PROFILE = PathHelper.tryFullPath (project.config.getString ("ios.provisioning-profile"));
+
+ }
+
+ if (project.config.exists ("ios.team-id")) {
+
+ context.DEVELOPMENT_TEAM_ID = project.config.getString ("ios.team-id");
+
+ }
+
+ context.linkedLibraries = [];
+
+ for (dependency in project.dependencies) {
+
+ if (!StringTools.endsWith (dependency.name, ".framework") && !StringTools.endsWith (dependency.name, ".tbd") && !StringTools.endsWith (dependency.path, ".framework")) {
+
+ if (dependency.path != "") {
+
+ var name = Path.withoutDirectory (Path.withoutExtension (dependency.path));
+
+ if (dependency.forceLoad) {
+
+ project.config.push ("ios.linker-flags", "-force_load $SRCROOT/$PRODUCT_NAME/lib/$CURRENT_ARCH/" + Path.withoutDirectory (dependency.path));
+
+ }
+
+ if (StringTools.startsWith (name, "lib")) {
+
+ name = name.substring (3, name.length);
+
+ }
+
+ context.linkedLibraries.push (name);
+
+ } else if (dependency.name != "") {
+
+ context.linkedLibraries.push (dependency.name);
+
+ }
+
+ }
+
+ }
+
+ var valid_archs = new Array ();
+ var armv6 = false;
+ var armv7 = false;
+ var armv7s = false;
+ var arm64 = false;
+ var architectures = project.architectures;
+
+ if (architectures == null || architectures.length == 0) {
+
+ architectures = [ Architecture.ARMV7, Architecture.ARM64 ];
+
+ }
+
+ if (project.config.getString ("ios.device", "universal") == "universal" || project.config.getString ("ios.device") == "iphone") {
+
+ if (project.config.getFloat ("ios.deployment", 8) < 5) {
+
+ ArrayHelper.addUnique (architectures, Architecture.ARMV6);
+
+ }
+
+ }
+
+ for (architecture in project.architectures) {
+
+ switch (architecture) {
+
+ case ARMV6: valid_archs.push ("armv6"); armv6 = true;
+ case ARMV7: valid_archs.push ("armv7"); armv7 = true;
+ case ARMV7S: valid_archs.push ("armv7s"); armv7s = true;
+ case ARM64: valid_archs.push ("arm64"); arm64 = true;
+ default:
+
+ }
+
+ }
+
+ context.CURRENT_ARCHS = "( " + valid_archs.join(",") + ") ";
+
+ valid_archs.push ("x86_64");
+ valid_archs.push ("i386");
+
+ context.VALID_ARCHS = valid_archs.join(" ");
+ context.THUMB_SUPPORT = armv6 ? "GCC_THUMB_SUPPORT = NO;" : "";
+
+ var requiredCapabilities = [];
+
+ if (!armv6 && armv7) {
+
+ requiredCapabilities.push ({ name: "armv7", value: true });
+
+ } else if (!armv6 && !armv7 && armv7s) {
+
+ requiredCapabilities.push ({ name: "armv7s", value: true });
+
+ } else if (!armv6 && !armv7 && !armv7s && arm64) {
+
+ requiredCapabilities.push ({ name: "arm64", value: true });
+
+ }
+
+ context.REQUIRED_CAPABILITY = requiredCapabilities;
+ context.ARMV6 = armv6;
+ context.ARMV7 = armv7;
+ context.ARMV7S = armv7s;
+ context.ARM64 = arm64;
+ context.TARGET_DEVICES = switch (project.config.getString ("ios.device", "universal")) { case "iphone": "1"; case "ipad": "2"; default: "1,2"; }
+ context.DEPLOYMENT = project.config.getString ("ios.deployment", "8.0");
+
+ if (project.config.getString ("ios.compiler") == "llvm" || project.config.getString ("ios.compiler", "clang") == "clang") {
+
+ context.OBJC_ARC = true;
+
+ }
+
+ //context.ENABLE_BITCODE = (project.config.getFloat ("ios.deployment", 8) >= 6);
+ context.ENABLE_BITCODE = project.config.getBool ("ios.enable-bitcode", false);
+ context.IOS_COMPILER = project.config.getString ("ios.compiler", "clang");
+ context.CPP_BUILD_LIBRARY = project.config.getString ("cpp.buildLibrary", "hxcpp");
+
+ var json = Json.parse (File.getContent (PathHelper.getHaxelib (new Haxelib ("hxcpp"), true) + "/haxelib.json"));
+
+ if (Std.parseFloat (json.version) > 3.1) {
+
+ context.CPP_LIBPREFIX = "lib";
+
+ } else {
+
+ context.CPP_LIBPREFIX = "";
+
+ }
+
+ context.IOS_LINKER_FLAGS = ["-stdlib=libc++"].concat (project.config.getArrayString ("ios.linker-flags"));
+ context.IOS_NON_EXEMPT_ENCRYPTION = project.config.getBool ("ios.non-exempt-encryption", true);
+
+ switch (project.window.orientation) {
+
+ case PORTRAIT:
+ context.IOS_APP_ORIENTATION = "UIInterfaceOrientationPortraitUIInterfaceOrientationPortraitUpsideDown";
+ case LANDSCAPE:
+ context.IOS_APP_ORIENTATION = "UIInterfaceOrientationLandscapeLeftUIInterfaceOrientationLandscapeRight";
+ case ALL:
+ context.IOS_APP_ORIENTATION = "UIInterfaceOrientationLandscapeLeftUIInterfaceOrientationLandscapeRightUIInterfaceOrientationPortraitUIInterfaceOrientationPortraitUpsideDown";
+ //case "allButUpsideDown":
+ //context.IOS_APP_ORIENTATION = "UIInterfaceOrientationLandscapeLeftUIInterfaceOrientationLandscapeRightUIInterfaceOrientationPortrait";
+ default:
+ context.IOS_APP_ORIENTATION = "UIInterfaceOrientationLandscapeLeftUIInterfaceOrientationLandscapeRightUIInterfaceOrientationPortraitUIInterfaceOrientationPortraitUpsideDown";
+
+ }
+
+ context.ADDL_PBX_BUILD_FILE = "";
+ context.ADDL_PBX_FILE_REFERENCE = "";
+ context.ADDL_PBX_FRAMEWORKS_BUILD_PHASE = "";
+ context.ADDL_PBX_FRAMEWORK_GROUP = "";
+
+ context.frameworkSearchPaths = [];
+
+ for (dependency in project.dependencies) {
+
+ var name = null;
+ var path = null;
+ var fileType = null;
+
+ if (Path.extension (dependency.name) == "framework") {
+
+ name = dependency.name;
+ path = "/System/Library/Frameworks/" + dependency.name;
+ fileType = "wrapper.framework";
+
+ } else if (Path.extension (dependency.name) == "tbd") {
+
+ name = dependency.name;
+ path = "/usr/lib/" + dependency.name;
+ fileType = "sourcecode.text-based-dylib-definition";
+
+ } else if (Path.extension (dependency.path) == "framework") {
+
+ name = Path.withoutDirectory (dependency.path);
+ path = PathHelper.tryFullPath (dependency.path);
+ fileType = "wrapper.framework";
+
+ }
+
+ if (name != null) {
+
+ var frameworkID = "11C0000000000018" + StringHelper.getUniqueID ();
+ var fileID = "11C0000000000018" + StringHelper.getUniqueID ();
+
+ ArrayHelper.addUnique (context.frameworkSearchPaths, Path.directory (path));
+
+ context.ADDL_PBX_BUILD_FILE += " " + frameworkID + " /* " + name + " in Frameworks */ = {isa = PBXBuildFile; fileRef = " + fileID + " /* " + name + " */; };\n";
+ context.ADDL_PBX_FILE_REFERENCE += " " + fileID + " /* " + name + " */ = {isa = PBXFileReference; lastKnownFileType = \"" + fileType + "\"; name = \"" + name + "\"; path = \"" + path + "\"; sourceTree = SDKROOT; };\n";
+ context.ADDL_PBX_FRAMEWORKS_BUILD_PHASE += " " + frameworkID + " /* " + name + " in Frameworks */,\n";
+ context.ADDL_PBX_FRAMEWORK_GROUP += " " + fileID + " /* " + name + " */,\n";
+
+ }
+
+ }
+
+ context.HXML_PATH = PathHelper.findTemplate (project.templatePaths, "iphone/PROJ/haxe/Build.hxml", false);
+ if (context.HXML_PATH == null) context.HXML_PATH = PathHelper.findTemplate (project.templatePaths, "ios/template/{{app.file}}/haxe/Build.hxml");
+ context.PRERENDERED_ICON = project.config.getBool ("ios.prerenderedIcon", false);
+
+ var allowInsecureHTTP = project.config.getString ("ios.allow-insecure-http", "*");
+
+ if (allowInsecureHTTP != "*" && allowInsecureHTTP != "true") {
+
+ var sites = [];
+
+ if (allowInsecureHTTP != "false") {
+
+ var domains = project.config.getArrayString ("ios.allow-insecure-http");
+
+ for (domain in domains) {
+
+ sites.push ({ domain: domain });
+
+ }
+
+ }
+
+ context.IOS_ALLOW_INSECURE_HTTP = sites;
+
+ }
+
+ var haxelibPath = project.environment.get ("HAXELIB_PATH");
+
+ if (haxelibPath != null) {
+
+ context.HAXELIB_PATH = 'export HAXELIB_PATH="$haxelibPath";';
+
+ } else {
+
+ context.HAXELIB_PATH = '';
+
+ }
+
+ return context;
+
+ }
+
+
+ private function getDisplayHXML ():String {
+
+ var hxml = PathHelper.findTemplate (project.templatePaths, "iphone/PROJ/haxe/Build.hxml", false);
+ if (hxml == null) hxml = PathHelper.findTemplate (project.templatePaths, "iphone/template/{{app.file}}/Build.hxml", true);
+ var template = new Template (File.getContent (hxml));
+
+ // project = project.clone ();
+ var context = generateContext ();
+ context.OUTPUT_DIR = targetDirectory;
+
+ return template.execute (context) + "\n-D display";
+
+ }
+
+
+ public override function rebuild ():Void {
+
+ var armv6 = (project.architectures.indexOf (Architecture.ARMV6) > -1 && !project.targetFlags.exists ("simulator"));
+ var armv7 = (command == "rebuild" || (project.architectures.indexOf (Architecture.ARMV7) > -1 && !project.targetFlags.exists ("simulator")));
+ var armv7s = (project.architectures.indexOf (Architecture.ARMV7S) > -1 && !project.targetFlags.exists ("simulator"));
+ var arm64 = (command == "rebuild" || (project.architectures.indexOf (Architecture.ARM64) > -1 && !project.targetFlags.exists ("simulator")));
+ var i386 = (command == "rebuild" || project.targetFlags.exists ("simulator"));
+ var x86_64 = (command == "rebuild" || project.targetFlags.exists ("simulator"));
+
+ var arc = (project.targetFlags.exists ("arc"));
+
+ var commands = [];
+
+ if (armv6) commands.push ([ "-Dios", "-DHXCPP_CPP11" ]);
+ if (armv7) commands.push ([ "-Dios", "-DHXCPP_CPP11", "-DHXCPP_ARMV7" ]);
+ if (armv7s) commands.push ([ "-Dios", "-DHXCPP_CPP11", "-DHXCPP_ARMV7S" ]);
+ if (arm64) commands.push ([ "-Dios", "-DHXCPP_CPP11", "-DHXCPP_ARM64" ]);
+ if (i386) commands.push ([ "-Dios", "-Dsimulator", "-DHXCPP_CPP11" ]);
+ if (x86_64) commands.push ([ "-Dios", "-Dsimulator", "-DHXCPP_M64", "-DHXCPP_CPP11" ]);
+
+ if (arc) {
+
+ for (command in commands) {
+
+ command.push ("-DOBJC_ARC");
+
+ }
+
+ }
+
+ IOSHelper.getIOSVersion (project);
+ var iphoneVer = project.environment.get ("IPHONE_VER");
+
+ for (command in commands) {
+
+ command.push ("-DIPHONE_VER=" + iphoneVer);
+
+ }
+
+ CPPHelper.rebuild (project, commands);
+
+ }
+
+
+ public override function run ():Void {
+
+ if (project.targetFlags.exists ("xcode")) return;
+
+ IOSHelper.launch (project, targetDirectory);
+
+ }
+
+
+ public override function update ():Void {
+
+ // project = project.clone ();
+
+ for (asset in project.assets) {
+
+ if (asset.embed && asset.sourcePath == "") {
+
+ var path = PathHelper.combine (targetDirectory + "/" + project.app.file + "/obj/tmp", asset.targetPath);
+ PathHelper.mkdir (Path.directory (path));
+ FileHelper.copyAsset (asset, path);
+ asset.sourcePath = path;
+
+ }
+
+ }
+
+ //var manifest = new Asset ();
+ //manifest.id = "__manifest__";
+ //manifest.data = AssetHelper.createManifest (project).serialize ();
+ //manifest.resourceName = manifest.flatName = manifest.targetPath = "manifest";
+ //manifest.type = AssetType.TEXT;
+ //project.assets.push (manifest);
+
+ var context = generateContext ();
+ context.OUTPUT_DIR = targetDirectory;
+
+ var projectDirectory = targetDirectory + "/" + project.app.file + "/";
+
+ PathHelper.mkdir (targetDirectory);
+ PathHelper.mkdir (projectDirectory);
+ PathHelper.mkdir (projectDirectory + "/haxe");
+ PathHelper.mkdir (projectDirectory + "/haxe/lime/installer");
+
+ var iconSizes:Array = [
+ { name: "Icon-20.png", size: 20 },
+ { name: "Icon-Small.png", size: 29 },
+ { name: "Icon-Small-40.png", size: 40 },
+ { name: "Icon-20@2x.png", size: 40 },
+ { name: "Icon-Small-50.png", size: 50 },
+ { name: "Icon.png", size: 57 },
+ { name: "Icon-Small@2x.png", size: 58 },
+ { name: "Icon-20@3x.png", size: 60 },
+ { name: "Icon-72.png", size: 72 },
+ { name: "Icon-76.png", size: 76 },
+ { name: "Icon-Small-40@2x.png", size: 80 },
+ { name: "Icon-Small@3x.png", size: 87 },
+ { name: "Icon-Small-50@2x.png", size: 100 },
+ { name: "Icon@2x.png", size: 114 },
+ { name: "Icon-60@2x.png", size: 120 },
+ { name: "Icon-Small-40@3x.png", size: 120 },
+ { name: "Icon-72@2x.png", size: 144 },
+ { name: "Icon-76@2x.png", size: 152 },
+ { name: "Icon-83.5@2x.png", size: 167 },
+ { name: "Icon-60@3x.png", size: 180 },
+ { name: "Icon-Marketing.png", size: 1024 }
+ ];
+
+ context.HAS_ICON = true;
+
+ var iconPath = PathHelper.combine (projectDirectory, "Images.xcassets/AppIcon.appiconset");
+ PathHelper.mkdir (iconPath);
+
+ var icons = project.icons;
+
+ if (icons.length == 0) {
+
+ icons = [ new Icon (PathHelper.findTemplate (project.templatePaths, "default/icon.svg")) ];
+
+ }
+
+ for (iconSize in iconSizes) {
+
+ if (!IconHelper.createIcon (icons, iconSize.size, iconSize.size, PathHelper.combine (iconPath, iconSize.name))) {
+
+ context.HAS_ICON = false;
+
+ }
+
+ }
+
+ var splashSizes:Array = [
+ { name: "Default.png", w: 320, h: 480 }, // iPhone, portrait
+ { name: "Default@2x.png", w: 640, h: 960 }, // iPhone Retina, portrait
+ { name: "Default-568h@2x.png", w: 640, h: 1136 }, // iPhone 5, portrait
+ { name: "Default-667h@2x.png", w: 750, h: 1334 }, // iPhone 6, portrait
+ { name: "Default-736h@3x.png", w: 1242, h: 2208 }, // iPhone 6 Plus, portrait
+ { name: "Default-Landscape.png", w: 1024, h: 768 }, // iPad, landscape
+ { name: "Default-Landscape@2x.png", w: 2048, h: 1536 }, // iPad Retina, landscape
+ { name: "Default-736h-Landscape@3x.png", w: 2208, h: 1242 }, // iPhone 6 Plus, landscape
+ { name: "Default-Portrait.png", w: 768, h: 1024 }, // iPad, portrait
+ { name: "Default-Portrait@2x.png", w: 1536, h: 2048 }, // iPad Retina, portrait
+ { name: "Default-812h@3x.png", w: 1125, h: 2436 }, // iPhone X, portrait
+ { name: "Default-Landscape-812h@3x.png", w: 2436, h: 1125 } // iPhone X, landscape
+ ];
+
+ var splashScreenPath = PathHelper.combine (projectDirectory, "Images.xcassets/LaunchImage.launchimage");
+ PathHelper.mkdir (splashScreenPath);
+
+ for (size in splashSizes) {
+
+ var match = false;
+
+ for (splashScreen in project.splashScreens) {
+
+ if (splashScreen.width == size.w && splashScreen.height == size.h && Path.extension (splashScreen.path) == "png") {
+
+ FileHelper.copyFile (splashScreen.path, PathHelper.combine (splashScreenPath, size.name));
+ match = true;
+
+ }
+
+ }
+
+ if (!match) {
+
+ var imagePath = PathHelper.combine (splashScreenPath, size.name);
+
+ if (!FileSystem.exists (imagePath)) {
+
+ LogHelper.info ("", " - \x1b[1mGenerating image:\x1b[0m " + imagePath);
+
+ var image = new Image (null, 0, 0, size.w, size.h, (0xFF << 24) | (project.window.background & 0xFFFFFF));
+ var bytes = image.encode ("png");
+
+ File.saveBytes (imagePath, bytes);
+
+ }
+
+ }
+
+ }
+
+ context.HAS_LAUNCH_IMAGE = true;
+
+ PathHelper.mkdir (projectDirectory + "/resources");
+ PathHelper.mkdir (projectDirectory + "/haxe/build");
+
+ // Long deprecated template path
+
+ FileHelper.recursiveSmartCopyTemplate (project, "iphone/resources", projectDirectory + "/resources", context, true, false);
+
+ // New template path
+
+ FileHelper.recursiveSmartCopyTemplate (project, "ios/template", targetDirectory, context);
+
+ // Recently deprecated template paths
+
+ FileHelper.recursiveSmartCopyTemplate (project, "iphone/PROJ/haxe", projectDirectory + "/haxe", context, true, false);
+ FileHelper.recursiveSmartCopyTemplate (project, "haxe", projectDirectory + "/haxe", context, true, false);
+ FileHelper.recursiveSmartCopyTemplate (project, "iphone/PROJ/Classes", projectDirectory + "/Classes", context, true, false);
+ FileHelper.recursiveSmartCopyTemplate (project, "iphone/PROJ/Images.xcassets", projectDirectory + "/Images.xcassets", context, true, false);
+ FileHelper.copyFileTemplate (project.templatePaths, "iphone/PROJ/PROJ-Info.plist", projectDirectory + "/" + project.app.file + "-Info.plist", context, true, false);
+ FileHelper.copyFileTemplate (project.templatePaths, "iphone/PROJ/PROJ-Prefix.pch", projectDirectory + "/" + project.app.file + "-Prefix.pch", context, true, false);
+ FileHelper.recursiveSmartCopyTemplate (project, "iphone/PROJ.xcodeproj", targetDirectory + "/" + project.app.file + ".xcodeproj", context, true, false);
+
+ PathHelper.mkdir (projectDirectory + "/lib");
+
+ for (archID in 0...6) {
+
+ var arch = [ "armv6", "armv7", "armv7s", "arm64", "i386", "x86_64" ][archID];
+
+ if (arch == "armv6" && !context.ARMV6)
+ continue;
+
+ if (arch == "armv7" && !context.ARMV7)
+ continue;
+
+ if (arch == "armv7s" && !context.ARMV7S)
+ continue;
+
+ if (arch == "arm64" && !context.ARM64)
+ continue;
+
+ var libExt = [ ".iphoneos.a", ".iphoneos-v7.a", ".iphoneos-v7s.a", ".iphoneos-64.a", ".iphonesim.a", ".iphonesim-64.a" ][archID];
+
+ PathHelper.mkdir (projectDirectory + "/lib/" + arch);
+ PathHelper.mkdir (projectDirectory + "/lib/" + arch + "-debug");
+
+ for (ndll in project.ndlls) {
+
+ //if (ndll.haxelib != null) {
+
+ var releaseLib = PathHelper.getLibraryPath (ndll, "iPhone", "lib", libExt);
+ var debugLib = PathHelper.getLibraryPath (ndll, "iPhone", "lib", libExt, true);
+ var releaseDest = projectDirectory + "/lib/" + arch + "/lib" + ndll.name + ".a";
+ var debugDest = projectDirectory + "/lib/" + arch + "-debug/lib" + ndll.name + ".a";
+
+ if (!FileSystem.exists (releaseLib)) {
+
+ releaseLib = PathHelper.getLibraryPath (ndll, "iPhone", "lib", ".iphoneos.a");
+ debugLib = PathHelper.getLibraryPath (ndll, "iPhone", "lib", ".iphoneos.a", true);
+
+ }
+
+ FileHelper.copyIfNewer (releaseLib, releaseDest);
+
+ if (FileSystem.exists (debugLib) && debugLib != releaseLib) {
+
+ FileHelper.copyIfNewer (debugLib, debugDest);
+
+ } else if (FileSystem.exists (debugDest)) {
+
+ FileSystem.deleteFile (debugDest);
+
+ }
+
+ //}
+
+ }
+
+ for (dependency in project.dependencies) {
+
+ if (StringTools.endsWith (dependency.path, ".a")) {
+
+ var fileName = Path.withoutDirectory (dependency.path);
+
+ if (!StringTools.startsWith (fileName, "lib")) {
+
+ fileName = "lib" + fileName;
+
+ }
+
+ FileHelper.copyIfNewer (dependency.path, projectDirectory + "/lib/" + arch + "/" + fileName);
+
+ }
+
+ }
+
+ }
+
+ PathHelper.mkdir (projectDirectory + "/assets");
+
+ for (asset in project.assets) {
+
+ if (asset.type != AssetType.TEMPLATE) {
+
+ var targetPath = PathHelper.combine (projectDirectory + "/assets/", asset.resourceName);
+
+ //var sourceAssetPath:String = projectDirectory + "haxe/" + asset.sourcePath;
+
+ PathHelper.mkdir (Path.directory (targetPath));
+ FileHelper.copyAssetIfNewer (asset, targetPath);
+
+ //PathHelper.mkdir (Path.directory (sourceAssetPath));
+ //FileHelper.linkFile (flatAssetPath, sourceAssetPath, true, true);
+
+ } else {
+
+ var targetPath = PathHelper.combine (projectDirectory, asset.targetPath);
+
+ PathHelper.mkdir (Path.directory (targetPath));
+ FileHelper.copyAsset (asset, targetPath, context);
+
+ }
+
+ }
+
+ if (project.targetFlags.exists ("xcode") && PlatformHelper.hostPlatform == Platform.MAC && command == "update") {
+
+ ProcessHelper.runCommand ("", "open", [ targetDirectory + "/" + project.app.file + ".xcodeproj" ] );
+
+ }
+
+ }
+
+
+ /*private function updateLaunchImage () {
+
+ var destination = buildDirectory + "/ios";
+ PathHelper.mkdir (destination);
+
+ var has_launch_image = false;
+ if (launchImages.length > 0) has_launch_image = true;
+
+ for (launchImage in launchImages) {
+
+ var splitPath = launchImage.name.split ("/");
+ var path = destination + "/" + splitPath[splitPath.length - 1];
+ FileHelper.copyFile (launchImage.name, path, context, false);
+
+ }
+
+ context.HAS_LAUNCH_IMAGE = has_launch_image;
+
+ }*/
+
+
+ public override function watch ():Void {
+
+ var dirs = WatchHelper.processHXML (project, getDisplayHXML ());
+ var command = WatchHelper.getCurrentCommand ();
+ WatchHelper.watch (project, command, dirs);
+
+ }
+
+
+ @ignore public override function install ():Void {}
+ @ignore public override function trace ():Void {}
+ @ignore public override function uninstall ():Void {}
+
+
+}
+
+
+private typedef IconSize = {
+
+ name:String,
+ size:Int,
+
+}
+
+
+private typedef SplashSize = {
+
+ name:String,
+ w:Int,
+ h:Int,
+
+}
diff --git a/tools/platforms/LinuxPlatform.hx b/tools/platforms/LinuxPlatform.hx
new file mode 100644
index 000000000..1df61a6d0
--- /dev/null
+++ b/tools/platforms/LinuxPlatform.hx
@@ -0,0 +1,457 @@
+package;
+
+
+import haxe.io.Path;
+import haxe.Template;
+import hxp.helpers.CPPHelper;
+import hxp.helpers.DeploymentHelper;
+import hxp.helpers.FileHelper;
+import hxp.helpers.JavaHelper;
+import hxp.helpers.LogHelper;
+import hxp.helpers.NekoHelper;
+import hxp.helpers.NodeJSHelper;
+import hxp.helpers.PathHelper;
+import hxp.helpers.PlatformHelper;
+import hxp.helpers.ProcessHelper;
+import hxp.helpers.WatchHelper;
+import hxp.project.AssetType;
+import hxp.project.Architecture;
+import hxp.project.Haxelib;
+import hxp.project.HXProject;
+import hxp.project.Platform;
+import hxp.project.PlatformTarget;
+import sys.io.File;
+import sys.io.Process;
+import sys.FileSystem;
+
+
+class LinuxPlatform extends PlatformTarget {
+
+
+ private var applicationDirectory:String;
+ private var executablePath:String;
+ private var is64:Bool;
+ private var isRaspberryPi:Bool;
+ private var targetType:String;
+
+
+ public function new (command:String, _project:HXProject, targetFlags:Map ) {
+
+ super (command, _project, targetFlags);
+
+ for (architecture in project.architectures) {
+
+ if (!targetFlags.exists ("32") && architecture == Architecture.X64) {
+
+ is64 = true;
+
+ } else if (architecture == Architecture.ARMV7) {
+
+ isRaspberryPi = true;
+
+ }
+
+ }
+
+ if (project.targetFlags.exists ("rpi")) {
+
+ isRaspberryPi = true;
+ is64 = false;
+
+ }
+
+ if (project.targetFlags.exists ("neko") || project.target != PlatformHelper.hostPlatform) {
+
+ targetType = "neko";
+
+ } else if (project.targetFlags.exists ("hl")) {
+
+ targetType = "hl";
+
+ } else if (project.targetFlags.exists ("nodejs")) {
+
+ targetType = "nodejs";
+
+ } else if (project.targetFlags.exists ("java")) {
+
+ targetType = "java";
+
+ } else {
+
+ targetType = "cpp";
+
+ }
+
+ targetDirectory = PathHelper.combine (project.app.path, project.config.getString ("linux.output-directory", targetType == "cpp" ? "linux" : targetType));
+ targetDirectory = StringTools.replace (targetDirectory, "arch64", is64 ? "64" : "");
+ applicationDirectory = targetDirectory + "/bin/";
+ executablePath = PathHelper.combine (applicationDirectory, project.app.file);
+
+ }
+
+
+ public override function build ():Void {
+
+ var hxml = targetDirectory + "/haxe/" + buildType + ".hxml";
+
+ PathHelper.mkdir (targetDirectory);
+
+ if (!project.targetFlags.exists ("static") || targetType != "cpp") {
+
+ var targetSuffix = (targetType == "hl") ? ".hdll" : null;
+
+ for (ndll in project.ndlls) {
+
+ if (isRaspberryPi) {
+
+ FileHelper.copyLibrary (project, ndll, "RPi", "", (ndll.haxelib != null && (ndll.haxelib.name == "hxcpp" || ndll.haxelib.name == "hxlibc")) ? ".dso" : ".ndll", applicationDirectory, project.debug, targetSuffix);
+
+ } else {
+
+ FileHelper.copyLibrary (project, ndll, "Linux" + (is64 ? "64" : ""), "", (ndll.haxelib != null && (ndll.haxelib.name == "hxcpp" || ndll.haxelib.name == "hxlibc")) ? ".dso" : ".ndll", applicationDirectory, project.debug, targetSuffix);
+
+ }
+
+ }
+
+ }
+
+ if (targetType == "neko") {
+
+ ProcessHelper.runCommand ("", "haxe", [ hxml ]);
+
+ if (noOutput) return;
+
+ if (isRaspberryPi) {
+
+ NekoHelper.createExecutable (project.templatePaths, "rpi", targetDirectory + "/obj/ApplicationMain.n", executablePath);
+ NekoHelper.copyLibraries (project.templatePaths, "rpi", applicationDirectory);
+
+ } else {
+
+ NekoHelper.createExecutable (project.templatePaths, "linux" + (is64 ? "64" : ""), targetDirectory + "/obj/ApplicationMain.n", executablePath);
+ NekoHelper.copyLibraries (project.templatePaths, "linux" + (is64 ? "64" : ""), applicationDirectory);
+
+ }
+
+ } else if (targetType == "hl") {
+
+ ProcessHelper.runCommand ("", "haxe", [ hxml ]);
+
+ if (noOutput) return;
+
+ FileHelper.copyFile (targetDirectory + "/obj/ApplicationMain" + (project.debug ? "-Debug" : "") + ".hl", PathHelper.combine (applicationDirectory, project.app.file + ".hl"));
+
+ } else if (targetType == "nodejs") {
+
+ ProcessHelper.runCommand ("", "haxe", [ hxml ]);
+ //NekoHelper.createExecutable (project.templatePaths, "linux" + (is64 ? "64" : ""), targetDirectory + "/obj/ApplicationMain.n", executablePath);
+ //NekoHelper.copyLibraries (project.templatePaths, "linux" + (is64 ? "64" : ""), applicationDirectory);
+
+ } else if (targetType == "java") {
+
+ var libPath = PathHelper.combine (PathHelper.getHaxelib (new Haxelib ("lime")), "templates/java/lib/");
+
+ ProcessHelper.runCommand ("", "haxe", [ hxml, "-java-lib", libPath + "disruptor.jar", "-java-lib", libPath + "lwjgl.jar" ]);
+ //ProcessHelper.runCommand ("", "haxe", [ hxml ]);
+
+ if (noOutput) return;
+
+ var haxeVersion = project.environment.get ("haxe_ver");
+ var haxeVersionString = "3404";
+
+ if (haxeVersion.length > 4) {
+
+ haxeVersionString = haxeVersion.charAt (0) + haxeVersion.charAt (2) + (haxeVersion.length == 5 ? "0" + haxeVersion.charAt (4) : haxeVersion.charAt (4) + haxeVersion.charAt (5));
+
+ }
+
+ ProcessHelper.runCommand (targetDirectory + "/obj", "haxelib", [ "run", "hxjava", "hxjava_build.txt", "--haxe-version", haxeVersionString ]);
+ FileHelper.recursiveCopy (targetDirectory + "/obj/lib", PathHelper.combine (applicationDirectory, "lib"));
+ FileHelper.copyFile (targetDirectory + "/obj/ApplicationMain" + (project.debug ? "-Debug" : "") + ".jar", PathHelper.combine (applicationDirectory, project.app.file + ".jar"));
+ JavaHelper.copyLibraries (project.templatePaths, "Linux" + (is64 ? "64" : ""), applicationDirectory);
+
+ } else {
+
+ var haxeArgs = [ hxml ];
+ var flags = [];
+
+ if (is64) {
+
+ haxeArgs.push ("-D");
+ haxeArgs.push ("HXCPP_M64");
+ flags.push ("-DHXCPP_M64");
+
+ } else {
+
+ haxeArgs.push ("-D");
+ haxeArgs.push ("HXCPP_M32");
+ flags.push ("-DHXCPP_M32");
+
+ }
+
+ if (!project.targetFlags.exists ("static")) {
+
+ ProcessHelper.runCommand ("", "haxe", haxeArgs);
+
+ if (noOutput) return;
+
+ CPPHelper.compile (project, targetDirectory + "/obj", flags);
+
+ FileHelper.copyFile (targetDirectory + "/obj/ApplicationMain" + (project.debug ? "-debug" : ""), executablePath);
+
+ } else {
+
+ ProcessHelper.runCommand ("", "haxe", haxeArgs.concat ([ "-D", "static_link" ]));
+
+ if (noOutput) return;
+
+ CPPHelper.compile (project, targetDirectory + "/obj", flags.concat ([ "-Dstatic_link" ]));
+ CPPHelper.compile (project, targetDirectory + "/obj", flags, "BuildMain.xml");
+
+ FileHelper.copyFile (targetDirectory + "/obj/Main" + (project.debug ? "-debug" : ""), executablePath);
+
+ }
+
+ }
+
+ if (PlatformHelper.hostPlatform != Platform.WINDOWS && (targetType != "nodejs" && targetType != "java")) {
+
+ ProcessHelper.runCommand ("", "chmod", [ "755", executablePath ]);
+
+ }
+
+ }
+
+
+ public override function clean ():Void {
+
+ if (FileSystem.exists (targetDirectory)) {
+
+ PathHelper.removeDirectory (targetDirectory);
+
+ }
+
+ }
+
+
+ public override function deploy ():Void {
+
+ DeploymentHelper.deploy (project, targetFlags, targetDirectory, "Linux " + (is64 ? "64" : "32") + "-bit");
+
+ }
+
+
+ public override function display ():Void {
+
+ Sys.println (getDisplayHXML ());
+
+ }
+
+
+ private function generateContext ():Dynamic {
+
+ // var project = project.clone ();
+
+ if (isRaspberryPi) {
+
+ project.haxedefs.set ("rpi", 1);
+
+ }
+
+ var context = project.templateContext;
+
+ context.NEKO_FILE = targetDirectory + "/obj/ApplicationMain.n";
+ context.NODE_FILE = targetDirectory + "/bin/ApplicationMain.js";
+ context.HL_FILE = targetDirectory + "/obj/ApplicationMain.hl";
+ context.CPP_DIR = targetDirectory + "/obj/";
+ context.BUILD_DIR = project.app.path + "/linux" + (is64 ? "64" : "") + (isRaspberryPi ? "-rpi" : "");
+ context.WIN_ALLOW_SHADERS = false;
+
+ return context;
+
+ }
+
+
+ private function getDisplayHXML ():String {
+
+ var hxml = PathHelper.findTemplate (project.templatePaths, targetType + "/hxml/" + buildType + ".hxml");
+ var template = new Template (File.getContent (hxml));
+
+ var context = generateContext ();
+ context.OUTPUT_DIR = targetDirectory;
+
+ return template.execute (context) + "\n-D display";
+
+ }
+
+
+ public override function rebuild ():Void {
+
+ var commands = [];
+
+ if (targetFlags.exists ("rpi")) {
+
+ commands.push ([ "-Dlinux", "-Drpi", "-Dtoolchain=linux", "-DBINDIR=RPi", "-DCXX=arm-linux-gnueabihf-g++", "-DHXCPP_M32", "-DHXCPP_STRIP=arm-linux-gnueabihf-strip", "-DHXCPP_AR=arm-linux-gnueabihf-ar", "-DHXCPP_RANLIB=arm-linux-gnueabihf-ranlib" ]);
+
+ } else {
+
+ if (!targetFlags.exists ("32") && PlatformHelper.hostArchitecture == X64) {
+
+ commands.push ([ "-Dlinux", "-DHXCPP_M64" ]);
+
+ }
+
+ if (!targetFlags.exists ("64") && (command == "rebuild" || PlatformHelper.hostArchitecture == Architecture.X86)) {
+
+ commands.push ([ "-Dlinux", "-DHXCPP_M32" ]);
+
+ }
+
+ }
+
+ CPPHelper.rebuild (project, commands);
+
+ }
+
+
+ public override function run ():Void {
+
+ var arguments = additionalArguments.copy ();
+
+ if (LogHelper.verbose) {
+
+ arguments.push ("-verbose");
+
+ }
+
+ if (targetType == "hl") {
+
+ ProcessHelper.runCommand (applicationDirectory, "hl", [ project.app.file + ".hl" ].concat (arguments));
+
+ } else if (targetType == "nodejs") {
+
+ NodeJSHelper.run (project, targetDirectory + "/bin/ApplicationMain.js", arguments);
+
+ } else if (targetType == "java") {
+
+ ProcessHelper.runCommand (applicationDirectory, "java", [ "-jar", project.app.file + ".jar" ].concat (arguments));
+
+ } else if (project.target == PlatformHelper.hostPlatform) {
+
+ arguments = arguments.concat ([ "-livereload" ]);
+ ProcessHelper.runCommand (applicationDirectory, "./" + Path.withoutDirectory (executablePath), arguments);
+
+ }
+
+ }
+
+
+ public override function update ():Void {
+
+ // project = project.clone ();
+ //initialize (project);
+
+ for (asset in project.assets) {
+
+ if (asset.embed && asset.sourcePath == "") {
+
+ var path = PathHelper.combine (targetDirectory + "/obj/tmp", asset.targetPath);
+ PathHelper.mkdir (Path.directory (path));
+ FileHelper.copyAsset (asset, path);
+ asset.sourcePath = path;
+
+ }
+
+ }
+
+ if (project.targetFlags.exists ("xml")) {
+
+ project.haxeflags.push ("-xml " + targetDirectory + "/types.xml");
+
+ }
+
+ var context = generateContext ();
+ context.OUTPUT_DIR = targetDirectory;
+
+ if (targetType == "cpp" && project.targetFlags.exists ("static")) {
+
+ for (i in 0...project.ndlls.length) {
+
+ var ndll = project.ndlls[i];
+
+ if (ndll.path == null || ndll.path == "") {
+
+ if (isRaspberryPi) {
+
+ context.ndlls[i].path = PathHelper.getLibraryPath (ndll, "RPi", "lib", ".a", project.debug);
+
+ } else {
+
+ context.ndlls[i].path = PathHelper.getLibraryPath (ndll, "Linux" + (is64 ? "64" : ""), "lib", ".a", project.debug);
+
+ }
+
+ }
+
+ }
+
+ }
+
+ PathHelper.mkdir (targetDirectory);
+ PathHelper.mkdir (targetDirectory + "/obj");
+ PathHelper.mkdir (targetDirectory + "/haxe");
+ PathHelper.mkdir (applicationDirectory);
+
+ //SWFHelper.generateSWFClasses (project, targetDirectory + "/haxe");
+
+ FileHelper.recursiveSmartCopyTemplate (project, "haxe", targetDirectory + "/haxe", context);
+ FileHelper.recursiveSmartCopyTemplate (project, targetType + "/hxml", targetDirectory + "/haxe", context);
+
+ if (targetType == "cpp" && project.targetFlags.exists ("static")) {
+
+ FileHelper.recursiveSmartCopyTemplate (project, "cpp/static", targetDirectory + "/obj", context);
+
+ }
+
+ //context.HAS_ICON = IconHelper.createIcon (project.icons, 256, 256, PathHelper.combine (applicationDirectory, "icon.png"));
+ for (asset in project.assets) {
+
+ var path = PathHelper.combine (applicationDirectory, asset.targetPath);
+
+ if (asset.embed != true) {
+
+ if (asset.type != AssetType.TEMPLATE) {
+
+ PathHelper.mkdir (Path.directory (path));
+ FileHelper.copyAssetIfNewer (asset, path);
+
+ } else {
+
+ PathHelper.mkdir (Path.directory (path));
+ FileHelper.copyAsset (asset, path, context);
+
+ }
+
+ }
+
+ }
+
+ }
+
+
+ public override function watch ():Void {
+
+ var dirs = WatchHelper.processHXML (project, getDisplayHXML ());
+ var command = WatchHelper.getCurrentCommand ();
+ WatchHelper.watch (project, command, dirs);
+
+ }
+
+
+ @ignore public override function install ():Void {}
+ @ignore public override function trace ():Void {}
+ @ignore public override function uninstall ():Void {}
+
+
+}
\ No newline at end of file
diff --git a/tools/platforms/MacPlatform.hx b/tools/platforms/MacPlatform.hx
new file mode 100644
index 000000000..e7be6344d
--- /dev/null
+++ b/tools/platforms/MacPlatform.hx
@@ -0,0 +1,425 @@
+package;
+
+
+import haxe.io.Path;
+import haxe.Template;
+import hxp.helpers.CPPHelper;
+import hxp.helpers.CSHelper;
+import hxp.helpers.DeploymentHelper;
+import hxp.helpers.GUID;
+import hxp.helpers.FileHelper;
+import hxp.helpers.HaxelibHelper;
+import hxp.helpers.IconHelper;
+import hxp.helpers.JavaHelper;
+import hxp.helpers.LogHelper;
+import hxp.helpers.NekoHelper;
+import hxp.helpers.NodeJSHelper;
+import hxp.helpers.PathHelper;
+import hxp.helpers.PlatformHelper;
+import hxp.helpers.ProcessHelper;
+import hxp.helpers.WatchHelper;
+import hxp.project.AssetType;
+import hxp.project.Architecture;
+import hxp.project.Haxelib;
+import hxp.project.HXProject;
+import hxp.project.Icon;
+import hxp.project.Platform;
+import hxp.project.PlatformTarget;
+import sys.io.File;
+import sys.FileSystem;
+
+
+class MacPlatform extends PlatformTarget {
+
+
+ private var applicationDirectory:String;
+ private var contentDirectory:String;
+ private var executableDirectory:String;
+ private var executablePath:String;
+ private var is64:Bool;
+ private var targetType:String;
+
+
+ public function new (command:String, _project:HXProject, targetFlags:Map ) {
+
+ super (command, _project, targetFlags);
+
+ for (architecture in project.architectures) {
+
+ if (architecture == Architecture.X64) {
+
+ is64 = true;
+
+ }
+
+ }
+
+ if (project.targetFlags.exists ("neko") || project.target != PlatformHelper.hostPlatform) {
+
+ targetType = "neko";
+
+ } else if (project.targetFlags.exists ("hl")) {
+
+ targetType = "hl";
+
+ } else if (project.targetFlags.exists ("java")) {
+
+ targetType = "java";
+
+ } else if (project.targetFlags.exists ("nodejs")) {
+
+ targetType = "nodejs";
+
+ } else if (project.targetFlags.exists ("cs")) {
+
+ targetType = "cs";
+
+ } else {
+
+ targetType = "cpp";
+
+ }
+
+ targetDirectory = PathHelper.combine (project.app.path, project.config.getString ("mac.output-directory", targetType == "cpp" ? "macos" : targetType));
+ targetDirectory = StringTools.replace (targetDirectory, "arch64", is64 ? "64" : "");
+ applicationDirectory = targetDirectory + "/bin/" + project.app.file + ".app";
+ contentDirectory = applicationDirectory + "/Contents/Resources";
+ executableDirectory = applicationDirectory + "/Contents/MacOS";
+ executablePath = executableDirectory + "/" + project.app.file;
+
+ }
+
+
+ public override function build ():Void {
+
+ var hxml = targetDirectory + "/haxe/" + buildType + ".hxml";
+
+ PathHelper.mkdir (targetDirectory);
+
+ if (!project.targetFlags.exists ("static") || targetType != "cpp") {
+
+ var targetSuffix = (targetType == "hl") ? ".hdll" : null;
+
+ for (ndll in project.ndlls) {
+
+ FileHelper.copyLibrary (project, ndll, "Mac" + (is64 ? "64" : ""), "", (ndll.haxelib != null && (ndll.haxelib.name == "hxcpp" || ndll.haxelib.name == "hxlibc")) ? ".dylib" : ".ndll", executableDirectory, project.debug, targetSuffix);
+
+ }
+
+ }
+
+ if (targetType == "neko") {
+
+ ProcessHelper.runCommand ("", "haxe", [ hxml ]);
+
+ if (noOutput) return;
+
+ NekoHelper.createExecutable (project.templatePaths, "mac" + (is64 ? "64" : ""), targetDirectory + "/obj/ApplicationMain.n", executablePath);
+ NekoHelper.copyLibraries (project.templatePaths, "mac" + (is64 ? "64" : ""), executableDirectory);
+
+ } else if (targetType == "hl") {
+
+ ProcessHelper.runCommand ("", "haxe", [ hxml ]);
+
+ if (noOutput) return;
+
+ FileHelper.copyFile (targetDirectory + "/obj/ApplicationMain" + (project.debug ? "-Debug" : "") + ".hl", PathHelper.combine (executableDirectory, project.app.file + ".hl"));
+
+ } else if (targetType == "java") {
+
+ var libPath = PathHelper.combine (PathHelper.getHaxelib (new Haxelib ("lime")), "templates/java/lib/");
+
+ ProcessHelper.runCommand ("", "haxe", [ hxml, "-java-lib", libPath + "disruptor.jar", "-java-lib", libPath + "lwjgl.jar" ]);
+
+ if (noOutput) return;
+
+ HaxelibHelper.runCommand (targetDirectory + "/obj", [ "run", "hxjava", "hxjava_build.txt", "--haxe-version", "3103" ]);
+ FileHelper.recursiveCopy (targetDirectory + "/obj/lib", PathHelper.combine (executableDirectory, "lib"));
+ FileHelper.copyFile (targetDirectory + "/obj/ApplicationMain" + (project.debug ? "-Debug" : "") + ".jar", PathHelper.combine (executableDirectory, project.app.file + ".jar"));
+ JavaHelper.copyLibraries (project.templatePaths, "Mac" + (is64 ? "64" : ""), executableDirectory);
+
+ } else if (targetType == "nodejs") {
+
+ ProcessHelper.runCommand ("", "haxe", [ hxml ]);
+
+ if (noOutput) return;
+
+ //NekoHelper.createExecutable (project.templatePaths, "Mac" + (is64 ? "64" : ""), targetDirectory + "/obj/ApplicationMain.n", executablePath);
+ //NekoHelper.copyLibraries (project.templatePaths, "Mac" + (is64 ? "64" : ""), executableDirectory);
+
+ } else if (targetType == "cs") {
+
+ ProcessHelper.runCommand ("", "haxe", [ hxml ]);
+
+ if (noOutput) return;
+
+ CSHelper.copySourceFiles (project.templatePaths, targetDirectory + "/obj/src");
+ var txtPath = targetDirectory + "/obj/hxcs_build.txt";
+ CSHelper.addSourceFiles (txtPath, CSHelper.ndllSourceFiles);
+ CSHelper.addGUID (txtPath, GUID.uuid ());
+ CSHelper.compile (project, targetDirectory + "/obj", targetDirectory + "/obj/ApplicationMain" + (project.debug ? "-debug" : ""), "x64", "desktop");
+ FileHelper.copyFile (targetDirectory + "/obj/ApplicationMain" + (project.debug ? "-debug" : "") + ".exe", executablePath + ".exe");
+ File.saveContent (executablePath, "#!/bin/sh\nmono ${PWD}/" + project.app.file + ".exe");
+
+ } else {
+
+ var haxeArgs = [ hxml, "-D", "HXCPP_CLANG" ];
+ var flags = [ "-DHXCPP_CLANG" ];
+
+ if (is64) {
+
+ haxeArgs.push ("-D");
+ haxeArgs.push ("HXCPP_M64");
+ flags.push ("-DHXCPP_M64");
+
+ }
+
+ if (!project.targetFlags.exists ("static")) {
+
+ ProcessHelper.runCommand ("", "haxe", haxeArgs);
+
+ if (noOutput) return;
+
+ CPPHelper.compile (project, targetDirectory + "/obj", flags);
+
+ FileHelper.copyFile (targetDirectory + "/obj/ApplicationMain" + (project.debug ? "-debug" : ""), executablePath);
+
+ } else {
+
+ ProcessHelper.runCommand ("", "haxe", haxeArgs.concat ([ "-D", "static_link" ]));
+
+ if (noOutput) return;
+
+ CPPHelper.compile (project, targetDirectory + "/obj", flags.concat ([ "-Dstatic_link" ]));
+ CPPHelper.compile (project, targetDirectory + "/obj", flags, "BuildMain.xml");
+
+ FileHelper.copyFile (targetDirectory + "/obj/Main" + (project.debug ? "-debug" : ""), executablePath);
+
+ }
+
+ }
+
+ if (PlatformHelper.hostPlatform != Platform.WINDOWS && targetType != "nodejs" && targetType != "java") {
+
+ ProcessHelper.runCommand ("", "chmod", [ "755", executablePath ]);
+
+ }
+
+ }
+
+
+ public override function clean ():Void {
+
+ if (FileSystem.exists (targetDirectory)) {
+
+ PathHelper.removeDirectory (targetDirectory);
+
+ }
+
+ }
+
+
+ public override function deploy ():Void {
+
+ DeploymentHelper.deploy (project, targetFlags, targetDirectory, "Mac");
+
+ }
+
+
+ public override function display ():Void {
+
+ Sys.println (getDisplayHXML ());
+
+ }
+
+
+ private function generateContext ():Dynamic {
+
+ var context = project.templateContext;
+ context.NEKO_FILE = targetDirectory + "/obj/ApplicationMain.n";
+ context.NODE_FILE = executableDirectory + "/ApplicationMain.js";
+ context.HL_FILE = targetDirectory + "/obj/ApplicationMain.hl";
+ context.CPP_DIR = targetDirectory + "/obj/";
+ context.BUILD_DIR = project.app.path + "/mac" + (is64 ? "64" : "");
+
+ return context;
+
+ }
+
+
+ private function getDisplayHXML ():String {
+
+ var hxml = PathHelper.findTemplate (project.templatePaths, targetType + "/hxml/" + buildType + ".hxml");
+ var template = new Template (File.getContent (hxml));
+
+ var context = generateContext ();
+ context.OUTPUT_DIR = targetDirectory;
+
+ return template.execute (context) + "\n-D display";
+
+ }
+
+
+ public override function rebuild ():Void {
+
+ var commands = [];
+
+ if (!targetFlags.exists ("32") && (command == "rebuild" || PlatformHelper.hostArchitecture == Architecture.X64)) {
+
+ commands.push ([ "-Dmac", "-DHXCPP_CLANG", "-DHXCPP_M64" ]);
+
+ }
+
+ if (!targetFlags.exists ("64") && (command == "rebuild" || PlatformHelper.hostArchitecture == Architecture.X86)) {
+
+ commands.push ([ "-Dmac", "-DHXCPP_CLANG", "-DHXCPP_M32" ]);
+
+ }
+
+ CPPHelper.rebuild (project, commands);
+
+ }
+
+
+ public override function run ():Void {
+
+ var arguments = additionalArguments.copy ();
+
+ if (LogHelper.verbose) {
+
+ arguments.push ("-verbose");
+
+ }
+
+ if (targetType == "hl") {
+
+ ProcessHelper.runCommand (applicationDirectory, "hl", [ project.app.file + ".hl" ].concat (arguments));
+
+ } else if (targetType == "nodejs") {
+
+ NodeJSHelper.run (project, executableDirectory + "/ApplicationMain.js", arguments);
+
+ } else if (targetType == "java") {
+
+ ProcessHelper.runCommand (executableDirectory, "java", [ "-jar", project.app.file + ".jar" ].concat (arguments));
+
+ } else if (project.target == PlatformHelper.hostPlatform) {
+
+ arguments = arguments.concat ([ "-livereload" ]);
+ ProcessHelper.runCommand (executableDirectory, "./" + Path.withoutDirectory (executablePath), arguments);
+
+ }
+
+ }
+
+
+ public override function update ():Void {
+
+ // project = project.clone ();
+
+ if (project.targetFlags.exists ("xml")) {
+
+ project.haxeflags.push ("-xml " + targetDirectory + "/types.xml");
+
+ }
+
+ for (asset in project.assets) {
+
+ if (asset.embed && asset.sourcePath == "") {
+
+ var path = PathHelper.combine (targetDirectory + "/obj/tmp", asset.targetPath);
+ PathHelper.mkdir (Path.directory (path));
+ FileHelper.copyAsset (asset, path);
+ asset.sourcePath = path;
+
+ }
+
+ }
+
+ var context = generateContext ();
+ context.OUTPUT_DIR = targetDirectory;
+
+ if (targetType == "cpp" && project.targetFlags.exists ("static")) {
+
+ for (i in 0...project.ndlls.length) {
+
+ var ndll = project.ndlls[i];
+
+ if (ndll.path == null || ndll.path == "") {
+
+ context.ndlls[i].path = PathHelper.getLibraryPath (ndll, "Mac" + (is64 ? "64" : ""), "lib", ".a", project.debug);
+
+ }
+
+ }
+
+ }
+
+ PathHelper.mkdir (targetDirectory);
+ PathHelper.mkdir (targetDirectory + "/obj");
+ PathHelper.mkdir (targetDirectory + "/haxe");
+ PathHelper.mkdir (applicationDirectory);
+ PathHelper.mkdir (contentDirectory);
+
+ //SWFHelper.generateSWFClasses (project, targetDirectory + "/haxe");
+
+ FileHelper.recursiveSmartCopyTemplate (project, "haxe", targetDirectory + "/haxe", context);
+ FileHelper.recursiveSmartCopyTemplate (project, targetType + "/hxml", targetDirectory + "/haxe", context);
+
+ if (targetType == "cpp" && project.targetFlags.exists ("static")) {
+
+ FileHelper.recursiveSmartCopyTemplate (project, "cpp/static", targetDirectory + "/obj", context);
+
+ }
+
+ FileHelper.copyFileTemplate (project.templatePaths, "mac/Info.plist", targetDirectory + "/bin/" + project.app.file + ".app/Contents/Info.plist", context);
+ FileHelper.copyFileTemplate (project.templatePaths, "mac/Entitlements.plist", targetDirectory + "/bin/" + project.app.file + ".app/Contents/Entitlements.plist", context);
+
+ var icons = project.icons;
+
+ if (icons.length == 0) {
+
+ icons = [ new Icon (PathHelper.findTemplate (project.templatePaths, "default/icon.svg")) ];
+
+ }
+
+ context.HAS_ICON = IconHelper.createMacIcon (icons, PathHelper.combine (contentDirectory, "icon.icns"));
+
+ for (asset in project.assets) {
+
+ if (asset.embed != true) {
+
+ if (asset.type != AssetType.TEMPLATE) {
+
+ PathHelper.mkdir (Path.directory (PathHelper.combine (contentDirectory, asset.targetPath)));
+ FileHelper.copyAssetIfNewer (asset, PathHelper.combine (contentDirectory, asset.targetPath));
+
+ } else {
+
+ PathHelper.mkdir (Path.directory (PathHelper.combine (targetDirectory, asset.targetPath)));
+ FileHelper.copyAsset (asset, PathHelper.combine (targetDirectory, asset.targetPath), context);
+
+ }
+
+ }
+
+ }
+
+ }
+
+
+ public override function watch ():Void {
+
+ var dirs = WatchHelper.processHXML (project, getDisplayHXML ());
+ var command = WatchHelper.getCurrentCommand ();
+ WatchHelper.watch (project, command, dirs);
+
+ }
+
+
+ @ignore public override function install ():Void {}
+ @ignore public override function trace ():Void {}
+ @ignore public override function uninstall ():Void {}
+
+
+}
\ No newline at end of file
diff --git a/tools/platforms/TVOSPlatform.hx b/tools/platforms/TVOSPlatform.hx
new file mode 100644
index 000000000..d00743d2e
--- /dev/null
+++ b/tools/platforms/TVOSPlatform.hx
@@ -0,0 +1,649 @@
+package lime.tools.platforms;
+
+
+//import openfl.display.BitmapData;
+import haxe.io.Path;
+import haxe.Json;
+import haxe.Template;
+import hxp.helpers.ArrayHelper;
+import hxp.helpers.CPPHelper;
+import hxp.helpers.DeploymentHelper;
+import hxp.helpers.FileHelper;
+import hxp.helpers.IconHelper;
+import hxp.helpers.TVOSHelper;
+import hxp.helpers.LogHelper;
+import hxp.helpers.PathHelper;
+import hxp.helpers.PlatformHelper;
+import hxp.helpers.ProcessHelper;
+import hxp.helpers.StringHelper;
+import hxp.helpers.WatchHelper;
+import lime.graphics.Image;
+import hxp.project.Architecture;
+import hxp.project.Asset;
+import hxp.project.AssetType;
+import hxp.project.Haxelib;
+import hxp.project.HXProject;
+import hxp.project.Icon;
+import hxp.project.Keystore;
+import hxp.project.NDLL;
+import hxp.project.Platform;
+import hxp.project.PlatformTarget;
+import sys.io.File;
+import sys.FileSystem;
+
+
+class TVOSPlatform extends PlatformTarget {
+
+
+ public function new (command:String, _project:HXProject, targetFlags:Map ) {
+
+ super (command, _project, targetFlags);
+
+ targetDirectory = PathHelper.combine (project.app.path, project.config.getString ("tvos.output-directory", "tvos"));
+
+ }
+
+
+ public override function build ():Void {
+
+ if (project.targetFlags.exists ("xcode") && PlatformHelper.hostPlatform == Platform.MAC) {
+
+ ProcessHelper.runCommand ("", "open", [ targetDirectory + "/" + project.app.file + ".xcodeproj" ] );
+
+ } else {
+
+ TVOSHelper.build (project, targetDirectory);
+
+ if (noOutput) return;
+
+ if (!project.targetFlags.exists ("simulator")) {
+
+ TVOSHelper.sign (project, targetDirectory + "/bin");
+
+ }
+
+ }
+
+ }
+
+
+ public override function clean ():Void {
+
+ if (FileSystem.exists (targetDirectory)) {
+
+ PathHelper.removeDirectory (targetDirectory);
+
+ }
+
+ }
+
+
+ public override function deploy ():Void {
+
+ TVOSHelper.deploy (project, targetDirectory);
+
+ }
+
+
+ public override function display ():Void {
+
+ Sys.println (getDisplayHXML ());
+
+ }
+
+
+ private function generateContext ():Dynamic {
+
+ // project = project.clone ();
+
+ project.sources.unshift ("");
+ project.sources = PathHelper.relocatePaths (project.sources, PathHelper.combine (targetDirectory, project.app.file + "/haxe"));
+ //project.dependencies.push ("stdc++");
+
+ if (project.targetFlags.exists ("xml")) {
+
+ project.haxeflags.push ("-xml " + targetDirectory + "/types.xml");
+
+ }
+
+ if (project.targetFlags.exists ("final")) {
+
+ project.haxedefs.set ("final", "");
+
+ }
+
+ if (!project.config.exists ("tvos.identity")) {
+
+ project.config.set ("tvos.identity", "tvOS Developer");
+
+ }
+
+ var context = project.templateContext;
+
+ context.HAS_ICON = false;
+ context.HAS_LAUNCH_IMAGE = false;
+ context.OBJC_ARC = false;
+ context.KEY_STORE_IDENTITY = project.config.getString ("tvos.identity");
+
+ context.linkedLibraries = [];
+
+ for (dependency in project.dependencies) {
+
+ if (!StringTools.endsWith (dependency.name, ".framework") && !StringTools.endsWith (dependency.name, ".tbd") && !StringTools.endsWith (dependency.path, ".framework")) {
+
+ if (dependency.path != "") {
+
+ var name = Path.withoutDirectory (Path.withoutExtension (dependency.path));
+
+ project.config.push ("tvos.linker-flags", "-force_load $SRCROOT/$PRODUCT_NAME/lib/$CURRENT_ARCH/" + Path.withoutDirectory (dependency.path));
+
+ if (StringTools.startsWith (name, "lib")) {
+
+ name = name.substring (3, name.length);
+
+ }
+
+ context.linkedLibraries.push (name);
+
+ } else if (dependency.name != "") {
+
+ context.linkedLibraries.push (dependency.name);
+
+ }
+
+ }
+
+ }
+
+ var valid_archs = new Array ();
+ var arm64 = false;
+ var architectures = project.architectures;
+
+ if (architectures == null || architectures.length == 0) {
+
+ architectures = [ Architecture.ARM64 ];
+
+ }
+
+ /*if (project.config.getString ("ios.device", "universal") == "universal" || project.config.getString ("ios.device") == "iphone") {
+
+ if (project.config.getFloat ("ios.deployment", 5.1) < 5) {
+
+ ArrayHelper.addUnique (architectures, Architecture.ARMV6);
+
+ }
+
+ }*/
+
+ for (architecture in project.architectures) {
+
+ switch (architecture) {
+
+ case ARM64: valid_archs.push ("arm64"); arm64 = true;
+ default:
+
+ }
+
+ }
+
+ context.CURRENT_ARCHS = "( " + valid_archs.join(",") + ") ";
+
+ valid_archs.push ("i386");
+
+ context.VALID_ARCHS = valid_archs.join(" ");
+ context.THUMB_SUPPORT = "";
+
+ var requiredCapabilities = [];
+
+ requiredCapabilities.push( { name: "arm64", value: true } );
+
+ context.REQUIRED_CAPABILITY = requiredCapabilities;
+ context.ARM64 = arm64;
+ context.TARGET_DEVICES = switch (project.config.getString ("tvos.device", "appletv")) { case "appletv": "3"; default: "3"; }
+ context.DEPLOYMENT = project.config.getString ("tvos.deployment", "9.0");
+
+ if (project.config.getString ("tvos.compiler") == "llvm" || project.config.getString ("tvos.compiler", "clang") == "clang") {
+
+ context.OBJC_ARC = true;
+
+ }
+
+ context.IOS_COMPILER = project.config.getString ("tvos.compiler", "clang");
+ context.CPP_BUILD_LIBRARY = project.config.getString ("cpp.buildLibrary", "hxcpp");
+
+ var json = Json.parse (File.getContent (PathHelper.getHaxelib (new Haxelib ("hxcpp"), true) + "/haxelib.json"));
+
+ if (Std.parseFloat (json.version) > 3.1) {
+
+ context.CPP_LIBPREFIX = "lib";
+
+ } else {
+
+ context.CPP_LIBPREFIX = "";
+
+ }
+
+ context.IOS_LINKER_FLAGS = ["-stdlib=libc++"].concat (project.config.getArrayString ("tvos.linker-flags"));
+ context.IOS_NON_EXEMPT_ENCRYPTION = project.config.getBool ("tvos.non-exempt-encryption", true);
+
+ switch (project.window.orientation) {
+
+ case PORTRAIT:
+ context.IOS_APP_ORIENTATION = "UIInterfaceOrientationPortraitUIInterfaceOrientationPortraitUpsideDown";
+ case LANDSCAPE:
+ context.IOS_APP_ORIENTATION = "UIInterfaceOrientationLandscapeLeftUIInterfaceOrientationLandscapeRight";
+ case ALL:
+ context.IOS_APP_ORIENTATION = "UIInterfaceOrientationLandscapeLeftUIInterfaceOrientationLandscapeRightUIInterfaceOrientationPortraitUIInterfaceOrientationPortraitUpsideDown";
+ //case "allButUpsideDown":
+ //context.IOS_APP_ORIENTATION = "UIInterfaceOrientationLandscapeLeftUIInterfaceOrientationLandscapeRightUIInterfaceOrientationPortrait";
+ default:
+ context.IOS_APP_ORIENTATION = "UIInterfaceOrientationLandscapeLeftUIInterfaceOrientationLandscapeRightUIInterfaceOrientationPortraitUIInterfaceOrientationPortraitUpsideDown";
+
+ }
+
+ context.ADDL_PBX_BUILD_FILE = "";
+ context.ADDL_PBX_FILE_REFERENCE = "";
+ context.ADDL_PBX_FRAMEWORKS_BUILD_PHASE = "";
+ context.ADDL_PBX_FRAMEWORK_GROUP = "";
+
+ context.frameworkSearchPaths = [];
+
+ for (dependency in project.dependencies) {
+
+ var name = null;
+ var path = null;
+ var fileType = null;
+
+ if (Path.extension (dependency.name) == "framework") {
+
+ name = dependency.name;
+ path = "/System/Library/Frameworks/" + dependency.name;
+ fileType = "wrapper.framework";
+
+ } else if (Path.extension (dependency.name) == "tbd") {
+
+ name = dependency.name;
+ path = "usr/lib/" + dependency.name;
+ fileType = "sourcecode.text-based-dylib-definition";
+
+ } else if (Path.extension (dependency.path) == "framework") {
+
+ name = Path.withoutDirectory (dependency.path);
+ path = PathHelper.tryFullPath (dependency.path);
+ fileType = "wrapper.framework";
+
+ }
+
+ if (name != null) {
+
+ var frameworkID = "11C0000000000018" + StringHelper.getUniqueID ();
+ var fileID = "11C0000000000018" + StringHelper.getUniqueID ();
+
+ ArrayHelper.addUnique (context.frameworkSearchPaths, Path.directory (path));
+
+ context.ADDL_PBX_BUILD_FILE += " " + frameworkID + " /* " + name + " in Frameworks */ = {isa = PBXBuildFile; fileRef = " + fileID + " /* " + name + " */; };\n";
+ context.ADDL_PBX_FILE_REFERENCE += " " + fileID + " /* " + name + " */ = {isa = PBXFileReference; lastKnownFileType = \"" + fileType + "\"; name = \"" + name + "\"; path = \"" + path + "\"; sourceTree = SDKROOT; };\n";
+ context.ADDL_PBX_FRAMEWORKS_BUILD_PHASE += " " + frameworkID + " /* " + name + " in Frameworks */,\n";
+ context.ADDL_PBX_FRAMEWORK_GROUP += " " + fileID + " /* " + name + " */,\n";
+
+ }
+
+ }
+
+ context.HXML_PATH = PathHelper.findTemplate (project.templatePaths, "tvos/PROJ/haxe/Build.hxml");
+ context.PRERENDERED_ICON = project.config.getBool ("tvos.prerenderedIcon", false);
+
+ var haxelibPath = project.environment.get ("HAXELIB_PATH");
+
+ if (haxelibPath != null) {
+
+ context.HAXELIB_PATH = 'export HAXELIB_PATH=$haxelibPath;';
+
+ } else {
+
+ context.HAXELIB_PATH = '';
+
+ }
+
+ return context;
+
+ }
+
+
+ private function getDisplayHXML ():String {
+
+ var hxml = PathHelper.findTemplate (project.templatePaths, "tvos/PROJ/haxe/Build.hxml");
+ var template = new Template (File.getContent (hxml));
+
+ var context = generateContext ();
+ context.OUTPUT_DIR = targetDirectory;
+
+ return template.execute (context) + "\n-D display";
+
+ }
+
+
+ public override function rebuild ():Void {
+
+ var arm64 = (command == "rebuild" || (project.architectures.indexOf (Architecture.ARM64) > -1 && !project.targetFlags.exists ("simulator")));
+ var i386 = (command == "rebuild" || project.targetFlags.exists ("simulator"));
+ var x86_64 = (command == "rebuild" || project.targetFlags.exists ("simulator"));
+
+ var commands = [];
+
+ if (arm64) commands.push ([ "-Dtvos", "-Dappletvos", "-DHXCPP_CPP11", "-DHXCPP_ARM64", "-DOBJC_ARC", "-DENABLE_BITCODE" ]);
+ if (i386) commands.push ([ "-Dtvos", "-Dappletvsim", "-Dsimulator", "-DHXCPP_CPP11", "-DOBJC_ARC", "-DENABLE_BITCODE" ]);
+ if (x86_64) commands.push ([ "-Dtvos", "-Dappletvsim", "-Dsimulator", "-DHXCPP_M64", "-DHXCPP_CPP11", "-DOBJC_ARC", "-DENABLE_BITCODE" ]);
+
+ CPPHelper.rebuild (project, commands);
+
+ }
+
+
+ public override function run ():Void {
+
+ if (project.targetFlags.exists ("xcode")) return;
+
+ TVOSHelper.launch (project, targetDirectory);
+
+ }
+
+
+ public override function update ():Void {
+
+ // project = project.clone ();
+
+ for (asset in project.assets) {
+
+ if (asset.embed && asset.sourcePath == "") {
+
+ var path = PathHelper.combine (targetDirectory + "/" + project.app.file + "/obj/tmp", asset.targetPath);
+ PathHelper.mkdir (Path.directory (path));
+ FileHelper.copyAsset (asset, path);
+ asset.sourcePath = path;
+
+ }
+
+ }
+
+ //var manifest = new Asset ();
+ //manifest.id = "__manifest__";
+ //manifest.data = AssetHelper.createManifest (project).serialize ();
+ //manifest.resourceName = manifest.flatName = manifest.targetPath = "manifest";
+ //manifest.type = AssetType.TEXT;
+ //project.assets.push (manifest);
+
+ var context = generateContext ();
+ context.OUTPUT_DIR = targetDirectory;
+
+ var projectDirectory = targetDirectory + "/" + project.app.file + "/";
+
+ PathHelper.mkdir (targetDirectory);
+ PathHelper.mkdir (projectDirectory);
+ PathHelper.mkdir (projectDirectory + "/haxe");
+ PathHelper.mkdir (projectDirectory + "/haxe/lime/installer");
+
+ var iconSizes:Array = [
+ { name : "Icon-Small.png", size : 29 },
+ { name : "Icon-Small-40.png", size : 40 },
+ { name : "Icon-Small-50.png", size : 50 },
+ { name : "Icon.png", size : 57 },
+ { name : "Icon-Small@2x.png", size : 58 },
+ { name : "Icon-72.png", size : 72 },
+ { name : "Icon-76.png", size : 76 },
+ { name : "Icon-Small-40@2x.png", size : 80 },
+ { name : "Icon-Small-50@2x.png", size : 100 },
+ { name : "Icon@2x.png", size : 114 },
+ { name : "Icon-60@2x.png", size : 120 },
+ { name : "Icon-72@2x.png", size : 144 },
+ { name : "Icon-76@2x.png", size : 152 },
+ { name : "Icon-60@3x.png", size : 180 },
+ ];
+
+ context.HAS_ICON = true;
+
+ var iconPath = PathHelper.combine (projectDirectory, "Images.xcassets/AppIcon.appiconset");
+ PathHelper.mkdir (iconPath);
+
+ var icons = project.icons;
+
+ if (icons.length == 0) {
+
+ icons = [ new Icon (PathHelper.findTemplate (project.templatePaths, "default/icon.svg")) ];
+
+ }
+
+ for (iconSize in iconSizes) {
+
+ if (!IconHelper.createIcon (icons, iconSize.size, iconSize.size, PathHelper.combine (iconPath, iconSize.name))) {
+
+ context.HAS_ICON = false;
+
+ }
+
+ }
+
+ var splashSizes:Array = [
+ { name: "Default.png", w: 320, h: 480 }, // iPhone, portrait
+ { name: "Default@2x.png", w: 640, h: 960 }, // iPhone Retina, portrait
+ { name: "Default-568h@2x.png", w: 640, h: 1136 }, // iPhone 5, portrait
+ { name: "Default-Portrait.png", w: 768, h: 1024 }, // iPad, portrait
+ { name: "Default-Landscape.png", w: 1024, h: 768 }, // iPad, landscape
+ { name: "Default-Portrait@2x.png", w: 1536, h: 2048 }, // iPad Retina, portrait
+ { name: "Default-Landscape@2x.png", w: 2048, h: 1536 }, // iPad Retina, landscape
+ { name: "Default-667h@2x.png", w: 750, h: 1334 }, // iPhone 6, portrait
+ { name: "Default-736h@3x.png", w: 1242, h: 2208 }, // iPhone 6 Plus, portrait
+ { name: "Default-736h-Landscape@3x.png", w: 2208, h: 1242 }, // iPhone 6 Plus, landscape
+ ];
+
+ var splashScreenPath = PathHelper.combine (projectDirectory, "Images.xcassets/LaunchImage.launchimage");
+ PathHelper.mkdir (splashScreenPath);
+
+ for (size in splashSizes) {
+
+ var match = false;
+
+ for (splashScreen in project.splashScreens) {
+
+ if (splashScreen.width == size.w && splashScreen.height == size.h && Path.extension (splashScreen.path) == "png") {
+
+ FileHelper.copyFile (splashScreen.path, PathHelper.combine (splashScreenPath, size.name));
+ match = true;
+
+ }
+
+ }
+
+ if (!match) {
+
+ var imagePath = PathHelper.combine (splashScreenPath, size.name);
+
+ if (!FileSystem.exists (imagePath)) {
+
+ LogHelper.info ("", " - \x1b[1mGenerating image:\x1b[0m " + imagePath);
+
+ var image = new Image (null, 0, 0, size.w, size.h, (0xFF << 24) | (project.window.background & 0xFFFFFF));
+ var bytes = image.encode ("png");
+
+ File.saveBytes (imagePath, bytes);
+
+ }
+
+ }
+
+ }
+
+ context.HAS_LAUNCH_IMAGE = true;
+
+ PathHelper.mkdir (projectDirectory + "/resources");
+ PathHelper.mkdir (projectDirectory + "/haxe/build");
+
+ FileHelper.recursiveSmartCopyTemplate (project, "tvos/resources", projectDirectory + "/resources", context, true, false);
+ FileHelper.recursiveSmartCopyTemplate (project, "tvos/PROJ/haxe", projectDirectory + "/haxe", context);
+ FileHelper.recursiveSmartCopyTemplate (project, "haxe", projectDirectory + "/haxe", context);
+ FileHelper.recursiveSmartCopyTemplate (project, "tvos/PROJ/Classes", projectDirectory + "/Classes", context);
+ FileHelper.recursiveSmartCopyTemplate (project, "tvos/PROJ/Images.xcassets", projectDirectory + "/Images.xcassets", context);
+ FileHelper.copyFileTemplate (project.templatePaths, "tvos/PROJ/PROJ-Info.plist", projectDirectory + "/" + project.app.file + "-Info.plist", context);
+ FileHelper.copyFileTemplate (project.templatePaths, "tvos/PROJ/PROJ-Prefix.pch", projectDirectory + "/" + project.app.file + "-Prefix.pch", context);
+ FileHelper.recursiveSmartCopyTemplate (project, "tvos/PROJ.xcodeproj", targetDirectory + "/" + project.app.file + ".xcodeproj", context);
+
+ //SWFHelper.generateSWFClasses (project, projectDirectory + "/haxe");
+
+ PathHelper.mkdir (projectDirectory + "/lib");
+
+ for (archID in 0...3) {
+
+ var arch = [ "arm64", "i386", "x86_64" ][archID];
+
+ if (arch == "arm64" && !context.ARM64)
+ continue;
+
+ var libExt = [ ".appletvos-64.a", ".appletvsim.a", ".appletvsim-64.a" ][archID];
+
+ PathHelper.mkdir (projectDirectory + "/lib/" + arch);
+ PathHelper.mkdir (projectDirectory + "/lib/" + arch + "-debug");
+
+ for (ndll in project.ndlls) {
+
+ //if (ndll.haxelib != null) {
+
+ var releaseLib = PathHelper.getLibraryPath (ndll, "AppleTV", "lib", libExt);
+ LogHelper.info("releaseLib: " + releaseLib);
+ var debugLib = PathHelper.getLibraryPath (ndll, "AppleTV", "lib", libExt, true);
+ var releaseDest = projectDirectory + "/lib/" + arch + "/lib" + ndll.name + ".a";
+ LogHelper.info("releaseDest: " + releaseDest);
+ var debugDest = projectDirectory + "/lib/" + arch + "-debug/lib" + ndll.name + ".a";
+
+ if (!FileSystem.exists (releaseLib)) {
+
+ releaseLib = PathHelper.getLibraryPath (ndll, "AppleTV", "lib", ".appletvos-64.a");
+ LogHelper.info("alternative releaseLib: " + releaseLib);
+ debugLib = PathHelper.getLibraryPath (ndll, "AppleTV", "lib", ".appletvos-64.a", true);
+
+ }
+
+ FileHelper.copyIfNewer (releaseLib, releaseDest);
+
+ if (FileSystem.exists (debugLib) && debugLib != releaseLib) {
+
+ FileHelper.copyIfNewer (debugLib, debugDest);
+
+ } else if (FileSystem.exists (debugDest)) {
+
+ FileSystem.deleteFile (debugDest);
+
+ }
+
+ //}
+
+ }
+
+ for (dependency in project.dependencies) {
+
+ if (StringTools.endsWith (dependency.path, ".a")) {
+
+ var fileName = Path.withoutDirectory (dependency.path);
+
+ if (!StringTools.startsWith (fileName, "lib")) {
+
+ fileName = "lib" + fileName;
+
+ }
+
+ FileHelper.copyIfNewer (dependency.path, projectDirectory + "/lib/" + arch + "/" + fileName);
+
+ }
+
+ }
+
+ }
+
+ PathHelper.mkdir (projectDirectory + "/assets");
+
+ for (asset in project.assets) {
+
+ if (asset.type != AssetType.TEMPLATE) {
+
+ var targetPath = PathHelper.combine (projectDirectory + "/assets/", asset.resourceName);
+
+ //var sourceAssetPath:String = projectDirectory + "haxe/" + asset.sourcePath;
+
+ PathHelper.mkdir (Path.directory (targetPath));
+ FileHelper.copyAssetIfNewer (asset, targetPath);
+
+ //PathHelper.mkdir (Path.directory (sourceAssetPath));
+ //FileHelper.linkFile (flatAssetPath, sourceAssetPath, true, true);
+
+ } else {
+
+ var targetPath = PathHelper.combine (projectDirectory, asset.targetPath);
+
+ PathHelper.mkdir (Path.directory (targetPath));
+ FileHelper.copyAsset (asset, targetPath, context);
+
+ }
+
+ }
+
+ if (project.targetFlags.exists ("xcode") && PlatformHelper.hostPlatform == Platform.MAC && command == "update") {
+
+ ProcessHelper.runCommand ("", "open", [ targetDirectory + "/" + project.app.file + ".xcodeproj" ] );
+
+ }
+
+ }
+
+
+ /*private function updateLaunchImage () {
+
+ var destination = buildDirectory + "/ios";
+ PathHelper.mkdir (destination);
+
+ var has_launch_image = false;
+ if (launchImages.length > 0) has_launch_image = true;
+
+ for (launchImage in launchImages) {
+
+ var splitPath = launchImage.name.split ("/");
+ var path = destination + "/" + splitPath[splitPath.length - 1];
+ FileHelper.copyFile (launchImage.name, path, context, false);
+
+ }
+
+ context.HAS_LAUNCH_IMAGE = has_launch_image;
+
+ }*/
+
+
+ public override function watch ():Void {
+
+ var dirs = WatchHelper.processHXML (project, getDisplayHXML ());
+ var command = WatchHelper.getCurrentCommand ();
+ WatchHelper.watch (project, command, dirs);
+
+ }
+
+
+ @ignore public override function install ():Void {}
+ @ignore public override function trace ():Void {}
+ @ignore public override function uninstall ():Void {}
+
+
+}
+
+
+private typedef IconSize = {
+
+ name:String,
+ size:Int,
+
+}
+
+
+private typedef SplashSize = {
+
+ name:String,
+ w:Int,
+ h:Int,
+
+}
\ No newline at end of file
diff --git a/tools/platforms/TizenPlatform.hx b/tools/platforms/TizenPlatform.hx
new file mode 100644
index 000000000..989bff425
--- /dev/null
+++ b/tools/platforms/TizenPlatform.hx
@@ -0,0 +1,232 @@
+package;
+
+
+import haxe.io.Path;
+import haxe.Template;
+import hxp.helpers.CPPHelper;
+import hxp.helpers.DeploymentHelper;
+import hxp.helpers.FileHelper;
+import hxp.helpers.IconHelper;
+import hxp.helpers.PathHelper;
+import hxp.helpers.ProcessHelper;
+import hxp.helpers.TizenHelper;
+import hxp.project.AssetType;
+import hxp.project.HXProject;
+import hxp.project.Icon;
+import hxp.project.PlatformTarget;
+import sys.io.File;
+import sys.FileSystem;
+
+
+class TizenPlatform extends PlatformTarget {
+
+
+ private static var uuid:String = null;
+
+
+ public function new (command:String, _project:HXProject, targetFlags:Map ) {
+
+ super (command, _project, targetFlags);
+
+ targetDirectory = PathHelper.combine (project.app.path, project.config.getString ("tizen.output-directory", "tizen"));
+
+ }
+
+
+ public override function build ():Void {
+
+ var destination = targetDirectory + "/bin/";
+
+ var arch = "";
+
+ if (project.targetFlags.exists ("simulator")) {
+
+ arch = "-x86";
+
+ }
+
+ for (ndll in project.ndlls) {
+
+ FileHelper.copyLibrary (project, ndll, "Tizen", "", arch + ".so", destination + "lib/", project.debug, ".so");
+
+ }
+
+ var hxml = targetDirectory + "/haxe/" + buildType + ".hxml";
+
+ ProcessHelper.runCommand ("", "haxe", [ hxml, "-D", "tizen" ] );
+
+ if (noOutput) return;
+
+ var args = [ "-Dtizen", "-DAPP_ID=" + TizenHelper.getUUID (project) ];
+
+ if (project.targetFlags.exists ("simulator")) {
+
+ args.push ("-Dsimulator");
+
+ }
+
+ CPPHelper.compile (project, targetDirectory + "/obj", args);
+ FileHelper.copyIfNewer (targetDirectory + "/obj/ApplicationMain" + (project.debug ? "-debug" : "") + ".exe", targetDirectory + "/bin/CommandLineBuild/" + project.app.file + ".exe");
+ TizenHelper.createPackage (project, targetDirectory + "/bin/CommandLineBuild", "");
+
+ }
+
+
+ public override function clean ():Void {
+
+ if (FileSystem.exists (targetDirectory)) {
+
+ PathHelper.removeDirectory (targetDirectory);
+
+ }
+
+ }
+
+
+ public override function deploy ():Void {
+
+ DeploymentHelper.deploy (project, targetFlags, targetDirectory, "Tizen");
+
+ }
+
+
+ public override function display ():Void {
+
+ var hxml = PathHelper.findTemplate (project.templatePaths, "tizen/hxml/" + buildType + ".hxml");
+
+ var context = project.templateContext;
+ context.CPP_DIR = targetDirectory + "/obj";
+ context.OUTPUT_DIR = targetDirectory;
+
+ var template = new Template (File.getContent (hxml));
+
+ Sys.println (template.execute (context));
+ Sys.println ("-D display");
+
+ }
+
+
+ public override function rebuild ():Void {
+
+ var device = (command == "rebuild" || !targetFlags.exists ("simulator"));
+ var simulator = (command == "rebuild" || targetFlags.exists ("simulator"));
+
+ var commands = [];
+
+ if (device) commands.push ([ "-Dtizen" ]);
+ if (simulator) commands.push ([ "-Dtizen", "-Dsimulator" ]);
+
+ CPPHelper.rebuild (project, commands);
+
+ }
+
+
+ public override function run ():Void {
+
+ TizenHelper.install (project, targetDirectory + "/bin/CommandLineBuild");
+ TizenHelper.launch (project);
+
+ }
+
+
+ public override function trace ():Void {
+
+ TizenHelper.trace (project);
+
+ }
+
+
+ public override function update ():Void {
+
+ // project = project.clone ();
+
+ for (asset in project.assets) {
+
+ if (asset.embed && asset.sourcePath == "") {
+
+ var path = PathHelper.combine (targetDirectory + "/obj/tmp", asset.targetPath);
+ PathHelper.mkdir (Path.directory (path));
+ FileHelper.copyAsset (asset, path);
+ asset.sourcePath = path;
+
+ }
+
+ }
+
+ var destination = targetDirectory + "/bin/";
+ PathHelper.mkdir (destination);
+
+ for (asset in project.assets) {
+
+ asset.resourceName = "../res/" + asset.resourceName;
+
+ }
+
+ if (project.targetFlags.exists ("xml")) {
+
+ project.haxeflags.push ("-xml " + targetDirectory + "/types.xml");
+
+ }
+
+ var context = project.templateContext;
+ context.CPP_DIR = targetDirectory + "/obj";
+ context.OUTPUT_DIR = targetDirectory;
+ context.APP_PACKAGE = TizenHelper.getUUID (project);
+ context.SIMULATOR = project.targetFlags.exists ("simulator");
+
+ PathHelper.mkdir (destination + "shared/res/screen-density-xhigh");
+
+ var icons = project.icons;
+
+ if (icons.length == 0) {
+
+ icons = [ new Icon (PathHelper.findTemplate (project.templatePaths, "default/icon.svg")) ];
+
+ }
+
+ if (IconHelper.createIcon (icons, 117, 117, PathHelper.combine (destination + "shared/res/screen-density-xhigh", "mainmenu.png"))) {
+
+ context.APP_ICON = "mainmenu.png";
+
+ }
+
+ FileHelper.recursiveSmartCopyTemplate (project, "tizen/template", destination, context);
+ FileHelper.recursiveSmartCopyTemplate (project, "haxe", targetDirectory + "/haxe", context);
+ FileHelper.recursiveSmartCopyTemplate (project, "tizen/hxml", targetDirectory + "/haxe", context);
+
+ for (asset in project.assets) {
+
+ var path = PathHelper.combine (destination + "res/", asset.targetPath);
+
+ PathHelper.mkdir (Path.directory (path));
+
+ if (asset.type != AssetType.TEMPLATE) {
+
+ if (asset.targetPath == "/appinfo.json") {
+
+ FileHelper.copyAsset (asset, path, context);
+
+ } else {
+
+ // going to root directory now, but should it be a forced "assets" folder later?
+
+ FileHelper.copyAssetIfNewer (asset, path);
+
+ }
+
+ } else {
+
+ FileHelper.copyAsset (asset, path, context);
+
+ }
+
+ }
+
+ }
+
+
+ @ignore public override function install ():Void {}
+ @ignore public override function uninstall ():Void {}
+
+
+}
\ No newline at end of file
diff --git a/tools/platforms/WindowsPlatform.hx b/tools/platforms/WindowsPlatform.hx
new file mode 100644
index 000000000..52b4a65ca
--- /dev/null
+++ b/tools/platforms/WindowsPlatform.hx
@@ -0,0 +1,870 @@
+package;
+
+
+import haxe.io.Path;
+import haxe.Template;
+import hxp.project.Icon;
+import hxp.helpers.CPPHelper;
+import hxp.helpers.DeploymentHelper;
+import hxp.helpers.FileHelper;
+import hxp.helpers.HTML5Helper;
+import hxp.helpers.IconHelper;
+import hxp.helpers.JavaHelper;
+import hxp.helpers.LogHelper;
+import hxp.helpers.ModuleHelper;
+import hxp.helpers.CSHelper;
+import hxp.helpers.GUID;
+import hxp.helpers.NekoHelper;
+import hxp.helpers.NodeJSHelper;
+import hxp.helpers.PathHelper;
+import hxp.helpers.PlatformHelper;
+import hxp.helpers.ProcessHelper;
+import hxp.helpers.WatchHelper;
+import hxp.project.Architecture;
+import hxp.project.Asset;
+import hxp.project.AssetType;
+import hxp.project.Haxelib;
+import hxp.project.HXProject;
+import hxp.project.Platform;
+import hxp.project.PlatformTarget;
+import sys.io.File;
+import sys.FileSystem;
+
+
+class WindowsPlatform extends PlatformTarget {
+
+
+ private var applicationDirectory:String;
+ private var executablePath:String;
+ private var is64:Bool;
+ private var targetType:String;
+ private var outputFile:String;
+
+
+ public function new (command:String, _project:HXProject, targetFlags:Map ) {
+
+ super (command, _project, targetFlags);
+
+ for (architecture in project.architectures) {
+
+ if (architecture == Architecture.X64) {
+
+ is64 = true;
+
+ }
+
+ }
+
+ if (project.targetFlags.exists ("uwp") || project.targetFlags.exists ("winjs")) {
+
+ targetType = "winjs";
+
+ } else if (project.targetFlags.exists ("neko") || project.target != PlatformHelper.hostPlatform) {
+
+ targetType = "neko";
+
+ } else if (project.targetFlags.exists ("hl")) {
+
+ targetType = "hl";
+
+ } else if (project.targetFlags.exists ("nodejs")) {
+
+ targetType = "nodejs";
+
+ } else if (project.targetFlags.exists ("cs")) {
+
+ targetType = "cs";
+
+ } else if (project.targetFlags.exists ("java")) {
+
+ targetType = "java";
+
+ } else {
+
+ targetType = "cpp";
+
+ }
+
+ targetDirectory = PathHelper.combine (project.app.path, project.config.getString ("windows.output-directory", targetType == "cpp" ? "windows" : targetType));
+ targetDirectory = StringTools.replace (targetDirectory, "arch64", is64 ? "64" : "");
+
+ if (targetType == "winjs") {
+
+ outputFile = targetDirectory + "/source/js/" + project.app.file + ".js";
+
+ } else {
+
+ applicationDirectory = targetDirectory + "/bin/";
+ executablePath = applicationDirectory + project.app.file + ".exe";
+
+ }
+
+ }
+
+
+ public override function build ():Void {
+
+ var hxml = targetDirectory + "/haxe/" + buildType + ".hxml";
+
+ PathHelper.mkdir (targetDirectory);
+
+ var icons = project.icons;
+
+ if (icons.length == 0) {
+
+ icons = [ new Icon (PathHelper.findTemplate (project.templatePaths, "default/icon.svg")) ];
+
+ }
+
+ if (targetType == "winjs") {
+
+ ModuleHelper.buildModules (project, targetDirectory, targetDirectory);
+
+ if (project.app.main != null) {
+
+ ProcessHelper.runCommand ("", "haxe", [ hxml ]);
+
+ var msBuildPath = "C:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\Community\\MSBuild\\15.0\\Bin\\MSBuild.exe";
+ var args = [ PathHelper.tryFullPath (targetDirectory + "/source/" + project.app.file + ".jsproj"), "/p:Configuration=Release" ];
+
+ ProcessHelper.runCommand ("", msBuildPath, args);
+ if (noOutput) return;
+
+ if (project.targetFlags.exists ("webgl")) {
+
+ FileHelper.copyFile (targetDirectory + "/source/ApplicationMain.js", outputFile);
+
+ }
+
+ if (project.modules.iterator ().hasNext ()) {
+
+ ModuleHelper.patchFile (outputFile);
+
+ }
+
+ if (project.targetFlags.exists ("minify") || buildType == "final") {
+
+ HTML5Helper.minify (project, targetDirectory + outputFile);
+
+ }
+
+ }
+
+ } else {
+
+ for (dependency in project.dependencies) {
+
+ if (StringTools.endsWith (dependency.path, ".dll")) {
+
+ var fileName = Path.withoutDirectory (dependency.path);
+ FileHelper.copyIfNewer (dependency.path, applicationDirectory + "/" + fileName);
+
+ }
+
+ }
+
+ if (!project.targetFlags.exists ("static") || targetType != "cpp") {
+
+ var targetSuffix = (targetType == "hl") ? ".hdll" : null;
+
+ for (ndll in project.ndlls) {
+
+ FileHelper.copyLibrary (project, ndll, "Windows" + (is64 ? "64" : ""), "", (ndll.haxelib != null && (ndll.haxelib.name == "hxcpp" || ndll.haxelib.name == "hxlibc")) ? ".dll" : ".ndll", applicationDirectory, project.debug, targetSuffix);
+
+ }
+
+ }
+
+ //IconHelper.createIcon (project.icons, 32, 32, PathHelper.combine (applicationDirectory, "icon.png"));
+
+ if (targetType == "neko") {
+
+ ProcessHelper.runCommand ("", "haxe", [ hxml ]);
+
+ if (noOutput) return;
+
+ var iconPath = PathHelper.combine (applicationDirectory, "icon.ico");
+
+ if (!IconHelper.createWindowsIcon (icons, iconPath)) {
+
+ iconPath = null;
+
+ }
+
+ NekoHelper.createWindowsExecutable (project.templatePaths, targetDirectory + "/obj/ApplicationMain.n", executablePath, iconPath);
+ NekoHelper.copyLibraries (project.templatePaths, "windows" + (is64 ? "64" : ""), applicationDirectory);
+
+ } else if (targetType == "hl") {
+
+ ProcessHelper.runCommand ("", "haxe", [ hxml ]);
+
+ if (noOutput) return;
+
+ FileHelper.copyFile (targetDirectory + "/obj/ApplicationMain.hl", PathHelper.combine (applicationDirectory, project.app.file + ".hl"));
+
+ } else if (targetType == "nodejs") {
+
+ ProcessHelper.runCommand ("", "haxe", [ hxml ]);
+
+ if (noOutput) return;
+
+ //NekoHelper.createExecutable (project.templatePaths, "windows" + (is64 ? "64" : ""), targetDirectory + "/obj/ApplicationMain.n", executablePath);
+ //NekoHelper.copyLibraries (project.templatePaths, "windows" + (is64 ? "64" : ""), applicationDirectory);
+
+ } else if (targetType == "cs") {
+
+ ProcessHelper.runCommand ("", "haxe", [ hxml ]);
+
+ if (noOutput) return;
+
+ CSHelper.copySourceFiles (project.templatePaths, targetDirectory + "/obj/src");
+ var txtPath = targetDirectory + "/obj/hxcs_build.txt";
+ CSHelper.addSourceFiles (txtPath, CSHelper.ndllSourceFiles);
+ CSHelper.addGUID (txtPath, GUID.uuid ());
+ CSHelper.compile (project, targetDirectory + "/obj", applicationDirectory + project.app.file, "x86", "desktop");
+
+ } else if (targetType == "java") {
+
+ var libPath = PathHelper.combine (PathHelper.getHaxelib (new Haxelib ("lime")), "templates/java/lib/");
+
+ ProcessHelper.runCommand ("", "haxe", [ hxml, "-java-lib", libPath + "disruptor.jar", "-java-lib", libPath + "lwjgl.jar" ]);
+ //ProcessHelper.runCommand ("", "haxe", [ hxml ]);
+
+ if (noOutput) return;
+
+ var haxeVersion = project.environment.get ("haxe_ver");
+ var haxeVersionString = "3404";
+
+ if (haxeVersion.length > 4) {
+
+ haxeVersionString = haxeVersion.charAt (0) + haxeVersion.charAt (2) + (haxeVersion.length == 5 ? "0" + haxeVersion.charAt (4) : haxeVersion.charAt (4) + haxeVersion.charAt (5));
+
+ }
+
+ ProcessHelper.runCommand (targetDirectory + "/obj", "haxelib", [ "run", "hxjava", "hxjava_build.txt", "--haxe-version", haxeVersionString ]);
+ FileHelper.recursiveCopy (targetDirectory + "/obj/lib", PathHelper.combine (applicationDirectory, "lib"));
+ FileHelper.copyFile (targetDirectory + "/obj/ApplicationMain" + (project.debug ? "-Debug" : "") + ".jar", PathHelper.combine (applicationDirectory, project.app.file + ".jar"));
+ JavaHelper.copyLibraries (project.templatePaths, "Windows" + (is64 ? "64" : ""), applicationDirectory);
+
+ } else {
+
+ var haxeArgs = [ hxml ];
+ var flags = [];
+
+ if (is64) {
+
+ haxeArgs.push ("-D");
+ haxeArgs.push ("HXCPP_M64");
+ flags.push ("-DHXCPP_M64");
+
+ } else {
+
+ flags.push ("-DHXCPP_M32");
+
+ }
+
+ if (!project.environment.exists ("SHOW_CONSOLE")) {
+
+ haxeArgs.push ("-D");
+ haxeArgs.push ("no_console");
+ flags.push ("-Dno_console");
+
+ }
+
+ if (!project.targetFlags.exists ("static")) {
+
+ ProcessHelper.runCommand ("", "haxe", haxeArgs);
+
+ if (noOutput) return;
+
+ CPPHelper.compile (project, targetDirectory + "/obj", flags);
+
+ FileHelper.copyFile (targetDirectory + "/obj/ApplicationMain" + (project.debug ? "-debug" : "") + ".exe", executablePath);
+
+ } else {
+
+ ProcessHelper.runCommand ("", "haxe", haxeArgs.concat ([ "-D", "static_link" ]));
+
+ if (noOutput) return;
+
+ CPPHelper.compile (project, targetDirectory + "/obj", flags.concat ([ "-Dstatic_link" ]));
+ CPPHelper.compile (project, targetDirectory + "/obj", flags, "BuildMain.xml");
+
+ FileHelper.copyFile (targetDirectory + "/obj/Main" + (project.debug ? "-debug" : "") + ".exe", executablePath);
+
+ }
+
+ var iconPath = PathHelper.combine (applicationDirectory, "icon.ico");
+
+ if (IconHelper.createWindowsIcon (icons, iconPath) && PlatformHelper.hostPlatform == Platform.WINDOWS) {
+
+ var templates = [ PathHelper.getHaxelib (new Haxelib ("lime")) + "/templates" ].concat (project.templatePaths);
+ ProcessHelper.runCommand ("", PathHelper.findTemplate (templates, "bin/ReplaceVistaIcon.exe"), [ executablePath, iconPath, "1" ], true, true);
+
+ }
+
+ }
+
+ }
+
+ }
+
+
+ public override function clean ():Void {
+
+ if (FileSystem.exists (targetDirectory)) {
+
+ PathHelper.removeDirectory (targetDirectory);
+
+ }
+
+ }
+
+
+ public override function deploy ():Void {
+
+ DeploymentHelper.deploy (project, targetFlags, targetDirectory, "Windows" + (is64 ? "64" : ""));
+
+ }
+
+
+ public override function display ():Void {
+
+ Sys.println (getDisplayHXML ());
+
+ }
+
+
+ private function generateContext ():Dynamic {
+
+ var context = project.templateContext;
+
+ if (targetType == "winjs") {
+
+ context.WIN_FLASHBACKGROUND = project.window.background != null ? StringTools.hex (project.window.background, 6) : "";
+ context.OUTPUT_FILE = outputFile;
+
+ if (project.targetFlags.exists ("webgl")) {
+
+ context.CPP_DIR = targetDirectory;
+
+ }
+
+ var guid = GUID.seededUuid (project.meta.packageName);
+ context.APP_GUID = guid;
+
+ var guidNoBrackets = guid.split("{").join("").split("}").join("");
+ context.APP_GUID_NOBRACKETS = guidNoBrackets;
+
+ if (context.APP_DESCRIPTION == null || context.APP_DESCRIPTION == "") {
+
+ context.APP_DESCRIPTION = project.meta.title;
+
+ }
+
+ } else {
+
+ context.NEKO_FILE = targetDirectory + "/obj/ApplicationMain.n";
+ context.NODE_FILE = targetDirectory + "/bin/ApplicationMain.js";
+ context.HL_FILE = targetDirectory + "/obj/ApplicationMain.hl";
+ context.CPP_DIR = targetDirectory + "/obj";
+ context.BUILD_DIR = project.app.path + "/windows" + (is64 ? "64" : "");
+
+ }
+
+ return context;
+
+ }
+
+
+ private function getDisplayHXML ():String {
+
+ var hxml = PathHelper.findTemplate (project.templatePaths, targetType + "/hxml/" + buildType + ".hxml");
+ var template = new Template (File.getContent (hxml));
+
+ var context = generateContext ();
+ context.OUTPUT_DIR = targetDirectory;
+
+ return template.execute (context) + "\n-D display";
+
+ }
+
+
+ public override function rebuild ():Void {
+
+ if (targetType != "winjs") {
+
+ if (project.environment.exists ("VS110COMNTOOLS") && project.environment.exists ("VS100COMNTOOLS")) {
+
+ project.environment.set ("HXCPP_MSVC", project.environment.get ("VS100COMNTOOLS"));
+ Sys.putEnv ("HXCPP_MSVC", project.environment.get ("VS100COMNTOOLS"));
+
+ }
+
+ var commands = [];
+
+ if (targetFlags.exists ("64")) {
+
+ commands.push ([ "-Dwindow", "-DHXCPP_M64" ]);
+
+ } else {
+
+ commands.push ([ "-Dwindow", "-DHXCPP_M32" ]);
+
+ }
+
+ CPPHelper.rebuild (project, commands);
+
+ }
+
+ }
+
+
+ public override function run ():Void {
+
+ var arguments = additionalArguments.copy ();
+
+ if (LogHelper.verbose) {
+
+ arguments.push ("-verbose");
+
+ }
+
+ if (targetType == "hl") {
+
+ ProcessHelper.runCommand (applicationDirectory, "hl", [ project.app.file + ".hl" ].concat (arguments));
+
+ } else if (targetType == "nodejs") {
+
+ NodeJSHelper.run (project, targetDirectory + "/bin/ApplicationMain.js", arguments);
+
+ } else if (targetType == "winjs") {
+
+ /*
+
+ The 'test' target is problematic for UWP applications. UWP applications are bundled in appx packages and
+ require app certs to properly install.
+
+ There are two options to trigger an appx install from the command line.
+
+ A. Use the WinAppDeployCmd.exe utility to deploy to local and remote devices
+
+ B. Execute the Add-AppDevPackage.ps1 powershell script that is an
+ artifact of the UWP msbuild
+
+ A: WinAppDeployCmd.exe
+ https://docs.microsoft.com/en-us/windows/uwp/packaging/install-universal-windows-apps-with-the-winappdeploycmd-tool
+ https://msdn.microsoft.com/en-us/windows/desktop/mt627714
+ Windows 10 SDK: https://developer.microsoft.com/windows/downloads/windows-10-sdk
+
+ I've never actually got this to work, but I feel like I was close. The WinAppDeployCmd.exe is a part of the
+ Windows 10 SDK and not a part of the Visual Studio 2017 community edition. It will appear magically if you
+ check enough boxes when installing various project templates for Visual Studio. It appeared for me, and I
+ have no clue how it got there.
+
+ A developer must take a few steps in order for this command to work.
+ 1. Install Visual Studio 2017 Community Edition
+ 2. Install the Windows 10 SDK
+ 3. Modify Windows 10 Settings to enable side loading and device discovery
+ 3. Enabling device discovery generates a pin number that is displayed to the user
+ 4. Open the "Developer Command Promp for VS 2017" from the Start menu
+ 5. run:
+ > WinAppDeployCmd devices
+ 6. Make sure your device shows up in the list (if it does not appear try step 3 again, toggling things on/off)
+ 7. run: (replase file, ip and pin with your values)
+ > WinAppDeployCmd install -file "uwp-project_1.0.0.0_AnyCPU.appx" -ip 192.168.27.167 -pin 326185
+
+ B: Add-AppDevPackage.ps1 + PowerShell_Set_Unrestricted.reg
+ The UWP build generates a powershell script by default. This script is usually executed by the user
+ by right clicking the file and choosing "run with powershell". Executing this script directly from the cmd
+ prompt results in a security error: "Add-AppDevPackage.ps1 cannot be loaded because running scripts is
+ disabled on this system."
+
+ We must edit the registry if we want to run this script directly from a shell.
+ See lime/templates/windows/template/PowerShell_Set_Unrestricted.reg
+
+ 1. run:
+ > regedit /s PowerShell_Set_Unrestricted.reg
+ 2. run:
+ > powershell "& ""./Add-AppDevPackage.ps1"""
+
+ note: the nonsensical double quotes are required.
+
+ */
+
+ // Using option B because obtaining the device pin programatically does not seem possible.
+ //ProcessHelper.runCommand ("", "regedit", [ '/s', '"' + targetDirectory + '/bin/PowerShell_Set_Unrestricted.reg"' ]);
+ //var test = '"& ""' + targetDirectory + '/bin/PowerShell_Set_Unrestricted.reg"""';
+ //Sys.command ('powershell & ""' + targetDirectory + '/bin/source/AppPackages/' + project.app.file + '_1.0.0.0_AnyCPU_Test/Add-AppDevPackage.ps1""');
+ var version = project.meta.version + "." + project.meta.buildNumber;
+ ProcessHelper.openFile (targetDirectory + "/source/AppPackages/" + project.app.file + "_" + version + "_AnyCPU_Test", project.app.file + "_" + version + "_AnyCPU.appx");
+
+ //source/AppPackages/uwp-project_1.0.0.0_AnyCPU_Test/Add-AppDevPackage.ps1
+
+ //HTML5Helper.launch (project, targetDirectory + "/bin");
+
+ } else if (targetType == "java") {
+
+ ProcessHelper.runCommand (applicationDirectory, "java", [ "-jar", project.app.file + ".jar" ].concat (arguments));
+
+ } else if (project.target == PlatformHelper.hostPlatform) {
+
+ arguments = arguments.concat ([ "-livereload" ]);
+ ProcessHelper.runCommand (applicationDirectory, Path.withoutDirectory (executablePath), arguments);
+
+ }
+
+ }
+
+
+ public override function update ():Void {
+
+ if (targetType == "winjs") {
+
+ updateUWP ();
+ return;
+
+ }
+
+ // project = project.clone ();
+
+ if (project.targetFlags.exists ("xml")) {
+
+ project.haxeflags.push ("-xml " + targetDirectory + "/types.xml");
+
+ }
+
+ for (asset in project.assets) {
+
+ if (asset.embed && asset.sourcePath == "") {
+
+ var path = PathHelper.combine (targetDirectory + "/obj/tmp", asset.targetPath);
+ PathHelper.mkdir (Path.directory (path));
+ FileHelper.copyAsset (asset, path);
+ asset.sourcePath = path;
+
+ }
+
+ }
+
+ var context = generateContext ();
+ context.OUTPUT_DIR = targetDirectory;
+
+ if (targetType == "cpp" && project.targetFlags.exists ("static")) {
+
+ // TODO: Better way to detect the suffix HXCPP will use?
+
+ var msvc19 = true;
+ var olderVersions = [ "120", "110", "100", "90", "80", "71", "70" ];
+
+ for (olderVersion in olderVersions) {
+
+ if (project.environment.exists ("VS" + olderVersion + "COMNTOOLS")) {
+
+ msvc19 = false;
+ break;
+
+ }
+
+ }
+
+ var suffix = (msvc19 ? "-19.lib" : ".lib");
+
+ for (i in 0...project.ndlls.length) {
+
+ var ndll = project.ndlls[i];
+
+ if (ndll.path == null || ndll.path == "") {
+
+ context.ndlls[i].path = PathHelper.getLibraryPath (ndll, "Windows" + (is64 ? "64" : ""), "lib", suffix, project.debug);
+
+ }
+
+ }
+
+ }
+
+ PathHelper.mkdir (targetDirectory);
+ PathHelper.mkdir (targetDirectory + "/obj");
+ PathHelper.mkdir (targetDirectory + "/haxe");
+ PathHelper.mkdir (applicationDirectory);
+
+ //SWFHelper.generateSWFClasses (project, targetDirectory + "/haxe");
+
+ FileHelper.recursiveSmartCopyTemplate (project, "haxe", targetDirectory + "/haxe", context);
+ FileHelper.recursiveSmartCopyTemplate (project, targetType + "/hxml", targetDirectory + "/haxe", context);
+
+ if (targetType == "cpp" && project.targetFlags.exists ("static")) {
+
+ FileHelper.recursiveSmartCopyTemplate (project, "cpp/static", targetDirectory + "/obj", context);
+
+ }
+
+ /*if (IconHelper.createIcon (project.icons, 32, 32, PathHelper.combine (applicationDirectory, "icon.png"))) {
+
+ context.HAS_ICON = true;
+ context.WIN_ICON = "icon.png";
+
+ }*/
+
+ for (asset in project.assets) {
+
+ if (asset.embed != true) {
+
+ var path = PathHelper.combine (applicationDirectory, asset.targetPath);
+
+ if (asset.type != AssetType.TEMPLATE) {
+
+ PathHelper.mkdir (Path.directory (path));
+ FileHelper.copyAssetIfNewer (asset, path);
+
+ } else {
+
+ PathHelper.mkdir (Path.directory (path));
+ FileHelper.copyAsset (asset, path, context);
+
+ }
+
+ }
+
+ }
+
+ }
+
+
+ private function updateUWP ():Void {
+
+ project = project.clone ();
+
+ var destination = targetDirectory + "/source/";
+ PathHelper.mkdir (destination);
+
+ var webfontDirectory = targetDirectory + "/obj/webfont";
+ var useWebfonts = true;
+
+ for (haxelib in project.haxelibs) {
+
+ if (haxelib.name == "openfl-html5-dom" || haxelib.name == "openfl-bitfive") {
+
+ useWebfonts = false;
+
+ }
+
+ }
+
+ var fontPath;
+
+ for (asset in project.assets) {
+
+ if (asset.type == AssetType.FONT) {
+
+ if (useWebfonts) {
+
+ fontPath = PathHelper.combine (webfontDirectory, Path.withoutDirectory (asset.targetPath));
+
+ if (!FileSystem.exists (fontPath)) {
+
+ PathHelper.mkdir (webfontDirectory);
+ FileHelper.copyFile (asset.sourcePath, fontPath);
+
+ asset.sourcePath = fontPath;
+
+ HTML5Helper.generateWebfonts (project, asset);
+
+ }
+
+ asset.sourcePath = fontPath;
+ asset.targetPath = Path.withoutExtension (asset.targetPath);
+
+ } else {
+
+ project.haxeflags.push (HTML5Helper.generateFontData (project, asset));
+
+ }
+
+ }
+
+ }
+
+ if (project.targetFlags.exists ("xml")) {
+
+ project.haxeflags.push ("-xml " + targetDirectory + "/types.xml");
+
+ }
+
+ if (LogHelper.verbose) {
+
+ project.haxedefs.set ("verbose", 1);
+
+ }
+
+ ModuleHelper.updateProject (project);
+
+ var libraryNames = new Map ();
+
+ for (asset in project.assets) {
+
+ if (asset.library != null && !libraryNames.exists (asset.library)) {
+
+ libraryNames[asset.library] = true;
+
+ }
+
+ }
+
+ //for (library in libraryNames.keys ()) {
+ //
+ //project.haxeflags.push ("-resource " + targetDirectory + "/obj/manifest/" + library + ".json@__ASSET_MANIFEST__" + library);
+ //
+ //}
+
+ //project.haxeflags.push ("-resource " + targetDirectory + "/obj/manifest/default.json@__ASSET_MANIFEST__default");
+
+ var context = generateContext ();
+ context.OUTPUT_DIR = targetDirectory;
+
+ context.favicons = [];
+
+ var icons = project.icons;
+
+ if (icons.length == 0) {
+
+ icons = [ new Icon (PathHelper.findTemplate (project.templatePaths, "default/icon.svg")) ];
+
+ }
+
+ //if (IconHelper.createWindowsIcon (icons, PathHelper.combine (destination, "favicon.ico"))) {
+ //
+ //context.favicons.push ({ rel: "icon", type: "image/x-icon", href: "./favicon.ico" });
+ //
+ //}
+
+ if (IconHelper.createIcon (icons, 192, 192, PathHelper.combine (destination, "favicon.png"))) {
+
+ context.favicons.push ({ rel: "shortcut icon", type: "image/png", href: "./favicon.png" });
+
+ }
+
+ context.linkedLibraries = [];
+
+ for (dependency in project.dependencies) {
+
+ if (StringTools.endsWith (dependency.name, ".js")) {
+
+ context.linkedLibraries.push (dependency.name);
+
+ } else if (StringTools.endsWith (dependency.path, ".js") && FileSystem.exists (dependency.path)) {
+
+ var name = Path.withoutDirectory (dependency.path);
+
+ context.linkedLibraries.push ("./js/lib/" + name);
+ FileHelper.copyIfNewer (dependency.path, PathHelper.combine (destination, PathHelper.combine ("js/lib", name)));
+
+ }
+
+ }
+
+ for (asset in project.assets) {
+
+ var path = PathHelper.combine (destination, asset.targetPath);
+
+ if (asset.type != AssetType.TEMPLATE) {
+
+ if (asset.type != AssetType.FONT) {
+
+ PathHelper.mkdir (Path.directory (path));
+ FileHelper.copyAssetIfNewer (asset, path);
+
+ } else if (useWebfonts) {
+
+ PathHelper.mkdir (Path.directory (path));
+ var ext = "." + Path.extension (asset.sourcePath);
+ var source = Path.withoutExtension (asset.sourcePath);
+
+ for (extension in [ ext, ".eot", ".woff", ".svg" ]) {
+
+ if (FileSystem.exists (source + extension)) {
+
+ FileHelper.copyIfNewer (source + extension, path + extension);
+
+ } else {
+
+ LogHelper.warn ("Could not find generated font file \"" + source + extension + "\"");
+
+ }
+
+ }
+
+ }
+
+ }
+
+ }
+
+ FileHelper.recursiveSmartCopyTemplate (project, "winjs/template", targetDirectory, context);
+
+ var renamePaths = [ "uwp-project.sln", "source/uwp-project.jsproj", "source/uwp-project_TemporaryKey.pfx" ];
+ var fullPath;
+
+ for (path in renamePaths) {
+
+ fullPath = targetDirectory + "/" + path;
+
+ try {
+
+ if (FileSystem.exists (fullPath)) {
+
+ File.copy (fullPath, targetDirectory + "/" + StringTools.replace (path, "uwp-project", project.app.file));
+ FileSystem.deleteFile (fullPath);
+
+ }
+
+ } catch (e:Dynamic) {}
+
+ }
+
+ if (project.app.main != null) {
+
+ FileHelper.recursiveSmartCopyTemplate (project, "haxe", targetDirectory + "/haxe", context);
+ FileHelper.recursiveSmartCopyTemplate (project, "winjs/haxe", targetDirectory + "/haxe", context, true, false);
+ FileHelper.recursiveSmartCopyTemplate (project, "winjs/hxml", targetDirectory + "/haxe", context);
+
+ if (project.targetFlags.exists ("webgl")) {
+
+ FileHelper.recursiveSmartCopyTemplate (project, "webgl/hxml", targetDirectory + "/haxe", context, true, false);
+
+ }
+
+ }
+
+ for (asset in project.assets) {
+
+ var path = PathHelper.combine (destination, asset.targetPath);
+
+ if (asset.type == AssetType.TEMPLATE) {
+
+ PathHelper.mkdir (Path.directory (path));
+ FileHelper.copyAsset (asset, path, context);
+
+ }
+
+ }
+
+ }
+
+
+ public override function watch ():Void {
+
+ var dirs = WatchHelper.processHXML (project, getDisplayHXML ());
+ var command = WatchHelper.getCurrentCommand ();
+ WatchHelper.watch (project, command, dirs);
+
+ }
+
+
+ @ignore public override function install ():Void {}
+ @ignore public override function trace ():Void {}
+ @ignore public override function uninstall ():Void {}
+
+
+}
\ No newline at end of file