public bool CreatePodfile(Podfile podfile, string podfilePath) { if (CancellationToken.IsCancellationRequested) { Log.LogError("Task was canceled."); return(false); } var podfileContents = $"{(podfile.UseFrameworks ? "use_frameworks!" : "")}\n" + $"platform :{podfile.PlatformName}, '{podfile.PlatformVersion}'\n" + $"target '{podfile.TargetName}' do\n"; foreach (var pod in podfile.Pods) { podfileContents += $" pod '{pod.Id}', '{pod.Version}'\n"; } podfileContents += $"end"; Ssh.CreateDirectory(CrossPath.GetDirectoryNameSsh(podfilePath)); using (var stream = Utilities.GetStreamFromText(podfileContents)) { Ssh.CreateFile(stream, podfilePath); } return(true); }
public bool ExecuteLaunchCtlCommand(string[] arguments, int checkInterval = 600, string workingDirectory = null) { var binary = arguments.FirstOrDefault(); var options = new StartOptions { Id = Process.GetCurrentProcess().Id.ToString(), DateTime = DateTime.Now }; var labelName = $"com.xamarin.nativebuild.tasks.{options.GetFormattedDateTime()}.{options.Id}.{Path.GetFileNameWithoutExtension(binary)}".ToLowerInvariant(); var root = $"/tmp/{labelName}"; var outputLog = CrossPath.CombineSsh(root, "output.log"); var errorLog = CrossPath.CombineSsh(root, "error.log"); var appPList = CrossPath.CombineSsh(root, "app.plist"); // upload the plist var plist = CreatePList(labelName, outputLog, errorLog, arguments, workingDirectory); CreateDirectory(root); using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(plist))) { CreateFile(stream, appPList); } // create the logs and start the process var launchctl = ExecuteCommand($"touch {outputLog}; touch {errorLog}; launchctl load -S Aqua {appPList}"); if (!WasSuccess(launchctl)) { Log.LogError($"Unable to starting {binary}: {launchctl.Result}"); return(false); } // tail and stream the output var tailOutput = ExecuteCommandStream($"tail -f {outputLog} & while launchctl list {labelName} &> /dev/null; do sleep {checkInterval / 1000}; done; kill $!;"); if (!WasSuccess(tailOutput)) { Log.LogError($"There was an error reading the output: {tailOutput.Result}"); return(false); } // get the errors var tailError = ExecuteCommand($"cat {errorLog}"); if (!WasSuccess(tailError)) { Log.LogError($"There was an error reading the error log: {tailError.Result}"); return(false); } else if (!string.IsNullOrEmpty(tailError.Result)) { Log.LogError($"There was an error: {tailError.Result}"); return(false); } return(true); }
public bool CreatePodfileXCodeProject(string podfileRoot, Podfile podfile, bool?noRepoUpdate = null) { if (CancellationToken.IsCancellationRequested) { Log.LogError("Task was canceled."); return(false); } var podfilePath = CrossPath.CombineSsh(podfileRoot, "Podfile"); var podfileLockPath = CrossPath.CombineSsh(podfileRoot, "Podfile.lock"); // see if we can avoid updating the master repo noRepoUpdate = noRepoUpdate == true || (noRepoUpdate == null && Ssh.FileExists(podfileLockPath)); // create and restore a Podfile return(CreatePodfile(podfile, podfilePath) && RestorePodfile(podfileRoot, noRepoUpdate)); }
public bool RestoreDependencies(string buildGradleRoot, IEnumerable <GradleDependency> dependencies, ICollection <GradleLibrary> libraries) { var buildGradlePath = Path.Combine(CrossPath.ToCurrent(buildGradleRoot), "build.gradle"); if (!CreateBuildGradle(buildGradlePath, dependencies)) { return(false); } var libs = GetLibraries(buildGradlePath); if (libs == null) { Log.LogError("Unable to restore gradle packages."); return(false); } if (!ProcessLibraries(dependencies, libs, libraries)) { return(false); } return(true); }
private XCodeBuildOutputs BuildPodfileXCodeProject(string podfileRoot, string[] targets, XCodeArchitectures architectures, bool framework) { var parameters = new XCodeBuildParameters { ArchitectureSettings = XCodeBuildArchitecture, ArtifactsDirectory = CrossPath.CombineSsh(podfileRoot, "build"), OutputDirectory = CrossPath.CombineSsh(podfileRoot, "out"), IsFrameworks = framework, ProjectFilePath = CrossPath.CombineSsh(podfileRoot, "Pods/Pods.xcodeproj"), BuildTargets = new[] { "Pods-MSBuildTask" }, OutputTargets = targets, ArchitectureOverride = architectures }; var outputs = new XCodeBuildOutputs(); if (XCodeBuild.BuildXCodeProject(parameters, outputs)) { return(outputs); } else { return(null); } }
public bool BuildXCodeProject(XCodeBuildParameters parameters, XCodeBuildOutputs outputs) { outputs.ProjectDirectory = CrossPath.GetDirectoryNameSsh(parameters.ProjectFilePath); outputs.OutputDirectory = parameters.OutputDirectory ?? CrossPath.CombineSsh(outputs.ProjectDirectory, "out"); outputs.ArtifactsDirectory = parameters.ArtifactsDirectory ?? CrossPath.CombineSsh(outputs.ProjectDirectory, "build"); foreach (var arch in parameters.SplitArchitectures) { if (CancellationToken.IsCancellationRequested) { Log.LogError("Task was canceled."); return(false); } var artifactsPath = CrossPath.CombineSsh(outputs.ArtifactsDirectory, parameters.ArchitectureSettings.GetArtifactDirectoryName("Release", arch: arch)); // build the project var result = Ssh.ExecuteLaunchCtlCommand( workingDirectory: outputs.ProjectDirectory, arguments: new[] { XCodeBuildToolPath, "-project", parameters.ProjectFilePath, "-target", parameters.BuildTargets[0], // TODO "-configuration", "Release", "-arch", arch.ToString().ToLowerInvariant(), "-sdk", parameters.ArchitectureSettings.GetSdk(arch).ToString().ToLowerInvariant(), "build" }); if (!result) { Log.LogError($"Error building the XCode project."); return(false); } if (CancellationToken.IsCancellationRequested) { Log.LogError("Task was canceled."); return(false); } // copy the artifacts to the intermediates directory, naming them per architecture foreach (var target in parameters.OutputTargets) { // this might be set multiple times as this is target-based, // but we are building the same target multiple times for each arch outputs[target].IntermediateDirectory = CrossPath.CombineSsh(outputs.OutputDirectory, target, "obj"); Ssh.CreateDirectory(outputs[target].IntermediateDirectory); var currentIntermediate = outputs[target].Intermediates[arch]; currentIntermediate.IsFrameworks = parameters.IsFrameworks; if (parameters.IsFrameworks) { var cleanTarget = CleanFrameworkName(target); currentIntermediate.Path = CrossPath.CombineSsh(outputs[target].IntermediateDirectory, $"{cleanTarget}-{arch}.framework"); Ssh.CopyPath(CrossPath.CombineSsh(artifactsPath, $"{cleanTarget}.framework"), currentIntermediate.Path); } else { currentIntermediate.Path = CrossPath.CombineSsh(outputs.OutputDirectory, target, "obj", $"lib{target}-{arch}.a"); Ssh.CopyPath(CrossPath.CombineSsh(artifactsPath, $"lib{target}.a"), currentIntermediate.Path); } } } // run lipo on the outputs, from the obj to the out foreach (var targetOutput in outputs) { targetOutput.Directory = CrossPath.CombineSsh(parameters.OutputDirectory, targetOutput.Target); // lipo the .a var staticIntermediates = targetOutput.Intermediates.Where(i => !i.IsFrameworks); if (staticIntermediates.Any()) { targetOutput.ArchiveOutput = new BuildArchitectureOutput(targetOutput) { Architecture = Utilities.CreateEnum(staticIntermediates.Select(i => i.Architecture)), IsFrameworks = false, Path = CrossPath.CombineSsh(parameters.OutputDirectory, targetOutput.Target, $"lib{targetOutput.Target}.a") }; if (!RunLipo(targetOutput.ArchiveOutput.Path, staticIntermediates.Select(i => i.Path))) { return(false); } } // lipo the .framework var frameworkIntermediates = targetOutput.Intermediates.Where(i => i.IsFrameworks); if (frameworkIntermediates.Any()) { var cleanTarget = CleanFrameworkName(targetOutput.Target); targetOutput.FrameworkOutput = new BuildArchitectureOutput(targetOutput) { Architecture = Utilities.CreateEnum(frameworkIntermediates.Select(i => i.Architecture)), IsFrameworks = true, Path = CrossPath.CombineSsh(parameters.OutputDirectory, targetOutput.Target, $"{cleanTarget}.framework") }; // copy the first arch as we need the other files var firstArch = frameworkIntermediates.First(); Ssh.CopyPath(firstArch.Path, targetOutput.FrameworkOutput.Path); // now lipo the archive if (!RunLipo(CrossPath.CombineSsh(targetOutput.FrameworkOutput.Path, cleanTarget), frameworkIntermediates.Select(i => CrossPath.CombineSsh(i.Path, cleanTarget)))) { return(false); } } } return(true); }
public void CreateFile(Stream stream, string remotePath) { Commands.Runner.Upload(stream, CrossPath.ToSsh(remotePath)); }
public string LocateToolPath(string toolPath, string tool, string versionOption) { string foundPath = null; if (!string.IsNullOrEmpty(toolPath)) { // if it was explicitly set, bail if it wasn't found toolPath = CrossPath.ToSsh(toolPath); if (Commands.FileExists(toolPath)) { foundPath = toolPath; } } else { // not set, so search var findTool = GetCommandResult($"which {tool}"); if (!string.IsNullOrEmpty(findTool)) { foundPath = findTool.Trim(); } else { // we didn't find {tool} in the default places, so do a bit of research var dirs = string.Join(" ", ToolSearchPaths); var command = $@"for file in {dirs}; do " + $@" if [ -e ""$file/{tool}"" ]; then" + $@" echo ""$file/{tool}""; " + $@" exit 0; " + $@" fi; " + $@"done; " + $@"exit 1; "; findTool = GetCommandResult(command); if (!string.IsNullOrEmpty(findTool)) { foundPath = findTool.Trim(); } } } if (string.IsNullOrEmpty(foundPath)) { Log.LogError($"Unable to find {tool}."); } else { foundPath = CrossPath.ToSsh(foundPath); if (string.IsNullOrEmpty(versionOption)) { Log.LogVerbose($"Found {tool} at {foundPath}."); } else { var version = GetCommandResult($"{foundPath} {versionOption}"); Log.LogVerbose($"Found {tool} version {version} at {foundPath}."); } } return(foundPath); }
public bool FileExists(string filePath) { return(Commands.FileExists(CrossPath.ToSsh(filePath))); }
public void CreateDirectory(string directoryPath) { Commands.CreateDirectory(CrossPath.ToSsh(directoryPath)); }
public void CopyPath(string source, string destination) { ExecuteCommand($@"cp -rf ""{CrossPath.ToSsh(source)}"" ""{CrossPath.ToSsh(destination)}"""); }