Unity のコマンドラインビルドは、Windows 以外の環境では -logFile
を無引数で与えることでログが標準出力に出てきます。しかし、Windows の環境ではなぜか対応していません。そのため、ログを tail -f
して標準出力にリダイレクトするツールを作りました。
ログの上では失敗になっているのに、Exit Code が 0 になる場合への簡易的な対応も入れてあります。
Unity.exe <args>
と書くところを
UnityBuildLogRedirector.exe Unity.exe <args>
と書くだけです。
適当に C# のソリューションを作って以下のコードを突っ込んでビルドしてください。
これだと Jenkins から中断した場合にうまくプロセスが死なないので、親子関係を作って一緒に死ぬようにしてあげる必要があります。以下のページが参考になります。
UnityBuildLogRedirector.csusing System;using System.Diagnostics;using System.IO;using System.Linq;using System.Threading;namespace UnityBuildLogRedirector{class Program{const int MaxLogFileDetectionTrial = 1000;const int LogFileDetectionIntervalMs = 100;const int LogReadingIntervalMs = 100;static void Main(string[] args){if (args.Any(a => a.ToLower() == "-logfile")){throw new InvalidOperationException("-logFile オプションは使用しないでください");}if (args.All(a => a.ToLower() != "-quit")){throw new InvalidOperationException("-quit オプションが必要です");}var unityExecutable = new FileInfo(args.First());var logFile = new FileInfo(Path.GetTempFileName());var unityArguments = args.Skip(1).ToList();unityArguments.Add("-logFile");unityArguments.Add("\"" + logFile.FullName + "\"");var unityProcessInfo = new ProcessStartInfo(){FileName = unityExecutable.FullName,Arguments = string.Join(" ", unityArguments),CreateNoWindow = true,UseShellExecute = false,};var unityProcess = Process.Start(unityProcessInfo);try{var logFileDetectionTrialCount = 0;while (!logFile.Exists || logFile.Length == 0){logFileDetectionTrialCount++;if (logFileDetectionTrialCount > MaxLogFileDetectionTrial){throw new Exception("ログファイルへの書き込みが検出できませんでした");}Thread.Sleep(LogFileDetectionIntervalMs);logFile.Refresh();}var failureDetectedByLog = false;using (var fs = new FileStream(logFile.FullName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))using (var reader = new StreamReader(fs)){while (!unityProcess.HasExited){ReadAllAndRedirectAndHandleError(reader, ref failureDetectedByLog);Thread.Sleep(LogReadingIntervalMs);}ReadAllAndRedirectAndHandleError(reader, ref failureDetectedByLog);}if (failureDetectedByLog){Environment.ExitCode = 1;}else{Environment.ExitCode = unityProcess.ExitCode;}}finally{if (!unityProcess.HasExited){Console.WriteLine("Unity のプロセスが正しく終了しませんでした");Environment.ExitCode = 1;unityProcess.Kill();}unityProcess.Dispose();}}static void ReadAllAndRedirectAndHandleError(StreamReader reader, ref bool failure){var output = reader.ReadToEnd();if (output.Contains("Aborting batchmode due to failure")){failure = true;}Console.Write(output);}}}
Jenkins で Windows 環境の Unity のビルドのログがリアルタイムに出てきてくれなくて困っていた方は是非参考にしてください!