public static Process RunNoWait(string executable, string arguments, ShellProcessArgs processArgs, DataReceivedEventHandler outputReceived = null, DataReceivedEventHandler errorReceived = null) { try { var exeDir = Where(executable, processArgs.ExtraPaths); if (exeDir == null) { if (processArgs.ThrowOnError) { throw new FileNotFoundException($"Could not find command '{executable}' in the given search locations."); } return(null); } return(StartProcess(Path.Combine(exeDir.FullName, executable), arguments, processArgs.WorkingDirectory, outputReceived, errorReceived)); } catch (Exception e) { TinyEditorAnalytics.SendException("Shell.RunNoWait", e); throw; } }
public static ShellProcessOutput RunInShell(string command, ShellProcessArgs args) { Assert.IsFalse(string.IsNullOrEmpty(command)); Assert.IsNotNull(args); try { var extraPaths = args.ExtraPaths; var workingDirectory = args.WorkingDirectory; var throwOnError = args.ThrowOnError; var runOutput = new ShellProcessOutput(); var hasErrors = false; var output = new StringBuilder(); var logOutput = new StringBuilder(); var errorOutput = new StringBuilder(); // Setup shell command if (extraPaths != null) { var sb = new StringBuilder(128); foreach (var part in extraPaths) { if (string.IsNullOrEmpty(part)) { continue; } if (sb.Length > 0) { sb.Append(s_PathSeparator); } #if UNITY_EDITOR_WIN sb.Append(part.Trim('"')); #else sb.Append(part[0] == '"' ? part : part.DoubleQuoted()); #endif } #if UNITY_EDITOR_WIN command = $"SET PATH={sb}{s_PathSeparator}%PATH%{Environment.NewLine}{command}"; #else command = $"export PATH={sb}{s_PathSeparator}$PATH{Environment.NewLine}{command}"; #endif } LogProcessData($"TINY SHELL> {(workingDirectory?.FullName ?? new DirectoryInfo(".").FullName)}", logOutput); LogProcessData(command, logOutput); // Setup temporary command file var tmpCommandFile = Path.GetTempPath() + Guid.NewGuid().ToString(); #if UNITY_EDITOR_WIN tmpCommandFile += ".bat"; #else tmpCommandFile += ".sh"; #endif File.WriteAllText(tmpCommandFile, command); // Prepare data received handlers DataReceivedEventHandler outputReceived = (sender, e) => { LogProcessData(e.Data, output); logOutput.Append(e.Data); }; DataReceivedEventHandler errorReceived = (sender, e) => { LogProcessData(e.Data, output); errorOutput.Append(e.Data); logOutput.Append(e.Data); if (!string.IsNullOrEmpty(e.Data)) { hasErrors = true; } }; // Run command in shell and wait for exit try { #if UNITY_EDITOR_WIN using (var process = StartProcess("cmd.exe", $"/Q /C \"{tmpCommandFile}\"", workingDirectory, outputReceived, errorReceived)) #else using (var process = StartProcess("bash", $"\"{tmpCommandFile}\"", workingDirectory, outputReceived, errorReceived)) #endif { var exitCode = WaitForProcess(process, output, args.MaxIdleTimeInMilliseconds); runOutput.ExitCode = exitCode; runOutput.Command = command; runOutput.CommandOutput = output.ToString(); runOutput.FullOutput = logOutput.ToString(); runOutput.ErrorOutput = errorOutput.ToString(); LogProcessData($"Process exited with code '{exitCode}'", logOutput); hasErrors |= (exitCode != 0); } } finally { File.Delete(tmpCommandFile); } if (hasErrors && throwOnError) { throw new Exception($"{UTinyConstants.ApplicationName}: " + errorOutput.ToString()); } runOutput.Succeeded = !hasErrors; return(runOutput); } catch (Exception e) { TinyEditorAnalytics.SendException("Shell.RunInShell", e); throw; } }
public static UTinyBuildResults Build(UTinyBuildOptions options) { if (options?.Project == null || options.Destination == null) { throw new ArgumentException($"{UTinyConstants.ApplicationName}: invalid build options provided", nameof(options)); } var buildStart = DateTime.Now; var results = new UTinyBuildResults(); IUTinyBuilder builder = null; switch (options.Platform) { case UTinyPlatform.HTML5: builder = new UTinyHTML5Builder(); break; default: throw new ArgumentException($"{UTinyConstants.ApplicationName}: build platform not supported", nameof(options)); } try { EditorUtility.DisplayProgressBar(ProgressBarTitle, "Build started for " + options.Platform.ToString(), 0.0f); var destFolder = options.Destination; destFolder.Create(); // BUILD = <DEST>/PLATFORM/CONFIG var buildFolder = new DirectoryInfo(GetBuildDirectory(options.Project, options.Platform, options.Configuration)); results.OutputFolder = buildFolder; UTinyBuildUtilities.PurgeDirectory(buildFolder); buildFolder.Create(); options.Destination = results.BinaryFolder = buildFolder; var idlFile = new FileInfo(Path.Combine(buildFolder.FullName, "generated.cs")); UTinyIDLGenerator.GenerateIDL(options.Project, idlFile); var distFolder = GetRuntimeDistFolder(); var bindGem = new FileInfo(Path.Combine( distFolder.FullName, "bindgem/BindGem/bin/Release/BindGem.exe")); var exeName = "\"" + bindGem.FullName + "\""; // always call bindgem with mono for consistency exeName = "mono " + exeName; // reference the core runtime file var bindReferences = $"-r \"{RuntimeDefsAssemblyPath}\""; UTinyBuildUtilities.RunInShell( $"{exeName} -j {bindReferences} -o bind-generated {idlFile.Name}", new ShellProcessArgs() { WorkingDirectory = buildFolder, ExtraPaths = TinyPreferences.MonoDirectory.AsEnumerable() }); // @TODO Perform a full refresh before building builder.Build(options, results); results.BuildReport.Update(); Debug.Log($"{UTinyConstants.ApplicationName} project generated at: {results.BinaryFolder.FullName}"); TinyEditorAnalytics.SendBuildEvent(options.Project, results, DateTime.Now - buildStart); return(results); } catch (Exception ex) { TinyEditorAnalytics.SendException("BuildPipeline.Build", ex); throw; } finally { EditorUtility.ClearProgressBar(); UTinyEditorUtility.RepaintAllWindows(); } }