// Copyright Epic Games, Inc. All Rights Reserved. using System; using System.Collections.Generic; using System.IO; using AutomationTool; using UnrealBuildTool; using System.Threading; using System.Text.RegularExpressions; using System.Linq; using EpicGames.Core; namespace Gauntlet { /// /// Represents a loose collection of files. For Mac the executable will point to the binary.app bundle and /// not the inner executable file /// public class MacStagedBuildSource : StagedBuildSource { public override string BuildName { get { return "MacStagedBuildSource"; } } public override UnrealTargetPlatform Platform { get { return UnrealTargetPlatform.Mac; } } public override string PlatformFolderPrefix { get { return "Mac"; } } } /// /// Represents a packaged mac build. E.g. a Game.app that contains the executable and content /// public class MacPackagedBuild : PackagedBuild { public MacPackagedBuild(UnrealTargetPlatform InPlatform, UnrealTargetConfiguration InConfig, UnrealTargetRole InRole, string InBuildPath, BuildFlags InFlags) : base(InPlatform, InConfig, InRole, InBuildPath, InFlags) { } } /// /// Build source that discovers packaged builds for Mac. A packaged build is a bundle.app that contains both an executable and UE content /// public class MacPackagedBuildSource : IFolderBuildSource { public string BuildName { get { return "MacPackagedBuildSource"; } } public string PlatformFolderPrefix { get { return "Mac"; } } public bool CanSupportPlatform(UnrealTargetPlatform InPlatform) { return InPlatform == UnrealTargetPlatform.Mac; } public List GetBuildsAtPath(string InProjectName, string InPath, int MaxRecursion = 3) { List Builds = new List(); // c:\path\to\build DirectoryInfo RootDir = new DirectoryInfo(InPath); if (RootDir.Exists == false) { Log.Warning("No such path {0} to search for builds", InPath); return Builds; } List SearchDirs = new List(); // If this folder starts with the platform prefix the path is likely /path/builds/MacClient etc if (RootDir.Name.StartsWith(PlatformFolderPrefix)) { SearchDirs.Add(RootDir); } else { // assume this is something like /Path/Builds and add any /Path/Builds/MacClient, /Path/Builds/MacNoEditor etc SearchDirs = RootDir.GetDirectories().Where(D => D.Name.StartsWith(PlatformFolderPrefix)).ToList(); } // recurse and add subfolders. IEnumerable DirsToRecurse = new List(SearchDirs); List AllPackages = new List(); // get subdirs while (MaxRecursion-- > 0) { IEnumerable DiscoveredDirs = DirsToRecurse.SelectMany(D => D.GetDirectories("*", SearchOption.TopDirectoryOnly)); // mac packages are folders so we only want things that end with .app IEnumerable Packages = DiscoveredDirs.Where(D => Path.GetExtension(D.Name).Equals(".app", StringComparison.OrdinalIgnoreCase)); AllPackages.AddRange(Packages); // don't recurse into the dirs that end with .app since those are builds we'll look at DirsToRecurse = DiscoveredDirs.Except(Packages); } string ShortName = Regex.Replace(InProjectName, "Game", "", RegexOptions.IgnoreCase); // Now foreach (DirectoryInfo Di in AllPackages) { // Mac packages are directories such as GameName.app or GameClient-Mac-Test.app so we can use the Gauntlet helpers // to discover them. If config is unknown we don't recognize the format UnrealTargetConfiguration Config = UnrealHelpers.GetConfigurationFromExecutableName(InProjectName, Di.Name); UnrealTargetRole Role = UnrealHelpers.GetRoleFromExecutableName(InProjectName, Di.Name); if (Config != UnrealTargetConfiguration.Unknown) { string MacOSDir = Path.Combine(Di.FullName, "Contents", "MacOS"); // check both binary AND Engine content. Regular Unreal builds won't have the latter if (Directory.Exists(MacOSDir) && Directory.Exists(Path.Combine(Di.FullName, "Contents", "UE"))) { // Check there's an executable FileInfo Executable = new DirectoryInfo(MacOSDir).GetFiles().Where(Fi => Fi.Name.StartsWith(ShortName, StringComparison.OrdinalIgnoreCase)).FirstOrDefault(); if (Executable == null) { Log.Warning("Found packaged build at {0} with no valid executable"); } else { // We can use the base packaged build class. it has everything we need. MacPackagedBuild Build = new MacPackagedBuild( UnrealTargetPlatform.Mac, Config, Role, Di.FullName, BuildFlags.Packaged | BuildFlags.CanReplaceCommandLine | BuildFlags.CanReplaceExecutable); Builds.Add(Build); } } } } return Builds; } } }