void CompilePluginWithUBT(FileReference HostProjectFile, FileReference HostProjectPluginFile, PluginDescriptor Plugin, string TargetName, TargetType TargetType, UnrealTargetPlatform Platform, UnrealTargetConfiguration Configuration, List <FileReference> ManifestFileNames, string InAdditionalArgs) { // Find a list of modules that need to be built for this plugin bool bCompilePlatform = false; if (Plugin.Modules != null) { bool bBuildDeveloperTools = (TargetType == TargetType.Editor || TargetType == TargetType.Program || (Configuration != UnrealTargetConfiguration.Test && Configuration != UnrealTargetConfiguration.Shipping)); bool bBuildRequiresCookedData = (TargetType != TargetType.Editor && TargetType != TargetType.Program); foreach (ModuleDescriptor Module in Plugin.Modules) { if (Module.IsCompiledInConfiguration(Platform, Configuration, TargetName, TargetType, bBuildDeveloperTools, bBuildRequiresCookedData)) { bCompilePlatform = true; } } } // Add these modules to the build agenda if (bCompilePlatform) { if (Platform == UnrealTargetPlatform.HoloLens) { // Make sure to save the manifests for each architecture with unique names so they don't get overwritten. // This fixes packaging issues when building from binary engine releases, where the build produces a manifest for the plugin for ARM64, which // then gets overwritten by the manifest for x64. Then during packaging, the plugin is referencing a manifest for the wrong architecture. foreach (string Arch in HoloLensArchitecture.Split('+')) { FileReference ManifestFileName = FileReference.Combine(HostProjectFile.Directory, "Saved", String.Format("Manifest-{0}-{1}-{2}-{3}.xml", TargetName, Platform, Configuration, Arch)); ManifestFileNames.Add(ManifestFileName); string Arguments = String.Format("-plugin={0} -iwyu -noubtmakefiles -manifest={1} -nohotreload", CommandUtils.MakePathSafeToUseWithCommandLine(HostProjectPluginFile.FullName), CommandUtils.MakePathSafeToUseWithCommandLine(ManifestFileName.FullName)); Arguments += String.Format(" -Architecture={0}", Arch); if (!String.IsNullOrEmpty(InAdditionalArgs)) { Arguments += InAdditionalArgs; } CommandUtils.RunUBT(CmdEnv, UE4Build.GetUBTExecutable(), HostProjectFile, TargetName, Platform, Configuration, Arguments); } } else { FileReference ManifestFileName = FileReference.Combine(HostProjectFile.Directory, "Saved", String.Format("Manifest-{0}-{1}-{2}.xml", TargetName, Platform, Configuration)); ManifestFileNames.Add(ManifestFileName); string Arguments = String.Format("-plugin={0} -iwyu -noubtmakefiles -manifest={1} -nohotreload", CommandUtils.MakePathSafeToUseWithCommandLine(HostProjectPluginFile.FullName), CommandUtils.MakePathSafeToUseWithCommandLine(ManifestFileName.FullName)); if (Platform == UnrealTargetPlatform.Android) { Arguments += String.Format(" -architectures={0}", AndroidArchitectures); } if (!String.IsNullOrEmpty(InAdditionalArgs)) { Arguments += InAdditionalArgs; } CommandUtils.RunUBT(CmdEnv, UE4Build.GetUBTExecutable(), HostProjectFile, TargetName, Platform, Configuration, Arguments); } } }
void CompilePluginWithUBT(FileReference HostProjectFile, FileReference HostProjectPluginFile, PluginDescriptor Plugin, string TargetName, TargetType TargetType, UnrealTargetPlatform Platform, UnrealTargetConfiguration Configuration, List <FileReference> ManifestFileNames, string InAdditionalArgs) { // Find a list of modules that need to be built for this plugin bool bCompilePlatform = false; if (Plugin.Modules != null) { foreach (ModuleDescriptor Module in Plugin.Modules) { bool bBuildDeveloperTools = (TargetType == TargetType.Editor || TargetType == TargetType.Program); bool bBuildEditor = (TargetType == TargetType.Editor); bool bBuildRequiresCookedData = (TargetType != TargetType.Editor && TargetType != TargetType.Program); if (Module.IsCompiledInConfiguration(Platform, Configuration, TargetName, TargetType, bBuildDeveloperTools, bBuildEditor, bBuildRequiresCookedData)) { bCompilePlatform = true; } } } // Add these modules to the build agenda if (bCompilePlatform) { FileReference ManifestFileName = FileReference.Combine(HostProjectFile.Directory, "Saved", String.Format("Manifest-{0}-{1}-{2}.xml", TargetName, Platform, Configuration)); ManifestFileNames.Add(ManifestFileName); string Arguments = String.Format("-plugin={0} -iwyu -noubtmakefiles -manifest={1}", CommandUtils.MakePathSafeToUseWithCommandLine(HostProjectPluginFile.FullName), CommandUtils.MakePathSafeToUseWithCommandLine(ManifestFileName.FullName)); if (!String.IsNullOrEmpty(InAdditionalArgs)) { Arguments += InAdditionalArgs; } CommandUtils.RunUBT(CmdEnv, UE4Build.GetUBTExecutable(), String.Format("{0} {1} {2} {3}", TargetName, Platform, Configuration, Arguments)); } }
IEnumerable <string> EnumerateBuildFolders(string Target, string Configuration, string Platform, bool DebugRun) { FileReference OutputFile = FileReference.Combine(CommandUtils.EngineDirectory, "Intermediate", "Build", "ThirdParty.json"); IProcessResult Result = Run(UE4Build.GetUBTExecutable(), String.Format("{0} {1} {2} -jsonexport=\"{3}\" -skipbuild", Target, Configuration, Platform, OutputFile.FullName), Options: DebugRun ? ERunOptions.Default : ERunOptions.NoLoggingOfRunCommand); if (Result.ExitCode != 0) { throw new AutomationException("Failed to run UBT"); } JsonObject Object = JsonObject.Read(OutputFile); // local function that takes a RuntimeDependency path and resolves it (replacing Env vars that we support) Func <string, DirectoryReference> ResolveRuntimeDependencyFolder = (string DependencyPath) => { return(new DirectoryReference(Path.GetDirectoryName( // Regex to replace the env vars we support $(EngineDir|ProjectDir), ignoring case Regex.Replace(DependencyPath, @"\$\((?<Type>Engine|Project)Dir\)", M => M.Groups["Type"].Value.Equals("Engine", StringComparison.InvariantCultureIgnoreCase) ? CommandUtils.EngineDirectory.FullName : new FileReference(Object.GetStringField("ProjectFile")).Directory.FullName, RegexOptions.IgnoreCase)))); }; JsonObject Modules = Object.GetObjectField("Modules"); // Create a set of directories used for each binary List <DirectoryReference> DirectoriesToScan = Modules // get all directories that the module uses (source folder and any runtime dependencies) .KeyNames.Select(KeyName => Modules.GetObjectField(KeyName)) .SelectMany(Module => Module // resolve any runtime dependency folders and add them. .GetObjectArrayField("RuntimeDependencies").Select(Dependency => ResolveRuntimeDependencyFolder(Dependency.GetStringField("Path"))) // Add on the module source directory .Concat(new[] { new DirectoryReference(Module.GetStringField("Directory")) })) // remove any duplicate folders since some modules may be from the same plugin .Distinct() // Project to a list as we need to do an O(n^2) operation below. .ToList(); List <string> FinalDirs = DirectoriesToScan.Where(RemovalCandidate => // O(n^2) search to remove subfolders of any we are already searching. // look for directories that aren't subdirectories of any other directory in the list. !DirectoriesToScan.Any(DirectoryToScan => // != check because this inner loop will eventually check against itself RemovalCandidate != DirectoryToScan && RemovalCandidate.IsUnderDirectory(DirectoryToScan))) // grab the full name .Select(Dir => Dir.FullName) // sort the final output .OrderBy(Dir => Dir) // log the folders .ToList(); return(FinalDirs); }
void CompilePluginWithUBT(FileReference HostProjectFile, FileReference HostProjectPluginFile, PluginDescriptor Plugin, string TargetName, TargetType TargetType, UnrealTargetPlatform Platform, UnrealTargetConfiguration Configuration, List <FileReference> ReceiptFileNames, string InAdditionalArgs) { // Find a list of modules that need to be built for this plugin List <string> ModuleNames = new List <string>(); if (Plugin.Modules != null) { foreach (ModuleDescriptor Module in Plugin.Modules) { bool bBuildDeveloperTools = (TargetType == TargetType.Editor || TargetType == TargetType.Program); bool bBuildEditor = (TargetType == TargetType.Editor); bool bBuildRequiresCookedData = (TargetType != TargetType.Editor && TargetType != TargetType.Program); if (Module.IsCompiledInConfiguration(Platform, TargetType, bBuildDeveloperTools, bBuildEditor, bBuildRequiresCookedData)) { ModuleNames.Add(Module.Name); } } } // Add these modules to the build agenda if (ModuleNames.Count > 0) { string Arguments = "-iwyu"; // String.Format("-plugin={0}", CommandUtils.MakePathSafeToUseWithCommandLine(PluginFile.FullName)); foreach (string ModuleName in ModuleNames) { Arguments += String.Format(" -module={0}", ModuleName); } string Architecture = PlatformExports.GetDefaultArchitecture(Platform, HostProjectFile); FileReference ReceiptFileName = TargetReceipt.GetDefaultPath(HostProjectPluginFile.Directory, TargetName, Platform, Configuration, Architecture); Arguments += String.Format(" -receipt={0}", CommandUtils.MakePathSafeToUseWithCommandLine(ReceiptFileName.FullName)); ReceiptFileNames.Add(ReceiptFileName); if (!String.IsNullOrEmpty(InAdditionalArgs)) { Arguments += InAdditionalArgs; } CommandUtils.RunUBT(CmdEnv, UE4Build.GetUBTExecutable(), String.Format("{0} {1} {2}{3} {4}", TargetName, Platform, Configuration, (HostProjectFile == null)? "" : String.Format(" -project=\"{0}\"", HostProjectFile.FullName), Arguments)); } }
void CompilePluginWithUBT(FileReference HostProjectFile, FileReference HostProjectPluginFile, PluginDescriptor Plugin, string TargetName, TargetType TargetType, UnrealTargetPlatform Platform, UnrealTargetConfiguration Configuration, List <FileReference> ReceiptFileNames, string InAdditionalArgs) { // Find a list of modules that need to be built for this plugin bool bCompilePlatform = false; if (Plugin.Modules != null) { foreach (ModuleDescriptor Module in Plugin.Modules) { bool bBuildDeveloperTools = (TargetType == TargetType.Editor || TargetType == TargetType.Program); bool bBuildEditor = (TargetType == TargetType.Editor); bool bBuildRequiresCookedData = (TargetType != TargetType.Editor && TargetType != TargetType.Program); if (Module.IsCompiledInConfiguration(Platform, TargetType, bBuildDeveloperTools, bBuildEditor, bBuildRequiresCookedData)) { bCompilePlatform = true; } } } // Add these modules to the build agenda if (bCompilePlatform) { string Architecture = PlatformExports.GetDefaultArchitecture(Platform, HostProjectFile); FileReference ReceiptFileName = TargetReceipt.GetDefaultPath(HostProjectPluginFile.Directory, TargetName, Platform, Configuration, Architecture); ReceiptFileNames.Add(ReceiptFileName); string Arguments = String.Format("-plugin {0} -iwyu -precompile -nosharedpch -noubtmakefiles -receipt {1}", CommandUtils.MakePathSafeToUseWithCommandLine(HostProjectPluginFile.FullName), CommandUtils.MakePathSafeToUseWithCommandLine(ReceiptFileName.FullName)); if (!String.IsNullOrEmpty(InAdditionalArgs)) { Arguments += InAdditionalArgs; } CommandUtils.RunUBT(CmdEnv, UE4Build.GetUBTExecutable(), String.Format("{0} {1} {2} {3}", TargetName, Platform, Configuration, Arguments)); } }
public override void ExecuteBuild() { CommandUtils.Log("************************* List Third Party Software"); string ProjectPath = ParseParamValue("Project", String.Empty); //Add quotes to avoid issues with spaces in project path if (ProjectPath != String.Empty) { ProjectPath = "\"" + ProjectPath + "\""; } // Parse the list of targets to list TPS for. Each target is specified by -Target="Name|Configuration|Platform" on the command line. HashSet <FileReference> TpsFiles = new HashSet <FileReference>(); foreach (string Target in ParseParamValues(Params, "Target")) { // Get the path to store the exported JSON target data FileReference OutputFile = FileReference.Combine(CommandUtils.EngineDirectory, "Intermediate", "Build", "ThirdParty.json"); IProcessResult Result; Result = Run(UE4Build.GetUBTExecutable(), String.Format("{0} {1} -jsonexport=\"{2}\" -skipbuild", Target.Replace('|', ' '), ProjectPath, OutputFile.FullName), Options: ERunOptions.Default); if (Result.ExitCode != 0) { throw new AutomationException("Failed to run UBT"); } // Read the exported target info back in JsonObject Object = JsonObject.Read(OutputFile); // Get the project file if there is one FileReference ProjectFile = null; string ProjectFileName; if (Object.TryGetStringField("ProjectFile", out ProjectFileName)) { ProjectFile = new FileReference(ProjectFileName); } // Get the default paths to search HashSet <DirectoryReference> DirectoriesToScan = new HashSet <DirectoryReference>(); DirectoriesToScan.Add(DirectoryReference.Combine(CommandUtils.EngineDirectory, "Shaders")); DirectoriesToScan.Add(DirectoryReference.Combine(CommandUtils.EngineDirectory, "Content")); if (ProjectFile != null) { DirectoriesToScan.Add(DirectoryReference.Combine(ProjectFile.Directory, "Content")); } // Get the variables to be expanded in any runtime dependencies variables Dictionary <string, string> Variables = new Dictionary <string, string>(); Variables.Add("EngineDir", CommandUtils.EngineDirectory.FullName); if (ProjectFile != null) { Variables.Add("ProjectDir", ProjectFile.Directory.FullName); } // Add all the paths for each module, and its runtime dependencies JsonObject Modules = Object.GetObjectField("Modules"); foreach (string ModuleName in Modules.KeyNames) { JsonObject Module = Modules.GetObjectField(ModuleName); DirectoriesToScan.Add(new DirectoryReference(Module.GetStringField("Directory"))); foreach (JsonObject RuntimeDependency in Module.GetObjectArrayField("RuntimeDependencies")) { string RuntimeDependencyPath = RuntimeDependency.GetStringField("Path"); RuntimeDependencyPath = Utils.ExpandVariables(RuntimeDependencyPath, Variables); DirectoriesToScan.Add(new FileReference(RuntimeDependencyPath).Directory); } } // Remove any directories that are under other directories, and sort the output list List <DirectoryReference> SortedDirectoriesToScan = new List <DirectoryReference>(); foreach (DirectoryReference DirectoryToScan in DirectoriesToScan.OrderBy(x => x.FullName)) { if (SortedDirectoriesToScan.Count == 0 || !DirectoryToScan.IsUnderDirectory(SortedDirectoriesToScan[SortedDirectoriesToScan.Count - 1])) { SortedDirectoriesToScan.Add(DirectoryToScan); } } // Get the platforms to exclude List <UnrealTargetPlatform> SupportedPlatforms = new List <UnrealTargetPlatform> { (UnrealTargetPlatform)Enum.Parse(typeof(UnrealTargetPlatform), Object.GetStringField("Platform")) }; FileSystemName[] ExcludePlatformNames = Utils.MakeListOfUnsupportedPlatforms(SupportedPlatforms).Select(x => new FileSystemName(x)).ToArray(); // Find all the TPS files under the engine directory which match foreach (DirectoryReference DirectoryToScan in SortedDirectoriesToScan) { foreach (FileReference TpsFile in DirectoryReference.EnumerateFiles(DirectoryToScan, "*.tps", SearchOption.AllDirectories)) { if (!TpsFile.ContainsAnyNames(ExcludePlatformNames, DirectoryToScan)) { TpsFiles.Add(TpsFile); } } } } // Also add any redirects List <string> OutputMessages = new List <string>(); foreach (FileReference TpsFile in TpsFiles) { string Message = TpsFile.FullName; string[] Lines = FileReference.ReadAllLines(TpsFile); foreach (string Line in Lines) { const string RedirectPrefix = "Redirect:"; int Idx = Line.IndexOf(RedirectPrefix, StringComparison.InvariantCultureIgnoreCase); if (Idx >= 0) { FileReference RedirectTpsFile = FileReference.Combine(TpsFile.Directory, Line.Substring(Idx + RedirectPrefix.Length).Trim()); Message = String.Format("{0} (redirect from {1})", RedirectTpsFile.FullName, TpsFile.FullName); break; } } OutputMessages.Add(Message); } OutputMessages.Sort(); // Print them all out foreach (string OutputMessage in OutputMessages) { CommandUtils.Log(OutputMessage); } }
public override void ExecuteBuild() { CommandUtils.Log("************************* List Third Party Software"); bool DebugRun = ParseParam("Debug"); // first get a list of all TPS files available (as a lookup of Dir -> List of TPS files in Dir). var AllTPSFiles = Directory.EnumerateFiles(CombinePaths(CmdEnv.LocalRoot), "*.tps", SearchOption.AllDirectories) .ToLookup(TPSFile => Path.GetDirectoryName(TPSFile), StringComparer.InvariantCultureIgnoreCase); ParseParamValues(Params, "Target") // Grab all the Target params. .Select(TargetArg => TargetArg.Split(new[] { '|' }, 3)) // split the arg up by | .Where(Target => Target.Length == 3) // ensure it has three parts .Select(Target => new // strongly name the parts of the target and { Name = Target[0], Configuration = Target[1], Platform = Target[2], // create a list of unsupported platform strings for that target, which we'll use later to cull out irrelvant TPS files UnsupportedSubstrings = Utils.MakeListOfUnsupportedPlatforms(new List <UnrealTargetPlatform> { (UnrealTargetPlatform)Enum.Parse(typeof(UnrealTargetPlatform), Target[2]) }) .Select(PlatformName => Path.DirectorySeparatorChar + PlatformName + Path.DirectorySeparatorChar) // convert to /Platform/ .ToList(), // project to list }) .SelectMany(Target => // run UBT on each target to get the build folders, add a few hard-coded paths, then search for TPS files in relevant folders to them RunAndLog(UE4Build.GetUBTExecutable(), string.Format("{0} {1} {2} -listbuildfolders", Target.Name, Target.Configuration, Target.Platform), Options: DebugRun?ERunOptions.Default: ERunOptions.NoLoggingOfRunCommand) // run UBT to get the raw output .EnumerateLines() // split it into separate lines .Where(Line => Line.StartsWith("BuildFolder:", StringComparison.InvariantCultureIgnoreCase)) // find the output lines that we need .Select(Line => Line.Substring("BuildFolder:".Length)) // chop it down to the path name // tack on the target content directory, which we could infer from one of a few places .Concat(new[] { Path.Combine(Path.GetDirectoryName(Target.Name), "Content"), // The target could be a .uproject, so look for a content folder there Path.Combine(CmdEnv.LocalRoot, Target.Name, "Content"), // the target could be a root project, so look for a content folder there }.Where(Folder => Directory.Exists(Folder)) // only accept Content folders that actually exist. ) // tack on hard-coded engine shaders and content folder .Concat(new List <string> { "Shaders", "Content", }.Select(Folder => Path.Combine(CmdEnv.LocalRoot, "Engine", Folder))) // canonicalize the path and convert separators. We do string compares below, so we need separators to be in consistent formats. .Select(FolderToScan => CombinePaths(FolderToScan)) // scan each folder for TPS files that appear relevant to that folder .SelectMany(FolderToScan => AllTPSFiles // A relevant folder is one that is in a subfolders or parent folder to that folder .Where(TPSFileDir => FolderToScan.StartsWith(TPSFileDir.Key, StringComparison.InvariantCultureIgnoreCase) || TPSFileDir.Key.StartsWith(FolderToScan, StringComparison.InvariantCultureIgnoreCase)) // flatten the list of all the TPS files in any folders we found (remember we were just looking at folders above, which could have a list of TPS files) .SelectMany(TPSFileDir => TPSFileDir) // filter out TPS from unwanted platforms for the current target. // This is a bit hard to follow, but we are only looking for unsupported platform names INSIDE the folder to search. // for instance, if the folder is Foo/PS4/Plugins/PadSupport and we are building for windows, we don't want to filter it out even though it has PS4 in the name. // but if the TPS file is Foo/PS4/Plugins/PadSupport/Android/TPS.TPS, then we do want to filter out because of the Android folder. // this basically checks if an unsupported platform string is found AFTER the original folder we are looking in. .Where(TpsFile => Target.UnsupportedSubstrings.Max(PlatformDir => TpsFile.IndexOf(PlatformDir, StringComparison.InvariantCultureIgnoreCase)) < FolderToScan.Length) ) ) .Distinct() // remove duplicate TPS files. // pull out the redirect if present (but leave a breadcrumb to where the redirect came from) .Select(TPSFile => // read all the lines in the file File.ReadAllLines(TPSFile) // look for a line with a redirect .Where(Line => Line.IndexOf("Redirect:", StringComparison.InvariantCultureIgnoreCase) >= 0) // grab the redirect file and canonicalize it, tacking on some info on where the redirect was from. .Select(Line => CombinePaths(Path.GetFullPath(Path.Combine(Path.GetDirectoryName(TPSFile), Line.Split(new[] { ':' }, 2)[1].Trim()))) + " (redirect from " + TPSFile + ")") // take the first one found, or just use the TPS file directly if no redirect was present. .SingleOrDefault() ?? TPSFile) .OrderBy(TPSFile => TPSFile) // sort them. .ToList().ForEach(TPSFile => UnrealBuildTool.Log.WriteLine(0, string.Empty, LogEventType.Console, TPSFile)); // log them. }