370 lines
8.6 KiB
Haxe
370 lines
8.6 KiB
Haxe
package lime.tools.helpers;
|
|
|
|
|
|
import haxe.io.Path;
|
|
import lime.tools.helpers.PathHelper;
|
|
import lime.tools.helpers.ProcessHelper;
|
|
import lime.project.Haxelib;
|
|
import lime.project.HXProject;
|
|
import sys.io.Process;
|
|
import sys.FileSystem;
|
|
|
|
|
|
class IOSHelper {
|
|
|
|
|
|
private static var initialized = false;
|
|
|
|
|
|
public static function build (project:HXProject, workingDirectory:String, additionalArguments:Array <String> = null):Void {
|
|
|
|
initialize (project);
|
|
|
|
var platformName = "iphoneos";
|
|
|
|
if (project.targetFlags.exists ("simulator")) {
|
|
|
|
platformName = "iphonesimulator";
|
|
|
|
}
|
|
|
|
var configuration = "Release";
|
|
|
|
if (project.debug) {
|
|
|
|
configuration = "Debug";
|
|
|
|
}
|
|
|
|
var iphoneVersion = project.environment.get ("IPHONE_VER");
|
|
var commands = [ "-configuration", configuration, "PLATFORM_NAME=" + platformName, "SDKROOT=" + platformName + iphoneVersion ];
|
|
|
|
if (project.targetFlags.exists("simulator")) {
|
|
|
|
commands.push ("-arch");
|
|
commands.push ("i386");
|
|
|
|
}
|
|
|
|
if (additionalArguments != null) {
|
|
|
|
commands = commands.concat (additionalArguments);
|
|
|
|
}
|
|
|
|
ProcessHelper.runCommand (workingDirectory, "xcodebuild", commands);
|
|
|
|
}
|
|
|
|
|
|
public static function getSDKDirectory (project:HXProject):String {
|
|
|
|
initialize (project);
|
|
|
|
var platformName = "iPhoneOS";
|
|
|
|
if (project.targetFlags.exists ("simulator")) {
|
|
|
|
platformName = "iPhoneSimulator";
|
|
|
|
}
|
|
|
|
var process = new Process ("xcode-select", [ "--print-path" ]);
|
|
var directory = process.stdout.readLine ();
|
|
process.close ();
|
|
|
|
if (directory == "" || directory.indexOf ("Run xcode-select") > -1) {
|
|
|
|
directory = "/Applications/Xcode.app/Contents/Developer";
|
|
|
|
}
|
|
|
|
directory += "/Platforms/" + platformName + ".platform/Developer/SDKs/" + platformName + project.environment.get ("IPHONE_VER") + ".sdk";
|
|
return directory;
|
|
|
|
}
|
|
|
|
|
|
private static function getIOSVersion (project:HXProject):Void {
|
|
|
|
if (!project.environment.exists("IPHONE_VER")) {
|
|
if (!project.environment.exists("DEVELOPER_DIR")) {
|
|
var proc = new Process("xcode-select", ["--print-path"]);
|
|
var developer_dir = proc.stdout.readLine();
|
|
proc.close();
|
|
project.environment.set("DEVELOPER_DIR", developer_dir);
|
|
}
|
|
var dev_path = project.environment.get("DEVELOPER_DIR") + "/Platforms/iPhoneOS.platform/Developer/SDKs";
|
|
|
|
if (FileSystem.exists (dev_path)) {
|
|
var best = "";
|
|
var files = FileSystem.readDirectory (dev_path);
|
|
var extract_version = ~/^iPhoneOS(.*).sdk$/;
|
|
|
|
for (file in files) {
|
|
if (extract_version.match (file)) {
|
|
var ver = extract_version.matched (1);
|
|
if (ver > best)
|
|
best = ver;
|
|
}
|
|
}
|
|
|
|
if (best != "")
|
|
project.environment.set ("IPHONE_VER", best);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
private static function getOSXVersion ():String {
|
|
|
|
var output = ProcessHelper.runProcess ("", "sw_vers", [ "-productVersion" ]);
|
|
|
|
return StringTools.trim (output);
|
|
|
|
}
|
|
|
|
|
|
public static function getProvisioningFile ():String {
|
|
|
|
var path = PathHelper.expand ("~/Library/MobileDevice/Provisioning Profiles");
|
|
var files = FileSystem.readDirectory (path);
|
|
|
|
for (file in files) {
|
|
|
|
if (Path.extension (file) == "mobileprovision") {
|
|
|
|
return path + "/" + file;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
|
|
private static function getXcodeVersion ():String {
|
|
|
|
var output = ProcessHelper.runProcess ("", "xcodebuild", [ "-version" ]);
|
|
var firstLine = output.split ("\n").shift ();
|
|
|
|
return StringTools.trim (firstLine.substring ("Xcode".length, firstLine.length));
|
|
|
|
}
|
|
|
|
|
|
private static function initialize (project:HXProject):Void {
|
|
|
|
if (!initialized) {
|
|
|
|
getIOSVersion (project);
|
|
|
|
initialized = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
public static function launch (project:HXProject, workingDirectory:String):Void {
|
|
|
|
initialize (project);
|
|
|
|
var configuration = "Release";
|
|
|
|
if (project.debug) {
|
|
|
|
configuration = "Debug";
|
|
|
|
}
|
|
|
|
if (project.targetFlags.exists ("simulator")) {
|
|
|
|
var applicationPath = "";
|
|
|
|
if (Path.extension (workingDirectory) == "app" || Path.extension (workingDirectory) == "ipa") {
|
|
|
|
applicationPath = workingDirectory;
|
|
|
|
} else {
|
|
|
|
applicationPath = workingDirectory + "/build/" + configuration + "-iphonesimulator/" + project.app.file + ".app";
|
|
|
|
}
|
|
|
|
var templatePaths = [ PathHelper.combine (PathHelper.getHaxelib (new Haxelib ("lime")), "templates") ].concat (project.templatePaths);
|
|
|
|
var output = ProcessHelper.runProcess ("", "xcrun", [ "simctl", "list", "devices" ]);
|
|
var lines = output.split ("\n");
|
|
var foundSection = false;
|
|
|
|
var device, deviceID;
|
|
var devices = new Map<String, String> ();
|
|
|
|
var currentDeviceID = null;
|
|
|
|
for (line in lines) {
|
|
|
|
if (StringTools.startsWith (line, "--")) {
|
|
|
|
if (line.indexOf ("iOS") > -1) {
|
|
|
|
foundSection = true;
|
|
|
|
} else if (foundSection) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else if (foundSection) {
|
|
|
|
device = StringTools.trim (line);
|
|
device = device.substring (0, device.indexOf ("(") - 1);
|
|
device = device.toLowerCase ();
|
|
device = StringTools.replace (device, " ", "-");
|
|
|
|
deviceID = line.substring (line.indexOf ("(") + 1, line.indexOf (")"));
|
|
|
|
if (deviceID.indexOf ("inch") > -1) {
|
|
|
|
var startIndex = line.indexOf (")") + 2;
|
|
deviceID = line.substring (line.indexOf ("(", startIndex) + 1, line.indexOf (")", startIndex));
|
|
|
|
}
|
|
|
|
devices.set (device, deviceID);
|
|
|
|
if (project.targetFlags.exists (device)) {
|
|
|
|
currentDeviceID = deviceID;
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (currentDeviceID == null) {
|
|
|
|
if (project.targetFlags.exists ("ipad")) {
|
|
|
|
currentDeviceID = devices.get ("ipad-air");
|
|
|
|
} else {
|
|
|
|
currentDeviceID = devices.get ("iphone-6");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
try {
|
|
|
|
ProcessHelper.runProcess ("", "open", [ "-Ra", "iOS Simulator" ], true, false);
|
|
ProcessHelper.runCommand ("", "open", [ "-a", "iOS Simulator", "--args", "-CurrentDeviceUDID", currentDeviceID ]);
|
|
|
|
} catch (e:Dynamic) {
|
|
|
|
ProcessHelper.runCommand ("", "open", [ "-a", "Simulator", "--args", "-CurrentDeviceUDID", currentDeviceID ]);
|
|
|
|
}
|
|
|
|
waitForDeviceState ("xcrun", [ "simctl", "uninstall", currentDeviceID, project.meta.packageName ]);
|
|
waitForDeviceState ("xcrun", [ "simctl", "install", currentDeviceID, applicationPath ]);
|
|
waitForDeviceState ("xcrun", [ "simctl", "launch", currentDeviceID, project.meta.packageName ]);
|
|
|
|
ProcessHelper.runCommand ("", "tail", [ "-F", "~/Library/Logs/CoreSimulator/" + currentDeviceID + "/system.log"]);
|
|
|
|
} else {
|
|
|
|
var applicationPath = "";
|
|
|
|
if (Path.extension (workingDirectory) == "app" || Path.extension (workingDirectory) == "ipa") {
|
|
|
|
applicationPath = workingDirectory;
|
|
|
|
} else {
|
|
|
|
applicationPath = workingDirectory + "/build/" + configuration + "-iphoneos/" + project.app.file + ".app";
|
|
|
|
}
|
|
|
|
var templatePaths = [ PathHelper.combine (PathHelper.getHaxelib (new Haxelib ("lime")), "templates") ].concat (project.templatePaths);
|
|
var launcher = PathHelper.findTemplate (templatePaths, "bin/ios-deploy");
|
|
Sys.command ("chmod", [ "+x", launcher ]);
|
|
|
|
var xcodeVersion = getXcodeVersion ();
|
|
|
|
ProcessHelper.runCommand ("", launcher, [ "install", "--noninteractive", "--debug", "--timeout", "5", "--bundle", FileSystem.fullPath (applicationPath) ]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
public static function sign (project:HXProject, workingDirectory:String, entitlementsPath:String):Void {
|
|
|
|
initialize (project);
|
|
|
|
var configuration = "Release";
|
|
|
|
if (project.debug) {
|
|
|
|
configuration = "Debug";
|
|
|
|
}
|
|
|
|
var identity = "iPhone Developer";
|
|
|
|
if (project.certificate != null && project.certificate.identity != null) {
|
|
|
|
identity = project.certificate.identity;
|
|
|
|
}
|
|
|
|
var commands = [ "-s", identity ];
|
|
|
|
if (entitlementsPath != null) {
|
|
|
|
commands.push ("--entitlements");
|
|
commands.push (entitlementsPath);
|
|
|
|
}
|
|
|
|
var applicationPath = "build/" + configuration + "-iphoneos/" + project.app.file + ".app";
|
|
commands.push (applicationPath);
|
|
|
|
ProcessHelper.runCommand (workingDirectory, "codesign", commands, true, true);
|
|
|
|
}
|
|
|
|
|
|
private static function waitForDeviceState (command:String, args:Array<String>):Void {
|
|
|
|
var output;
|
|
|
|
while (true) {
|
|
|
|
output = ProcessHelper.runProcess ("", command, args, true, true, true);
|
|
|
|
if (output != null && output.toLowerCase ().indexOf ("invalid device state") > -1) {
|
|
|
|
Sys.sleep (3);
|
|
|
|
} else {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
} |