private VCEnvironment(CPPTargetPlatform InPlatform, bool bSupportWindowsXP) { Platform = InPlatform; // Get the Visual Studio install directory WindowsPlatform.TryGetVSInstallDir(WindowsPlatform.Compiler, out VSInstallDir); // Get the Visual C++ compiler install directory. if(!WindowsPlatform.TryGetVCInstallDir(WindowsPlatform.Compiler, out VCInstallDir)) { throw new BuildException(WindowsPlatform.GetCompilerName(WindowsPlatform.Compiler) + " must be installed in order to build this target."); } WindowsSDKDir = FindWindowsSDKInstallationFolder(Platform, bSupportWindowsXP); WindowsSDKLibVersion = FindWindowsSDKLibVersion(WindowsSDKDir); WindowsSDKExtensionDir = FindWindowsSDKExtensionInstallationFolder(); NetFxSDKExtensionDir = FindNetFxSDKExtensionInstallationFolder(); WindowsSDKExtensionHeaderLibVersion = FindWindowsSDKExtensionLatestVersion(WindowsSDKExtensionDir); UniversalCRTDir = bSupportWindowsXP ? "" : FindUniversalCRTInstallationFolder(); UniversalCRTVersion = bSupportWindowsXP ? "0.0.0.0" : FindUniversalCRTVersion(UniversalCRTDir); VCToolPath32 = GetVCToolPath32(VCInstallDir); VCToolPath64 = GetVCToolPath64(VCInstallDir); // Compile using 64 bit tools for 64 bit targets, and 32 for 32. DirectoryReference CompilerDir = (Platform == CPPTargetPlatform.Win64) ? VCToolPath64 : VCToolPath32; // Regardless of the target, if we're linking on a 64 bit machine, we want to use the 64 bit linker (it's faster than the 32 bit linker and can handle large linking jobs) DirectoryReference LinkerDir = VCToolPath64; CompilerPath = GetCompilerToolPath(InPlatform, CompilerDir); CLExeVersion = FindCLExeVersion(CompilerPath.FullName); LinkerPath = GetLinkerToolPath(InPlatform, LinkerDir); LibraryManagerPath = GetLibraryLinkerToolPath(InPlatform, LinkerDir); ResourceCompilerPath = new FileReference(GetResourceCompilerToolPath(Platform, bSupportWindowsXP)); // Make sure the base 32-bit VS tool path is in the PATH, regardless of which configuration we're using. The toolchain may need to reference support DLLs from this directory (eg. mspdb120.dll). string PathEnvironmentVariable = Environment.GetEnvironmentVariable("PATH") ?? ""; if (!PathEnvironmentVariable.Split(';').Any(x => String.Compare(x, VCToolPath32.FullName, true) == 0)) { PathEnvironmentVariable = VCToolPath32.FullName + ";" + PathEnvironmentVariable; Environment.SetEnvironmentVariable("PATH", PathEnvironmentVariable); } // Setup the INCLUDE environment variable List<string> IncludePaths = GetVisualCppIncludePaths(VCInstallDir.FullName, UniversalCRTDir, UniversalCRTVersion, NetFxSDKExtensionDir, WindowsSDKDir, WindowsSDKLibVersion, bSupportWindowsXP); if(InitialIncludePaths != null) { IncludePaths.Add(InitialIncludePaths); } Environment.SetEnvironmentVariable("INCLUDE", String.Join(";", IncludePaths)); // Setup the LIB environment variable List<string> LibraryPaths = GetVisualCppLibraryPaths(VCInstallDir.FullName, UniversalCRTDir, UniversalCRTVersion, NetFxSDKExtensionDir, WindowsSDKDir, WindowsSDKLibVersion, Platform, bSupportWindowsXP); if(InitialLibraryPaths != null) { LibraryPaths.Add(InitialLibraryPaths); } Environment.SetEnvironmentVariable("LIB", String.Join(";", LibraryPaths)); }
public static bool FindTargetFilesInFolder(DirectoryReference InTargetFolder) { bool bFoundTargetFiles = false; IEnumerable<string> Files; if (!Utils.IsRunningOnMono) { Files = Directory.EnumerateFiles(InTargetFolder.FullName, "*.target.cs", SearchOption.TopDirectoryOnly); } else { Files = Directory.GetFiles(InTargetFolder.FullName, "*.Target.cs", SearchOption.TopDirectoryOnly).AsEnumerable(); } foreach (string TargetFilename in Files) { bFoundTargetFiles = true; foreach (KeyValuePair<FileReference, UProjectInfo> Entry in ProjectInfoDictionary) { FileInfo ProjectFileInfo = new FileInfo(Entry.Key.FullName); string ProjectDir = ProjectFileInfo.DirectoryName.TrimEnd(Path.DirectorySeparatorChar) + Path.DirectorySeparatorChar; if (TargetFilename.StartsWith(ProjectDir, StringComparison.InvariantCultureIgnoreCase)) { FileInfo TargetInfo = new FileInfo(TargetFilename); // Strip off the target.cs string TargetName = Utils.GetFilenameWithoutAnyExtensions(TargetInfo.Name); if (TargetToProjectDictionary.ContainsKey(TargetName) == false) { TargetToProjectDictionary.Add(TargetName, Entry.Key); } } } } return bFoundTargetFiles; }
/// <summary> /// Fills in a project file with source files discovered in the specified list of paths /// </summary> /// <param name="SourceFilePaths">List of paths to look for source files</param> /// <param name="SubdirectoryNamesToExclude">Directory base names to ignore when searching subdirectories. Can be null.</param> /// <param name="SearchSubdirectories">True to include subdirectories, otherwise we only search the list of base directories</param> /// <param name="IncludePrivateSourceCode">True if source files in the 'Private' directory should be included</param> public static List<FileReference> FindFiles(DirectoryReference DirectoryToSearch, List<string> SubdirectoryNamesToExclude = null, bool SearchSubdirectories = true) { // Build a list of directory names that we don't want to search under. We always ignore intermediate directories. string[] ExcludedDirectorySuffixes; if (SubdirectoryNamesToExclude == null) { ExcludedDirectorySuffixes = DefaultExcludedDirectorySuffixes; } else { ExcludedDirectorySuffixes = SubdirectoryNamesToExclude.Select(x => Path.DirectorySeparatorChar + x.ToLowerInvariant()).Union(DefaultExcludedDirectorySuffixes).ToArray(); } // Find all the files List<FileReference> FoundFiles = new List<FileReference>(); if (SearchSubdirectories) { FindFilesInternalRecursive(DirectoryToSearch, ExcludedDirectorySuffixes, FoundFiles); } else { FindFilesInternal(DirectoryToSearch, ExcludedDirectorySuffixes, FoundFiles); } return FoundFiles; }
public static bool FindTargetFiles(DirectoryReference CurrentTopDirectory, ref bool bOutFoundTargetFiles) { // We will only search as deep as the first target file found List<DirectoryReference> SubFolderList = new List<DirectoryReference>(); // Check the root directory bOutFoundTargetFiles |= FindTargetFilesInFolder(CurrentTopDirectory); if (bOutFoundTargetFiles == false) { foreach (DirectoryReference TargetFolder in Directory.EnumerateDirectories(CurrentTopDirectory.FullName, "*", SearchOption.TopDirectoryOnly).Select(x => new DirectoryReference(x))) { SubFolderList.Add(TargetFolder); bOutFoundTargetFiles |= FindTargetFilesInFolder(TargetFolder); } } if (bOutFoundTargetFiles == false) { // Recurse each folders folders foreach (DirectoryReference SubFolder in SubFolderList) { FindTargetFiles(SubFolder, ref bOutFoundTargetFiles); } } return bOutFoundTargetFiles; }
UProjectInfo(FileReference InFilePath, bool bInIsCodeProject) { GameName = InFilePath.GetFileNameWithoutExtension(); FileName = InFilePath.GetFileName(); FilePath = InFilePath; Folder = FilePath.Directory; bIsCodeProject = bInIsCodeProject; }
/// <summary> /// Constructs a PluginInfo object /// </summary> /// <param name="InFile"></param> /// <param name="InLoadedFrom">Where this pl</param> public PluginInfo(FileReference InFile, PluginLoadedFrom InLoadedFrom) { Name = Path.GetFileNameWithoutExtension(InFile.FullName); File = InFile; Directory = File.Directory; Descriptor = PluginDescriptor.FromFile(File, InLoadedFrom == PluginLoadedFrom.GameProject); LoadedFrom = InLoadedFrom; }
static void FindFilesInternal(DirectoryReference Directory, string[] ExcludedDirectorySuffixes, List<FileReference> FoundFiles) { foreach (FileReference File in Directory.EnumerateFileReferences()) { if (ShouldInclude(File, DefaultExcludedFileSuffixes)) { FoundFiles.Add(File); } } }
static DirectoryCache FindOrCreateDirectoryCache(DirectoryReference Directory) { DirectoryCache FoundDirectoryCache; if (!Directories.TryGetValue(Directory, out FoundDirectoryCache)) { FoundDirectoryCache = new DirectoryCache(Directory); Directories.Add(Directory, FoundDirectoryCache); } return FoundDirectoryCache; }
public DirectoryCache(DirectoryReference InDirectory) { Directory = InDirectory; Exists = Directory.Exists(); if (!Exists) { Files = new HashSet<FileReference>(); Directories = new HashSet<DirectoryReference>(); } }
/// <summary> /// </summary> public override void CleanProjectFiles(DirectoryReference InMasterProjectDirectory, string InMasterProjectName, DirectoryReference InIntermediateProjectFilesDirectory) { FileReference MasterProjectFile = FileReference.Combine(InMasterProjectDirectory, InMasterProjectName); FileReference MasterProjDeleteFilename = MasterProjectFile + ".sln"; if (MasterProjDeleteFilename.Exists()) { MasterProjDeleteFilename.Delete(); } MasterProjDeleteFilename = MasterProjectFile + ".sdf"; if (MasterProjDeleteFilename.Exists()) { MasterProjDeleteFilename.Delete(); } MasterProjDeleteFilename = MasterProjectFile + ".suo"; if (MasterProjDeleteFilename.Exists()) { MasterProjDeleteFilename.Delete(); } MasterProjDeleteFilename = MasterProjectFile + ".v11.suo"; if (MasterProjDeleteFilename.Exists()) { MasterProjDeleteFilename.Delete(); } MasterProjDeleteFilename = MasterProjectFile + ".v12.suo"; if (MasterProjDeleteFilename.Exists()) { MasterProjDeleteFilename.Delete(); } // Delete the project files folder if (InIntermediateProjectFilesDirectory.Exists()) { try { Directory.Delete(InIntermediateProjectFilesDirectory.FullName, true); } catch (Exception Ex) { Log.TraceInformation("Error while trying to clean project files path {0}. Ignored.", InIntermediateProjectFilesDirectory); Log.TraceInformation("\t" + Ex.Message); } } }
/// <summary> /// </summary> public override void CleanProjectFiles(DirectoryReference InMasterProjectDirectory, string InMasterProjectName, DirectoryReference InIntermediateProjectFilesPath) { DirectoryReference MasterProjDeleteFilename = DirectoryReference.Combine(InMasterProjectDirectory, InMasterProjectName + ".xcworkspace"); if (MasterProjDeleteFilename.Exists()) { Directory.Delete(MasterProjDeleteFilename.FullName, true); } // Delete the project files folder if (InIntermediateProjectFilesPath.Exists()) { try { Directory.Delete(InIntermediateProjectFilesPath.FullName, true); } catch (Exception Ex) { Log.TraceInformation("Error while trying to clean project files path {0}. Ignored.", InIntermediateProjectFilesPath); Log.TraceInformation("\t" + Ex.Message); } } }
public override void GetFilesToDeployOrStage(ProjectParams Params, DeploymentContext SC) { // Engine non-ufs (binaries) if (SC.bStageCrashReporter) { FileReference ReceiptFileName = TargetReceipt.GetDefaultPath(CommandUtils.EngineDirectory, "CrashReportClient", SC.StageTargetPlatform.PlatformType, UnrealTargetConfiguration.Shipping, null); if (FileReference.Exists(ReceiptFileName)) { DirectoryReference EngineDir = CommandUtils.EngineDirectory; DirectoryReference ProjectDir = DirectoryReference.FromFile(Params.RawProjectPath); TargetReceipt Receipt = TargetReceipt.Read(ReceiptFileName, EngineDir, ProjectDir); SC.StageBuildProductsFromReceipt(Receipt, true, false); } } // Stage all the build products foreach (StageTarget Target in SC.StageTargets) { SC.StageBuildProductsFromReceipt(Target.Receipt, Target.RequireFilesExist, Params.bTreatNonShippingBinariesAsDebugFiles); } // Copy the splash screen, windows specific FileReference SplashImage = FileReference.Combine(SC.ProjectRoot, "Content", "Splash", "Splash.bmp"); if (FileReference.Exists(SplashImage)) { SC.StageFile(StagedFileType.NonUFS, SplashImage); } // Stage the bootstrap executable if (!Params.NoBootstrapExe) { foreach (StageTarget Target in SC.StageTargets) { BuildProduct Executable = Target.Receipt.BuildProducts.FirstOrDefault(x => x.Type == BuildProductType.Executable); if (Executable != null) { // only create bootstraps for executables List <StagedFileReference> StagedFiles = SC.FilesToStage.NonUFSFiles.Where(x => x.Value == Executable.Path).Select(x => x.Key).ToList(); if (StagedFiles.Count > 0 && Executable.Path.HasExtension(".exe")) { string BootstrapArguments = ""; if (!ShouldStageCommandLine(Params, SC)) { if (!SC.IsCodeBasedProject) { BootstrapArguments = String.Format("..\\..\\..\\{0}\\{0}.uproject", SC.ShortProjectName); } else { BootstrapArguments = SC.ShortProjectName; } } string BootstrapExeName; if (SC.StageTargetConfigurations.Count > 1) { BootstrapExeName = Executable.Path.GetFileName(); } else if (Params.IsCodeBasedProject) { BootstrapExeName = Target.Receipt.TargetName + ".exe"; } else { BootstrapExeName = SC.ShortProjectName + ".exe"; } foreach (StagedFileReference StagePath in StagedFiles) { StageBootstrapExecutable(SC, BootstrapExeName, Executable.Path, StagePath, BootstrapArguments); } } } } } }
/// <summary> /// Allocates a generator-specific source file object /// </summary> /// <param name="InitFilePath">Path to the source file on disk</param> /// <param name="InitProjectSubFolder">Optional sub-folder to put the file in. If empty, this will be determined automatically from the file's path relative to the project file</param> /// <returns>The newly allocated source file object</returns> public override SourceFile AllocSourceFile(FileReference InitFilePath, DirectoryReference InitProjectSubFolder) { if (InitFilePath.GetFileName().StartsWith(".")) { return null; } return new XcodeSourceFile(InitFilePath, InitProjectSubFolder); }
private void RunCsvTool(string ToolName, string Arguments) { var ToolPath = FileReference.Combine(DirectoryReference.Combine(RootDir, "Engine", "Programs", "NotForLicensees", "CSVTools", "Binaries"), ToolName + ".exe"); Run(ToolPath.FullName, Arguments); }
/// <summary> /// Build a node /// </summary> /// <param name="Job">Information about the current job</param> /// <param name="Graph">The graph to which the node belongs. Used to determine which outputs need to be transferred to temp storage.</param> /// <param name="Node">The node to build</param> /// <param name="Storage">The temp storage backend which stores the shared state</param> /// <param name="bWithBanner">Whether to write a banner before and after this node's log output</param> /// <returns>True if the node built successfully, false otherwise.</returns> bool BuildNode(JobContext Job, Graph Graph, Node Node, TempStorage Storage, bool bWithBanner) { DirectoryReference RootDir = new DirectoryReference(CommandUtils.CmdEnv.LocalRoot); // Create the mapping of tag names to file sets Dictionary <string, HashSet <FileReference> > TagNameToFileSet = new Dictionary <string, HashSet <FileReference> >(); // Read all the input tags for this node, and build a list of referenced input storage blocks HashSet <TempStorageBlock> InputStorageBlocks = new HashSet <TempStorageBlock>(); foreach (NodeOutput Input in Node.Inputs) { TempStorageFileList FileList = Storage.ReadFileList(Input.ProducingNode.Name, Input.TagName); TagNameToFileSet[Input.TagName] = FileList.ToFileSet(RootDir); InputStorageBlocks.UnionWith(FileList.Blocks); } // Read the manifests for all the input storage blocks Dictionary <TempStorageBlock, TempStorageManifest> InputManifests = new Dictionary <TempStorageBlock, TempStorageManifest>(); foreach (TempStorageBlock InputStorageBlock in InputStorageBlocks) { TempStorageManifest Manifest = Storage.Retreive(InputStorageBlock.NodeName, InputStorageBlock.OutputName); InputManifests[InputStorageBlock] = Manifest; } // Read all the input storage blocks, keeping track of which block each file came from Dictionary <FileReference, TempStorageBlock> FileToStorageBlock = new Dictionary <FileReference, TempStorageBlock>(); foreach (KeyValuePair <TempStorageBlock, TempStorageManifest> Pair in InputManifests) { TempStorageBlock InputStorageBlock = Pair.Key; foreach (FileReference File in Pair.Value.Files.Select(x => x.ToFileReference(RootDir))) { TempStorageBlock CurrentStorageBlock; if (FileToStorageBlock.TryGetValue(File, out CurrentStorageBlock)) { LogError("File '{0}' was produced by {1} and {2}", File, InputStorageBlock, CurrentStorageBlock); } FileToStorageBlock[File] = InputStorageBlock; } } // Add placeholder outputs for the current node foreach (NodeOutput Output in Node.Outputs) { TagNameToFileSet.Add(Output.TagName, new HashSet <FileReference>()); } // Execute the node if (bWithBanner) { Console.WriteLine(); CommandUtils.LogInformation("========== Starting: {0} ==========", Node.Name); } if (!Node.Build(Job, TagNameToFileSet)) { return(false); } if (bWithBanner) { CommandUtils.LogInformation("========== Finished: {0} ==========", Node.Name); Console.WriteLine(); } // Check that none of the inputs have been clobbered Dictionary <string, string> ModifiedFiles = new Dictionary <string, string>(StringComparer.InvariantCultureIgnoreCase); foreach (TempStorageFile File in InputManifests.Values.SelectMany(x => x.Files)) { string Message; if (!ModifiedFiles.ContainsKey(File.RelativePath) && !File.Compare(CommandUtils.RootDirectory, out Message)) { ModifiedFiles.Add(File.RelativePath, Message); } } if (ModifiedFiles.Count > 0) { throw new AutomationException("Build {0} from a previous step have been modified:\n{1}", (ModifiedFiles.Count == 1)? "product" : "products", String.Join("\n", ModifiedFiles.Select(x => x.Value))); } // Determine all the output files which are required to be copied to temp storage (because they're referenced by nodes in another agent) HashSet <FileReference> ReferencedOutputFiles = new HashSet <FileReference>(); foreach (Agent Agent in Graph.Agents) { bool bSameAgent = Agent.Nodes.Contains(Node); foreach (Node OtherNode in Agent.Nodes) { if (!bSameAgent || Node.ControllingTrigger != OtherNode.ControllingTrigger) { foreach (NodeOutput Input in OtherNode.Inputs.Where(x => x.ProducingNode == Node)) { ReferencedOutputFiles.UnionWith(TagNameToFileSet[Input.TagName]); } } } } // Find a block name for all new outputs Dictionary <FileReference, string> FileToOutputName = new Dictionary <FileReference, string>(); foreach (NodeOutput Output in Node.Outputs) { HashSet <FileReference> Files = TagNameToFileSet[Output.TagName]; foreach (FileReference File in Files) { if (!FileToStorageBlock.ContainsKey(File) && File.IsUnderDirectory(RootDir)) { if (Output == Node.DefaultOutput) { if (!FileToOutputName.ContainsKey(File)) { FileToOutputName[File] = ""; } } else { string OutputName; if (FileToOutputName.TryGetValue(File, out OutputName) && OutputName.Length > 0) { FileToOutputName[File] = String.Format("{0}+{1}", OutputName, Output.TagName.Substring(1)); } else { FileToOutputName[File] = Output.TagName.Substring(1); } } } } } // Invert the dictionary to make a mapping of storage block to the files each contains Dictionary <string, HashSet <FileReference> > OutputStorageBlockToFiles = new Dictionary <string, HashSet <FileReference> >(); foreach (KeyValuePair <FileReference, string> Pair in FileToOutputName) { HashSet <FileReference> Files; if (!OutputStorageBlockToFiles.TryGetValue(Pair.Value, out Files)) { Files = new HashSet <FileReference>(); OutputStorageBlockToFiles.Add(Pair.Value, Files); } Files.Add(Pair.Key); } // Write all the storage blocks, and update the mapping from file to storage block foreach (KeyValuePair <string, HashSet <FileReference> > Pair in OutputStorageBlockToFiles) { TempStorageBlock OutputBlock = new TempStorageBlock(Node.Name, Pair.Key); foreach (FileReference File in Pair.Value) { FileToStorageBlock.Add(File, OutputBlock); } Storage.Archive(Node.Name, Pair.Key, Pair.Value.ToArray(), Pair.Value.Any(x => ReferencedOutputFiles.Contains(x))); } // Publish all the output tags foreach (NodeOutput Output in Node.Outputs) { HashSet <FileReference> Files = TagNameToFileSet[Output.TagName]; HashSet <TempStorageBlock> StorageBlocks = new HashSet <TempStorageBlock>(); foreach (FileReference File in Files) { TempStorageBlock StorageBlock; if (FileToStorageBlock.TryGetValue(File, out StorageBlock)) { StorageBlocks.Add(StorageBlock); } } Storage.WriteFileList(Node.Name, Output.TagName, Files, StorageBlocks.ToArray()); } // Mark the node as succeeded Storage.MarkAsComplete(Node.Name); return(true); }
/// <summary> /// Allow various platform project generators to generate any special project properties if required /// </summary> /// <param name="InPlatform"></param> /// <returns></returns> public static bool GenerateGamePlatformSpecificProperties(UnrealTargetPlatform InPlatform, UnrealTargetConfiguration Configuration, TargetRules.TargetType TargetType, StringBuilder VCProjectFileContent, DirectoryReference RootDirectory, FileReference TargetFilePath) { if (ProjectGeneratorDictionary.ContainsKey(InPlatform) == true) { ProjectGeneratorDictionary[InPlatform].GenerateGameProperties(Configuration, VCProjectFileContent, TargetType, RootDirectory, TargetFilePath); ; } return true; }
public override bool HasDefaultBuildConfig(UnrealTargetPlatform Platform, DirectoryReference ProjectPath) { string[] BoolKeys = new string[] { "bBuildForArmV7", "bBuildForArm64", "bBuildForX86", "bBuildForX8664", "bBuildForES2", "bBuildForESDeferred", "bSupportsVulkan", "bBuildForES3" }; // look up Android specific settings if (!DoProjectSettingsMatchDefault(Platform, ProjectPath, "/Script/AndroidRuntimeSettings.AndroidRuntimeSettings", BoolKeys, null, null)) { return false; } // check the base settings return base.HasDefaultBuildConfig(Platform, ProjectPath); }
/// <summary> /// Finds a list of files within a given directory which match the filter. /// </summary> /// <param name="DirectoryName">File to match</param> /// <returns>List of files that pass the filter</returns> public List<FileReference> ApplyToDirectory(DirectoryReference DirectoryName, bool bIgnoreSymlinks) { List<FileReference> MatchingFileNames = new List<FileReference>(); FindMatchesFromDirectory(new DirectoryInfo(DirectoryName.FullName), "", bIgnoreSymlinks, MatchingFileNames); return MatchingFileNames; }
public void StageAppLocalDependencies(ProjectParams Params, DeploymentContext SC, string PlatformDir) { Dictionary <string, string> PathVariables = new Dictionary <string, string>(); PathVariables["EngineDir"] = SC.EngineRoot.FullName; PathVariables["ProjectDir"] = SC.ProjectRoot.FullName; // support multiple comma-separated paths string[] AppLocalDirectories = Params.AppLocalDirectory.Split(';'); foreach (string AppLocalDirectory in AppLocalDirectories) { string ExpandedAppLocalDir = Utils.ExpandVariables(AppLocalDirectory, PathVariables); DirectoryReference BaseAppLocalDependenciesPath = Path.IsPathRooted(ExpandedAppLocalDir) ? new DirectoryReference(CombinePaths(ExpandedAppLocalDir, PlatformDir)) : DirectoryReference.Combine(SC.ProjectRoot, ExpandedAppLocalDir, PlatformDir); if (DirectoryReference.Exists(BaseAppLocalDependenciesPath)) { StageAppLocalDependenciesToDir(SC, BaseAppLocalDependenciesPath, StagedDirectoryReference.Combine("Engine", "Binaries", PlatformDir)); StageAppLocalDependenciesToDir(SC, BaseAppLocalDependenciesPath, StagedDirectoryReference.Combine(SC.RelativeProjectRootForStage, "Binaries", PlatformDir)); } else { LogWarning("Unable to deploy AppLocalDirectory dependencies. No such path: {0}", BaseAppLocalDependenciesPath); } } }
/// <summary> /// Resolve a list of files, tag names or file specifications separated by semicolons. Supported entries may be: /// a) The name of a tag set (eg. #CompiledBinaries) /// b) Relative or absolute filenames /// c) A simple file pattern (eg. Foo/*.cpp) /// d) A full directory wildcard (eg. Engine/...) /// Note that wildcards may only match the last fragment in a pattern, so matches like "/*/Foo.txt" and "/.../Bar.txt" are illegal. /// </summary> /// <param name="DefaultDirectory">The default directory to resolve relative paths to</param> /// <param name="DelimitedPatterns">List of files, tag names, or file specifications to include separated by semicolons.</param> /// <param name="TagNameToFileSet">Mapping of tag name to fileset, as passed to the Execute() method</param> /// <returns>Set of matching files.</returns> public static HashSet <FileReference> ResolveFilespec(DirectoryReference DefaultDirectory, string DelimitedPatterns, Dictionary <string, HashSet <FileReference> > TagNameToFileSet) { List <string> ExcludePatterns = new List <string>(); return(ResolveFilespecWithExcludePatterns(DefaultDirectory, DelimitedPatterns, ExcludePatterns, TagNameToFileSet)); }
/** * Notify stakeholders of the commandlet results */ void SendCompletionMessage(bool bWasSuccessful, String MessageBody) { if (StakeholdersEmailAddresses != null) { MailMessage Message = new System.Net.Mail.MailMessage(); Message.Priority = MailPriority.High; Message.From = new MailAddress("*****@*****.**"); string Branch = "Unknown"; if (P4Enabled) { Branch = P4Env.Branch; } foreach (String NextStakeHolder in StakeholdersEmailAddresses) { Message.To.Add(new MailAddress(NextStakeHolder)); } ConfigHierarchy Ini = ConfigCache.ReadHierarchy(ConfigHierarchyType.EditorPerProjectUserSettings, DirectoryReference.FromFile(ProjectFullPath), UnrealTargetPlatform.Win64); List <string> Emails; Ini.GetArray("RebuildHLODSettings", "EmailNotification", out Emails); foreach (var Email in Emails) { Message.CC.Add(new MailAddress(Email)); } Message.Subject = String.Format("Nightly HLOD rebuild {0} for {1}", bWasSuccessful ? "[SUCCESS]" : "[FAILED]", Branch); Message.Body = MessageBody; /*Attachment Attach = new Attachment(); * Message.Attachments.Add()*/ try { #pragma warning disable CS0618 // Mono 4.6.x obsoletes this class SmtpClient MailClient = new SmtpClient("smtp.epicgames.net"); MailClient.Send(Message); #pragma warning restore CS0618 } catch (Exception Ex) { LogError("Failed to send notify email to {0} ({1})", String.Join(", ", StakeholdersEmailAddresses.ToArray()), Ex.Message); } } }
public TobiiGTOM(ReadOnlyTargetRules Target) : base(Target) { PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs; PrivateDependencyModuleNames.AddRange(new string[] { "Core" , "CoreUObject" , "Engine" , "Slate" , "SlateCore" , "UMG" , "HeadMountedDisplay" }); PublicDependencyModuleNames.AddRange(new string[] { "TobiiCore" }); PrivateIncludePaths.AddRange(new string[] { "TobiiGTOM/Public" , "TobiiGTOM/Public/GTOMAwareUI" }); string AssemblyLocation = Path.GetDirectoryName(new Uri(System.Reflection.Assembly.GetExecutingAssembly().CodeBase).LocalPath); DirectoryReference RootDirectory = new DirectoryReference(Path.Combine(AssemblyLocation, "..", "..", "..")); bool IsEnginePlugin = RootDirectory.GetDirectoryName() == "Engine"; PublicDefinitions.Add("TOBII_COMPILE_AS_ENGINE_PLUGIN=" + (IsEnginePlugin ? 1 : 0)); //Platform specific if (Target.Platform == UnrealTargetPlatform.Win64 || Target.Platform == UnrealTargetPlatform.Win32) { string PlatformString = (Target.Platform == UnrealTargetPlatform.Win64) ? "Win64" : "Win32"; string PluginsPath = Path.Combine(ModuleDirectory, "../../../"); string TobiiRelativeAPIPath = "TobiiEyetracking/ThirdParty/GameIntegration"; string TobiiRelativeIncludePath = Path.Combine(TobiiRelativeAPIPath, "include"); string TobiiRelativeLibraryBasePath = Path.Combine(TobiiRelativeAPIPath, "lib"); //Includes PrivateIncludePaths.Add(Path.Combine(PluginsPath, TobiiRelativeIncludePath)); //Add libraries AddLibrary(Path.Combine(PluginsPath, TobiiRelativeLibraryBasePath, PlatformString, "tobii_g2om.lib")); AddLibrary(Path.Combine(PluginsPath, TobiiRelativeLibraryBasePath, PlatformString, "Tobii.GameIntegration.GTOM.lib")); //Add DLL string RelativeG2OMDllPath = ""; string RelativeGTOMDllPath = ""; const string G2OMDllName = "tobii_g2om.dll"; const string GTOMDllName = "Tobii.GameIntegration.GTOM.dll"; if (IsEnginePlugin) { RelativeG2OMDllPath = Path.Combine("Binaries/ThirdParty/TobiiEyetracking", PlatformString, G2OMDllName); RuntimeDependencies.Add("$(EngineDir)/" + RelativeG2OMDllPath); RelativeGTOMDllPath = Path.Combine("Binaries/ThirdParty/TobiiEyetracking", PlatformString, GTOMDllName); RuntimeDependencies.Add("$(EngineDir)/" + RelativeGTOMDllPath); } else { RelativeG2OMDllPath = Path.Combine(TobiiRelativeLibraryBasePath, PlatformString, G2OMDllName); RuntimeDependencies.Add(Path.Combine(PluginsPath, RelativeG2OMDllPath)); RelativeGTOMDllPath = Path.Combine(TobiiRelativeLibraryBasePath, PlatformString, GTOMDllName); RuntimeDependencies.Add(Path.Combine(PluginsPath, RelativeGTOMDllPath)); } PublicDefinitions.Add("TOBII_G2OM_RELATIVE_DLL_PATH=R\"(" + RelativeG2OMDllPath + ")\""); PublicDelayLoadDLLs.Add(G2OMDllName); PublicDefinitions.Add("TOBII_GTOM_RELATIVE_DLL_PATH=R\"(" + RelativeGTOMDllPath + ")\""); PublicDelayLoadDLLs.Add(GTOMDllName); PublicDefinitions.Add("TOBII_EYETRACKING_ACTIVE=1"); } else { PublicDefinitions.Add("TOBII_EYETRACKING_ACTIVE=0"); } }
/// <summary> /// Generate HTML documentation for all the tasks /// </summary> /// <param name="NameToTask">Map of task name to implementation</param> /// <param name="OutputFile">Output file</param> static void GenerateDocumentation(Dictionary <string, ScriptTask> NameToTask, FileReference OutputFile) { // Find all the assemblies containing tasks Assembly[] TaskAssemblies = NameToTask.Values.Select(x => x.ParametersClass.Assembly).Distinct().ToArray(); // Read documentation for each of them Dictionary <string, XmlElement> MemberNameToElement = new Dictionary <string, XmlElement>(); foreach (Assembly TaskAssembly in TaskAssemblies) { string XmlFileName = Path.ChangeExtension(TaskAssembly.Location, ".xml"); if (File.Exists(XmlFileName)) { // Read the document XmlDocument Document = new XmlDocument(); Document.Load(XmlFileName); // Parse all the members, and add them to the map foreach (XmlElement Element in Document.SelectNodes("/doc/members/member")) { string Name = Element.GetAttribute("name"); MemberNameToElement.Add(Name, Element); } } } // Create the output directory if (FileReference.Exists(OutputFile)) { FileReference.MakeWriteable(OutputFile); } else { DirectoryReference.CreateDirectory(OutputFile.Directory); } // Write the output file LogInformation("Writing {0}...", OutputFile); using (StreamWriter Writer = new StreamWriter(OutputFile.FullName)) { Writer.WriteLine("<html>"); Writer.WriteLine(" <head>"); Writer.WriteLine(" <style>"); Writer.WriteLine(" table { border-collapse: collapse }"); Writer.WriteLine(" table, th, td { border: 1px solid black; }"); Writer.WriteLine(" </style>"); Writer.WriteLine(" </head>"); Writer.WriteLine(" <body>"); Writer.WriteLine(" <h1>BuildGraph Tasks</h1>"); foreach (string TaskName in NameToTask.Keys.OrderBy(x => x)) { // Get the task object ScriptTask Task = NameToTask[TaskName]; // Get the documentation for this task XmlElement TaskElement; if (MemberNameToElement.TryGetValue("T:" + Task.TaskClass.FullName, out TaskElement)) { // Write the task heading Writer.WriteLine(" <h2>{0}</h2>", TaskName); Writer.WriteLine(" <p>{0}</p>", TaskElement.SelectSingleNode("summary").InnerXml.Trim()); // Start the parameter table Writer.WriteLine(" <table>"); Writer.WriteLine(" <tr>"); Writer.WriteLine(" <th>Attribute</th>"); Writer.WriteLine(" <th>Type</th>"); Writer.WriteLine(" <th>Usage</th>"); Writer.WriteLine(" <th>Description</th>"); Writer.WriteLine(" </tr>"); // Document the parameters foreach (string ParameterName in Task.NameToParameter.Keys) { // Get the parameter data ScriptTaskParameter Parameter = Task.NameToParameter[ParameterName]; // Get the documentation for this parameter XmlElement ParameterElement; if (MemberNameToElement.TryGetValue("F:" + Parameter.FieldInfo.DeclaringType.FullName + "." + Parameter.Name, out ParameterElement)) { string TypeName = Parameter.FieldInfo.FieldType.Name; if (Parameter.ValidationType != TaskParameterValidationType.Default) { StringBuilder NewTypeName = new StringBuilder(Parameter.ValidationType.ToString()); for (int Idx = 1; Idx < NewTypeName.Length; Idx++) { if (Char.IsLower(NewTypeName[Idx - 1]) && Char.IsUpper(NewTypeName[Idx])) { NewTypeName.Insert(Idx, ' '); } } TypeName = NewTypeName.ToString(); } Writer.WriteLine(" <tr>"); Writer.WriteLine(" <td>{0}</td>", ParameterName); Writer.WriteLine(" <td>{0}</td>", TypeName); Writer.WriteLine(" <td>{0}</td>", Parameter.bOptional? "Optional" : "Required"); Writer.WriteLine(" <td>{0}</td>", ParameterElement.SelectSingleNode("summary").InnerXml.Trim()); Writer.WriteLine(" </tr>"); } } // Always include the "If" attribute Writer.WriteLine(" <tr>"); Writer.WriteLine(" <td>If</td>"); Writer.WriteLine(" <td>Condition</td>"); Writer.WriteLine(" <td>Optional</td>"); Writer.WriteLine(" <td>Whether to execute this task. It is ignored if this condition evaluates to false.</td>"); Writer.WriteLine(" </tr>"); // Close the table Writer.WriteLine(" <table>"); } } Writer.WriteLine(" </body>"); Writer.WriteLine("</html>"); } }
/// <summary> /// Main entry point for the BuildGraph command /// </summary> public override ExitCode Execute() { // Parse the command line parameters string ScriptFileName = ParseParamValue("Script", null); string TargetNames = ParseParamValue("Target", null); string DocumentationFileName = ParseParamValue("Documentation", null); string SchemaFileName = ParseParamValue("Schema", null); string ExportFileName = ParseParamValue("Export", null); string PreprocessedFileName = ParseParamValue("Preprocess", null); string SharedStorageDir = ParseParamValue("SharedStorageDir", null); string SingleNodeName = ParseParamValue("SingleNode", null); string TriggerName = ParseParamValue("Trigger", null); string[] SkipTriggerNames = ParseParamValue("SkipTrigger", "").Split(new char[] { '+', ';' }, StringSplitOptions.RemoveEmptyEntries).ToArray(); bool bSkipTriggers = ParseParam("SkipTriggers"); string TokenSignature = ParseParamValue("TokenSignature", null); bool bSkipTargetsWithoutTokens = ParseParam("SkipTargetsWithoutTokens"); bool bResume = SingleNodeName != null || ParseParam("Resume"); bool bListOnly = ParseParam("ListOnly"); bool bShowDiagnostics = ParseParam("ShowDiagnostics"); bool bWriteToSharedStorage = ParseParam("WriteToSharedStorage") || CommandUtils.IsBuildMachine; bool bPublicTasksOnly = ParseParam("PublicTasksOnly"); string ReportName = ParseParamValue("ReportName", null); GraphPrintOptions PrintOptions = GraphPrintOptions.ShowCommandLineOptions; if (ParseParam("ShowDeps")) { PrintOptions |= GraphPrintOptions.ShowDependencies; } if (ParseParam("ShowNotifications")) { PrintOptions |= GraphPrintOptions.ShowNotifications; } // Parse any specific nodes to clean List <string> CleanNodes = new List <string>(); foreach (string NodeList in ParseParamValues("CleanNode")) { foreach (string NodeName in NodeList.Split('+', ';')) { CleanNodes.Add(NodeName); } } // Set up the standard properties which build scripts might need Dictionary <string, string> DefaultProperties = new Dictionary <string, string>(StringComparer.InvariantCultureIgnoreCase); DefaultProperties["Branch"] = P4Enabled ? P4Env.Branch : "Unknown"; DefaultProperties["EscapedBranch"] = P4Enabled ? CommandUtils.EscapePath(P4Env.Branch) : "Unknown"; DefaultProperties["Change"] = P4Enabled ? P4Env.Changelist.ToString() : "0"; DefaultProperties["CodeChange"] = P4Enabled ? P4Env.CodeChangelist.ToString() : "0"; DefaultProperties["RootDir"] = CommandUtils.RootDirectory.FullName; DefaultProperties["IsBuildMachine"] = IsBuildMachine ? "true" : "false"; DefaultProperties["HostPlatform"] = HostPlatform.Current.HostEditorPlatform.ToString(); DefaultProperties["RestrictedFolderNames"] = String.Join(";", RestrictedFolders.Names); DefaultProperties["RestrictedFolderFilter"] = String.Join(";", RestrictedFolders.Names.Select(x => String.Format(".../{0}/...", x))); // Attempt to read existing Build Version information BuildVersion Version; if (BuildVersion.TryRead(BuildVersion.GetDefaultFileName(), out Version)) { DefaultProperties["EngineMajorVersion"] = Version.MajorVersion.ToString(); DefaultProperties["EngineMinorVersion"] = Version.MinorVersion.ToString(); DefaultProperties["EnginePatchVersion"] = Version.PatchVersion.ToString(); DefaultProperties["EngineCompatibleChange"] = Version.CompatibleChangelist.ToString(); } // Add any additional custom arguments from the command line (of the form -Set:X=Y) Dictionary <string, string> Arguments = new Dictionary <string, string>(StringComparer.InvariantCultureIgnoreCase); foreach (string Param in Params) { const string Prefix = "set:"; if (Param.StartsWith(Prefix, StringComparison.InvariantCultureIgnoreCase)) { int EqualsIdx = Param.IndexOf('='); if (EqualsIdx >= 0) { Arguments[Param.Substring(Prefix.Length, EqualsIdx - Prefix.Length)] = Param.Substring(EqualsIdx + 1); } else { LogWarning("Missing value for '{0}'", Param.Substring(Prefix.Length)); } } } // Find all the tasks from the loaded assemblies Dictionary <string, ScriptTask> NameToTask = new Dictionary <string, ScriptTask>(); if (!FindAvailableTasks(NameToTask, bPublicTasksOnly)) { return(ExitCode.Error_Unknown); } // Generate documentation if (DocumentationFileName != null) { GenerateDocumentation(NameToTask, new FileReference(DocumentationFileName)); return(ExitCode.Success); } // Create a schema for the given tasks ScriptSchema Schema = new ScriptSchema(NameToTask); if (SchemaFileName != null) { FileReference FullSchemaFileName = new FileReference(SchemaFileName); LogInformation("Writing schema to {0}...", FullSchemaFileName.FullName); Schema.Export(FullSchemaFileName); if (ScriptFileName == null) { return(ExitCode.Success); } } // Check there was a script specified if (ScriptFileName == null) { LogError("Missing -Script= parameter for BuildGraph"); return(ExitCode.Error_Unknown); } // Read the script from disk Graph Graph; if (!ScriptReader.TryRead(new FileReference(ScriptFileName), Arguments, DefaultProperties, Schema, out Graph)) { return(ExitCode.Error_Unknown); } // Create the temp storage handler DirectoryReference RootDir = new DirectoryReference(CommandUtils.CmdEnv.LocalRoot); TempStorage Storage = new TempStorage(RootDir, DirectoryReference.Combine(RootDir, "Engine", "Saved", "BuildGraph"), (SharedStorageDir == null)? null : new DirectoryReference(SharedStorageDir), bWriteToSharedStorage); if (!bResume) { Storage.CleanLocal(); } foreach (string CleanNode in CleanNodes) { Storage.CleanLocalNode(CleanNode); } // Convert the supplied target references into nodes HashSet <Node> TargetNodes = new HashSet <Node>(); if (TargetNames == null) { if (!bListOnly) { LogError("Missing -Target= parameter for BuildGraph"); return(ExitCode.Error_Unknown); } TargetNodes.UnionWith(Graph.Agents.SelectMany(x => x.Nodes)); } else { foreach (string TargetName in TargetNames.Split(new char[] { '+', ';' }, StringSplitOptions.RemoveEmptyEntries).Select(x => x.Trim())) { Node[] Nodes; if (!Graph.TryResolveReference(TargetName, out Nodes)) { LogError("Target '{0}' is not in graph", TargetName); return(ExitCode.Error_Unknown); } TargetNodes.UnionWith(Nodes); } } // Try to acquire tokens for all the target nodes we want to build if (TokenSignature != null) { // Find all the lock files HashSet <FileReference> RequiredTokens = new HashSet <FileReference>(TargetNodes.SelectMany(x => x.RequiredTokens)); // List out all the required tokens if (SingleNodeName == null) { CommandUtils.LogInformation("Required tokens:"); foreach (Node Node in TargetNodes) { foreach (FileReference RequiredToken in Node.RequiredTokens) { CommandUtils.LogInformation(" '{0}' requires {1}", Node, RequiredToken); } } } // Try to create all the lock files List <FileReference> CreatedTokens = new List <FileReference>(); if (!bListOnly) { CreatedTokens.AddRange(RequiredTokens.Where(x => WriteTokenFile(x, TokenSignature))); } // Find all the tokens that we don't have Dictionary <FileReference, string> MissingTokens = new Dictionary <FileReference, string>(); foreach (FileReference RequiredToken in RequiredTokens) { string CurrentOwner = ReadTokenFile(RequiredToken); if (CurrentOwner != null && CurrentOwner != TokenSignature) { MissingTokens.Add(RequiredToken, CurrentOwner); } } // If we want to skip all the nodes with missing locks, adjust the target nodes to account for it if (MissingTokens.Count > 0) { if (bSkipTargetsWithoutTokens) { // Find all the nodes we're going to skip HashSet <Node> SkipNodes = new HashSet <Node>(); foreach (IGrouping <string, FileReference> MissingTokensForBuild in MissingTokens.GroupBy(x => x.Value, x => x.Key)) { LogInformation("Skipping the following nodes due to {0}:", MissingTokensForBuild.Key); foreach (FileReference MissingToken in MissingTokensForBuild) { foreach (Node SkipNode in TargetNodes.Where(x => x.RequiredTokens.Contains(MissingToken) && SkipNodes.Add(x))) { LogInformation(" {0}", SkipNode); } } } // Write a list of everything left over if (SkipNodes.Count > 0) { TargetNodes.ExceptWith(SkipNodes); LogInformation("Remaining target nodes:"); foreach (Node TargetNode in TargetNodes) { LogInformation(" {0}", TargetNode); } if (TargetNodes.Count == 0) { LogInformation(" None."); } } } else { foreach (KeyValuePair <FileReference, string> Pair in MissingTokens) { List <Node> SkipNodes = TargetNodes.Where(x => x.RequiredTokens.Contains(Pair.Key)).ToList(); LogError("Cannot run {0} due to previous build: {1}", String.Join(", ", SkipNodes), Pair.Value); } foreach (FileReference CreatedToken in CreatedTokens) { FileReference.Delete(CreatedToken); } return(ExitCode.Error_Unknown); } } } // Cull the graph to include only those nodes Graph.Select(TargetNodes); // Collapse any triggers in the graph which are marked to be skipped HashSet <ManualTrigger> SkipTriggers = new HashSet <ManualTrigger>(); if (bSkipTriggers) { SkipTriggers.UnionWith(Graph.NameToTrigger.Values); } else { foreach (string SkipTriggerName in SkipTriggerNames) { ManualTrigger SkipTrigger; if (!Graph.NameToTrigger.TryGetValue(TriggerName, out SkipTrigger)) { LogError("Couldn't find trigger '{0}'", TriggerName); return(ExitCode.Error_Unknown); } SkipTriggers.Add(SkipTrigger); } } Graph.SkipTriggers(SkipTriggers); // If a report for the whole build was requested, insert it into the graph if (ReportName != null) { Report NewReport = new Report(ReportName); NewReport.Nodes.UnionWith(Graph.Agents.SelectMany(x => x.Nodes)); Graph.NameToReport.Add(ReportName, NewReport); } // Write out the preprocessed script if (PreprocessedFileName != null) { FileReference PreprocessedFileLocation = new FileReference(PreprocessedFileName); LogInformation("Writing {0}...", PreprocessedFileLocation); Graph.Write(PreprocessedFileLocation, (SchemaFileName != null)? new FileReference(SchemaFileName) : null); return(ExitCode.Success); } // Find the triggers which we are explicitly running. ManualTrigger Trigger = null; if (TriggerName != null && !Graph.NameToTrigger.TryGetValue(TriggerName, out Trigger)) { LogError("Couldn't find trigger '{0}'", TriggerName); return(ExitCode.Error_Unknown); } // If we're just building a single node, find it Node SingleNode = null; if (SingleNodeName != null && !Graph.NameToNode.TryGetValue(SingleNodeName, out SingleNode)) { LogError("Node '{0}' is not in the trimmed graph", SingleNodeName); return(ExitCode.Error_Unknown); } // If we just want to show the contents of the graph, do so and exit. if (bListOnly) { HashSet <Node> CompletedNodes = FindCompletedNodes(Graph, Storage); Graph.Print(CompletedNodes, PrintOptions); } // Print out all the diagnostic messages which still apply, unless we're running a step as part of a build system or just listing the contents of the file. if (SingleNode == null && (!bListOnly || bShowDiagnostics)) { IEnumerable <GraphDiagnostic> Diagnostics = Graph.Diagnostics.Where(x => x.EnclosingTrigger == Trigger); foreach (GraphDiagnostic Diagnostic in Diagnostics) { if (Diagnostic.EventType == LogEventType.Console) { CommandUtils.LogInformation(Diagnostic.Message); } else if (Diagnostic.EventType == LogEventType.Warning) { CommandUtils.LogWarning(Diagnostic.Message); } else { CommandUtils.LogError(Diagnostic.Message); } } if (Diagnostics.Any(x => x.EventType == LogEventType.Error)) { return(ExitCode.Error_Unknown); } } // Export the graph to a file if (ExportFileName != null) { HashSet <Node> CompletedNodes = FindCompletedNodes(Graph, Storage); Graph.Print(CompletedNodes, PrintOptions); Graph.Export(new FileReference(ExportFileName), Trigger, CompletedNodes); return(ExitCode.Success); } // Execute the command if (!bListOnly) { if (SingleNode != null) { if (!BuildNode(new JobContext(this), Graph, SingleNode, Storage, bWithBanner: true)) { return(ExitCode.Error_Unknown); } } else { if (!BuildAllNodes(new JobContext(this), Graph, Storage)) { return(ExitCode.Error_Unknown); } } } return(ExitCode.Success); }
/// <summary> /// Adds rules for files which match the given names /// </summary> /// <param name="FileName">The filenames to rules for</param> /// <param name="BaseDirectoryName">Base directory for the rules</param> /// <param name="Type">Whether to add an include or exclude rule</param> public void AddRuleForFiles(IEnumerable<FileReference> Files, DirectoryReference BaseDirectory, FileFilterType Type) { foreach (FileReference File in Files) { AddRule("/" + File.MakeRelativeTo(BaseDirectory), Type); } }
public override bool PublishSymbols(DirectoryReference SymbolStoreDirectory, List <FileReference> Files, string Product, string BuildVersion = null) { // Get the SYMSTORE.EXE path, using the latest SDK version we can find. FileReference SymStoreExe = GetSymStoreExe(); List <FileReference> FilesToAdd = Files.Where(x => x.HasExtension(".pdb") || x.HasExtension(".exe") || x.HasExtension(".dll")).ToList(); if (FilesToAdd.Count > 0) { DateTime Start = DateTime.Now; DirectoryReference TempSymStoreDir = DirectoryReference.Combine(RootDirectory, "Saved", "SymStore"); if (DirectoryReference.Exists(TempSymStoreDir)) { CommandUtils.DeleteDirectory(TempSymStoreDir); DirectoryReference.CreateDirectory(TempSymStoreDir); } string TempFileName = Path.GetTempFileName(); try { File.WriteAllLines(TempFileName, FilesToAdd.Select(x => x.FullName), Encoding.ASCII); // Copy everything to the temp symstore ProcessStartInfo StartInfo = new ProcessStartInfo(); StartInfo.FileName = SymStoreExe.FullName; StartInfo.Arguments = string.Format("add /f \"@{0}\" /s \"{1}\" /t \"{2}\"", TempFileName, TempSymStoreDir, Product); StartInfo.UseShellExecute = false; StartInfo.CreateNoWindow = true; if (Utils.RunLocalProcessAndLogOutput(StartInfo) != 0) { return(false); } } finally { File.Delete(TempFileName); } DateTime CompressDone = DateTime.Now; LogInformation("Took {0}s to compress the symbol files to temp path {1}", (CompressDone - Start).TotalSeconds, TempSymStoreDir); int CopiedCount = 0; // Take each new compressed file made and try and copy it to the real symstore. Exclude any symstore admin files foreach (FileReference File in DirectoryReference.EnumerateFiles(TempSymStoreDir, "*.*", SearchOption.AllDirectories).Where(File => IsSymbolFile(File))) { string RelativePath = File.MakeRelativeTo(DirectoryReference.Combine(TempSymStoreDir)); FileReference ActualDestinationFile = FileReference.Combine(SymbolStoreDirectory, RelativePath); // Try and add a version file. Do this before checking to see if the symbol is there already in the case of exact matches (multiple builds could use the same pdb, for example) if (!string.IsNullOrWhiteSpace(BuildVersion)) { FileReference BuildVersionFile = FileReference.Combine(ActualDestinationFile.Directory, string.Format("{0}.version", BuildVersion)); // Attempt to create the file. Just continue if it fails. try { DirectoryReference.CreateDirectory(BuildVersionFile.Directory); FileReference.WriteAllText(BuildVersionFile, string.Empty); } catch (Exception Ex) { LogWarning("Failed to write the version file, reason {0}", Ex.ToString()); } } // Don't bother copying the temp file if the destination file is there already. if (FileReference.Exists(ActualDestinationFile)) { LogInformation("Destination file {0} already exists, skipping", ActualDestinationFile.FullName); continue; } FileReference TempDestinationFile = new FileReference(ActualDestinationFile.FullName + Guid.NewGuid().ToString()); try { CommandUtils.CopyFile(File.FullName, TempDestinationFile.FullName); } catch (Exception Ex) { throw new AutomationException("Couldn't copy the symbol file to the temp store! Reason: {0}", Ex.ToString()); } // Move the file in the temp store over. try { FileReference.Move(TempDestinationFile, ActualDestinationFile); //LogVerbose("Moved {0} to {1}", TempDestinationFile, ActualDestinationFile); CopiedCount++; } catch (Exception Ex) { // If the file is there already, it was likely either copied elsewhere (and this is an ioexception) or it had a file handle open already. // Either way, it's fine to just continue on. if (FileReference.Exists(ActualDestinationFile)) { LogInformation("Destination file {0} already exists or was in use, skipping.", ActualDestinationFile.FullName); continue; } // If it doesn't exist, we actually failed to copy it entirely. else { LogWarning("Couldn't move temp file {0} to the symbol store at location {1}! Reason: {2}", TempDestinationFile.FullName, ActualDestinationFile.FullName, Ex.ToString()); } } // Delete the temp one no matter what, don't want them hanging around in the symstore finally { FileReference.Delete(TempDestinationFile); } } LogInformation("Took {0}s to copy {1} symbol files to the store at {2}", (DateTime.Now - CompressDone).TotalSeconds, CopiedCount, SymbolStoreDirectory); FileReference PingmeFile = FileReference.Combine(SymbolStoreDirectory, "pingme.txt"); if (!FileReference.Exists(PingmeFile)) { LogInformation("Creating {0} to mark path as three-tiered symbol location", PingmeFile); File.WriteAllText(PingmeFile.FullName, "Exists to mark this as a three-tiered symbol location"); } } return(true); }
public override void ExecuteBuild() { CommandUtils.LogInformation("************************* 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} -Mode=JsonExport -OutputFile=\"{2}\"", 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")); } // 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; if (RuntimeDependency.TryGetStringField("SourcePath", out RuntimeDependencyPath) || RuntimeDependency.TryGetStringField("Path", out RuntimeDependencyPath)) { List <FileReference> Files = FileFilter.ResolveWildcard(DirectoryReference.Combine(CommandUtils.EngineDirectory, "Source"), RuntimeDependencyPath); DirectoriesToScan.UnionWith(Files.Select(x => x.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.Parse(Object.GetStringField("Platform")) }; string[] ExcludePlatformNames = Utils.MakeListOfUnsupportedPlatforms(SupportedPlatforms, bIncludeUnbuildablePlatforms: true).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; try { 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; } } } catch (Exception Ex) { ExceptionUtils.AddContext(Ex, "while processing {0}", TpsFile); throw; } OutputMessages.Add(Message); } OutputMessages.Sort(); // Print them all out foreach (string OutputMessage in OutputMessages) { CommandUtils.LogInformation(OutputMessage); } }
public override void ExecuteBuild() { // Get the plugin filename string PluginParam = ParseParamValue("Plugin"); if (PluginParam == null) { throw new AutomationException("Plugin file name was not specified via the -plugin argument"); } // Read the plugin FileReference PluginFile = new FileReference(PluginParam); DirectoryReference PluginDirectory = PluginFile.Directory; PluginDescriptor Plugin = PluginDescriptor.FromFile(PluginFile); // Clean the intermediate build directory DirectoryReference IntermediateBuildDirectory = DirectoryReference.Combine(PluginDirectory, "Intermediate", "Build"); if (CommandUtils.DirectoryExists(IntermediateBuildDirectory.FullName)) { CommandUtils.DeleteDirectory(IntermediateBuildDirectory.FullName); } // Create a host project for the plugin. For script generator plugins, we need to have UHT be able to load it - and that can only happen if it's enabled in a project. DirectoryReference HostProjectDirectory = DirectoryReference.Combine(new DirectoryReference(CommandUtils.CmdEnv.LocalRoot), "HostProject"); if (CommandUtils.DirectoryExists(HostProjectDirectory.FullName)) { CommandUtils.DeleteDirectory(HostProjectDirectory.FullName); } DirectoryReference HostProjectPluginDirectory = DirectoryReference.Combine(HostProjectDirectory, "Plugins", PluginFile.GetFileNameWithoutExtension()); string[] CopyPluginFiles = Directory.EnumerateFiles(PluginDirectory.FullName, "*", SearchOption.AllDirectories).ToArray(); foreach (string CopyPluginFile in CopyPluginFiles) { CommandUtils.CopyFile(CopyPluginFile, CommandUtils.MakeRerootedFilePath(CopyPluginFile, PluginDirectory.FullName, HostProjectPluginDirectory.FullName)); } FileReference HostProjectPluginFile = FileReference.Combine(HostProjectPluginDirectory, PluginFile.GetFileName()); FileReference HostProjectFile = FileReference.Combine(HostProjectDirectory, "HostProject.uproject"); File.WriteAllText(HostProjectFile.FullName, "{ \"FileVersion\": 3, \"Plugins\": [ { \"Name\": \"" + PluginFile.GetFileNameWithoutExtension() + "\", \"Enabled\": true } ] }"); // Get any additional arguments from the commandline string AdditionalArgs = ""; // Build the host platforms List <string> ReceiptFileNames = new List <string>(); UnrealTargetPlatform HostPlatform = BuildHostPlatform.Current.Platform; if (!ParseParam("NoHostPlatform")) { if (Plugin.bCanBeUsedWithUnrealHeaderTool) { BuildPluginWithUBT(PluginFile, Plugin, null, "UnrealHeaderTool", TargetRules.TargetType.Program, HostPlatform, UnrealTargetConfiguration.Development, ReceiptFileNames, String.Format("{0} -plugin {1}", AdditionalArgs, CommandUtils.MakePathSafeToUseWithCommandLine(HostProjectPluginFile.FullName))); } BuildPluginWithUBT(PluginFile, Plugin, HostProjectFile, "UE4Editor", TargetRules.TargetType.Editor, HostPlatform, UnrealTargetConfiguration.Development, ReceiptFileNames, AdditionalArgs); } // Add the game targets List <UnrealTargetPlatform> TargetPlatforms = Rocket.RocketBuild.GetTargetPlatforms(this, HostPlatform); foreach (UnrealTargetPlatform TargetPlatform in TargetPlatforms) { if (Rocket.RocketBuild.IsCodeTargetPlatform(HostPlatform, TargetPlatform)) { BuildPluginWithUBT(PluginFile, Plugin, HostProjectFile, "UE4Game", TargetRules.TargetType.Game, TargetPlatform, UnrealTargetConfiguration.Development, ReceiptFileNames, AdditionalArgs); BuildPluginWithUBT(PluginFile, Plugin, HostProjectFile, "UE4Game", TargetRules.TargetType.Game, TargetPlatform, UnrealTargetConfiguration.Shipping, ReceiptFileNames, AdditionalArgs); } } // Package the plugin to the output folder string PackageDirectory = ParseParamValue("Package"); if (PackageDirectory != null) { List <BuildProduct> BuildProducts = GetBuildProductsFromReceipts(UnrealBuildTool.UnrealBuildTool.EngineDirectory, HostProjectDirectory, ReceiptFileNames); PackagePlugin(HostProjectPluginFile, BuildProducts, PackageDirectory); } }
public virtual bool PublishSymbols(DirectoryReference SymbolStoreDirectory, List<FileReference> Files, string Product) { Log.TraceWarning("PublishSymbols() has not been implemented for {0}", CppPlatform.ToString()); return false; }
public virtual bool PublishSymbols(DirectoryReference SymbolStoreDirectory, List <FileReference> Files, string Product) { CommandUtils.LogWarning("PublishSymbols() has not been implemented for {0}", PlatformType.ToString()); return(false); }
static public void InvalidateCachedDirectory(DirectoryReference Directory) { Directories.Remove(Directory); }
public override bool PrepForUATPackageOrDeploy(UnrealTargetConfiguration Config, FileReference ProjectFile, string InProjectName, DirectoryReference InProjectDirectory, string InExecutablePath, DirectoryReference InEngineDir, bool bForDistribution, string CookFlavor, bool bIsDataDeploy, bool bCreateStubIPA) { return(TVOSExports.PrepForUATPackageOrDeploy(Config, ProjectFile, InProjectName, InProjectDirectory, InExecutablePath, InEngineDir, bForDistribution, CookFlavor, bIsDataDeploy, bCreateStubIPA)); }
public static bool CanCreateMapPaks(ProjectParams Param) { bool UseAsyncLevelLoading = false; var ConfigCache = UnrealBuildTool.ConfigCache.ReadHierarchy(ConfigHierarchyType.Engine, DirectoryReference.FromFile(Param.RawProjectPath), UnrealTargetPlatform.HTML5); ConfigCache.GetBool("/Script/HTML5PlatformEditor.HTML5TargetSettings", "UseAsyncLevelLoading", out UseAsyncLevelLoading); if (Param.Run) { return(false); } return(UseAsyncLevelLoading); }
public override bool DeployGeneratePList(FileReference ProjectFile, UnrealTargetConfiguration Config, DirectoryReference ProjectDirectory, bool bIsUE4Game, string GameName, string ProjectName, DirectoryReference InEngineDir, DirectoryReference AppDirectory, out bool bSupportsPortrait, out bool bSupportsLandscape, out bool bSkipIcons) { return(TVOSExports.GeneratePList(ProjectFile, Config, ProjectDirectory, bIsUE4Game, GameName, ProjectName, InEngineDir, AppDirectory, out bSupportsPortrait, out bSupportsLandscape, out bSkipIcons)); }
/// <summary> /// Constructor /// </summary> public XcodeSourceFile(FileReference InitFilePath, DirectoryReference InitRelativeBaseFolder) : base(InitFilePath, InitRelativeBaseFolder) { FileGuid = XcodeProjectFileGenerator.MakeXcodeGuid(); FileRefGuid = XcodeProjectFileGenerator.MakeXcodeGuid(); }
public override void GetFilesToDeployOrStage(ProjectParams Params, DeploymentContext SC) { // if (UnrealBuildTool.BuildHostPlatform.Current.Platform != UnrealTargetPlatform.Mac) { // copy the icons/launch screens from the engine { DirectoryReference SourcePath = DirectoryReference.Combine(SC.LocalRoot, "Engine", "Binaries", "TVOS", "AssetCatalog"); SC.StageFiles(StagedFileType.NonUFS, SourcePath, "Assets.car", false, null, StagedDirectoryReference.Root, true, false); } // copy any additional framework assets that will be needed at runtime { DirectoryReference SourcePath = DirectoryReference.Combine((SC.IsCodeBasedProject ? SC.ProjectRoot : SC.EngineRoot), "Intermediate", "TVOS", "FrameworkAssets"); if (DirectoryReference.Exists(SourcePath)) { SC.StageFiles(StagedFileType.NonUFS, SourcePath, "*.*", true, null, StagedDirectoryReference.Root, true, false); } } // copy the icons/launch screens from the game (may stomp the engine copies) { DirectoryReference SourcePath = DirectoryReference.Combine(SC.ProjectRoot, "Binaries", "TVOS", "AssetCatalog"); SC.StageFiles(StagedFileType.NonUFS, SourcePath, "Assets.car", false, null, StagedDirectoryReference.Root, true, false); } // copy the plist (only if code signing, as it's protected by the code sign blob in the executable and can't be modified independently) if (GetCodeSignDesirability(Params)) { DirectoryReference SourcePath = DirectoryReference.Combine((SC.IsCodeBasedProject ? SC.ProjectRoot : SC.EngineRoot), "Intermediate", "TVOS"); FileReference TargetPListFile = FileReference.Combine(SourcePath, (SC.IsCodeBasedProject ? SC.ShortProjectName : "UE4Game") + "-Info.plist"); // if (!File.Exists(TargetPListFile)) { // ensure the plist, entitlements, and provision files are properly copied Console.WriteLine("CookPlat {0}, this {1}", GetCookPlatform(false, false), ToString()); if (!SC.IsCodeBasedProject) { UnrealBuildTool.PlatformExports.SetRemoteIniPath(SC.ProjectRoot.FullName); } if (SC.StageTargetConfigurations.Count != 1) { throw new AutomationException("iOS is currently only able to package one target configuration at a time, but StageTargetConfigurations contained {0} configurations", SC.StageTargetConfigurations.Count); } var TargetConfiguration = SC.StageTargetConfigurations[0]; bool bSupportsPortrait = false; bool bSupportsLandscape = false; bool bSkipIcons = false; DeployGeneratePList(SC.RawProjectPath, TargetConfiguration, (SC.IsCodeBasedProject ? SC.ProjectRoot : SC.EngineRoot), !SC.IsCodeBasedProject, (SC.IsCodeBasedProject ? SC.ShortProjectName : "UE4Game"), SC.ShortProjectName, SC.EngineRoot, DirectoryReference.Combine((SC.IsCodeBasedProject ? SC.ProjectRoot : SC.EngineRoot), "Binaries", "TVOS", "Payload", (SC.IsCodeBasedProject ? SC.ShortProjectName : "UE4Game") + ".app"), out bSupportsPortrait, out bSupportsLandscape, out bSkipIcons); } SC.StageFiles(StagedFileType.NonUFS, SourcePath, TargetPListFile.GetFileName(), false, null, StagedDirectoryReference.Root, false, false, "Info.plist"); } } // copy the movies from the project { SC.StageFiles(StagedFileType.NonUFS, DirectoryReference.Combine(SC.ProjectRoot, "Build/TVOS/Resources/Movies"), "*", false, null, StagedDirectoryReference.Root, true, false); SC.StageFiles(StagedFileType.NonUFS, DirectoryReference.Combine(SC.ProjectRoot, "Content/Movies"), "*", true, null, StagedDirectoryReference.Root, true, false); } }
public void StageAppLocalDependencies(ProjectParams Params, DeploymentContext SC, string PlatformDir) { string BaseAppLocalDependenciesPath = Path.IsPathRooted(Params.AppLocalDirectory) ? CombinePaths(Params.AppLocalDirectory, PlatformDir) : CombinePaths(SC.ProjectRoot, Params.AppLocalDirectory, PlatformDir); if (Directory.Exists(BaseAppLocalDependenciesPath)) { string ProjectBinaryPath = new DirectoryReference(SC.ProjectBinariesFolder).MakeRelativeTo(new DirectoryReference(CombinePaths(SC.ProjectRoot, ".."))); string EngineBinaryPath = CombinePaths("Engine", "Binaries", PlatformDir); Log("Copying AppLocal dependencies from {0} to {1} and {2}", BaseAppLocalDependenciesPath, ProjectBinaryPath, EngineBinaryPath); foreach (string DependencyDirectory in Directory.EnumerateDirectories(BaseAppLocalDependenciesPath)) { SC.StageFiles(StagedFileType.NonUFS, DependencyDirectory, "*", false, null, ProjectBinaryPath); SC.StageFiles(StagedFileType.NonUFS, DependencyDirectory, "*", false, null, EngineBinaryPath); } } else { throw new AutomationException("Unable to deploy AppLocalDirectory dependencies. No such path: {0}", BaseAppLocalDependenciesPath); } }
public override void GetFilesToDeployOrStage(ProjectParams Params, DeploymentContext SC) { if (SC.bStageCrashReporter) { FileReference ReceiptFileName = TargetReceipt.GetDefaultPath(CommandUtils.EngineDirectory, "CrashReportClient", SC.StageTargetPlatform.PlatformType, UnrealTargetConfiguration.Shipping, null); if (FileReference.Exists(ReceiptFileName)) { DirectoryReference EngineDir = CommandUtils.EngineDirectory; DirectoryReference ProjectDir = DirectoryReference.FromFile(Params.RawProjectPath); TargetReceipt Receipt = TargetReceipt.Read(ReceiptFileName, EngineDir, ProjectDir); SC.StageBuildProductsFromReceipt(Receipt, true, false); } } // Stage all the build products Console.WriteLine("Staging all {0} build products", SC.StageTargets.Count); int BuildProductIdx = 0; foreach (StageTarget Target in SC.StageTargets) { Console.WriteLine(" Product {0}: {1}", BuildProductIdx, Target.Receipt.TargetName); SC.StageBuildProductsFromReceipt(Target.Receipt, Target.RequireFilesExist, Params.bTreatNonShippingBinariesAsDebugFiles); ++BuildProductIdx; } FileReference SplashImage = FileReference.Combine(SC.ProjectRoot, "Content", "Splash", "Splash.bmp"); if (FileReference.Exists(SplashImage)) { SC.StageFile(StagedFileType.NonUFS, SplashImage); } // Stage the bootstrap executable if (!Params.NoBootstrapExe) { foreach (StageTarget Target in SC.StageTargets) { BuildProduct Executable = Target.Receipt.BuildProducts.FirstOrDefault(x => x.Type == BuildProductType.Executable); if (Executable != null) { // only create bootstraps for executables string FullExecutablePath = Path.GetFullPath(Executable.Path.FullName); if (Executable.Path.FullName.Replace("\\", "/").Contains("/" + TargetPlatformType.ToString() + "/")) { string BootstrapArguments = ""; if (!ShouldStageCommandLine(Params, SC)) { if (!SC.IsCodeBasedProject) { BootstrapArguments = String.Format("\\\"../../../{0}/{0}.uproject\\\"", SC.ShortProjectName); } else { BootstrapArguments = SC.ShortProjectName; } } string BootstrapExeName; if (SC.StageTargetConfigurations.Count > 1) { BootstrapExeName = Path.GetFileName(Executable.Path.FullName); } else if (Params.IsCodeBasedProject) { BootstrapExeName = Target.Receipt.TargetName; } else { BootstrapExeName = SC.ShortProjectName; } List <StagedFileReference> StagePaths = SC.FilesToStage.NonUFSFiles.Where(x => x.Value == Executable.Path).Select(x => x.Key).ToList(); foreach (StagedFileReference StagePath in StagePaths) { StageBootstrapExecutable(SC, BootstrapExeName + ".sh", FullExecutablePath, StagePath.Name, BootstrapArguments); } } } } } }
public Noesis(ReadOnlyTargetRules Target) : base(Target) { Type = ModuleType.External; string NoesisBasePath = ModuleDirectory + "/NoesisSDK/"; string NoesisIncludePath = NoesisBasePath + "Include/"; string NoesisInteractivityIncludePath = NoesisBasePath + "Src/Packages/App/Interactivity/Include/"; PublicIncludePaths.Add(ModuleDirectory); PublicIncludePaths.Add(NoesisIncludePath); PublicIncludePaths.Add(NoesisInteractivityIncludePath); // Let's try to make sure the right version of the SDK is in the right place. const string RequiredVersionName = "2.2.5"; PublicDefinitions.Add("NOESIS_VERSION_NAME=\"" + RequiredVersionName + "\""); if (!Directory.Exists(NoesisBasePath)) { throw new BuildException("Could not find NoesisGUI SDK in " + NoesisBasePath + ". Minimum required version is " + RequiredVersionName); } if (!Directory.Exists(NoesisBasePath + "Bin")) { throw new BuildException("Could not find NoesisGUI SDK Bin directory in " + NoesisBasePath + "Bin. Minimum required version is " + RequiredVersionName); } if (!Directory.Exists(NoesisBasePath + "Include")) { throw new BuildException("Could not find NoesisGUI SDK Include directory in " + NoesisBasePath + "Include. Minimum required version is " + RequiredVersionName); } if (!Directory.Exists(NoesisBasePath + "Lib")) { throw new BuildException("Could not find NoesisGUI SDK Lib directory in " + NoesisBasePath + "Lib. Minimum required version is " + RequiredVersionName); } string NoesisSdkVersionInfo; try { NoesisSdkVersionInfo = File.ReadAllText(NoesisBasePath + "version.txt"); } catch (Exception) { throw new BuildException("Could not find NoesisGUI SDK version.txt in " + NoesisBasePath + "version.txt. Minimum required version is " + RequiredVersionName); } string[] LineSplit = NoesisSdkVersionInfo.Split('\n'); string[] SplitVersion = LineSplit[1].Split(' '); Version InstalledVersion = new Version(SplitVersion[0]); Version RequiredVersion = new Version(RequiredVersionName); if (InstalledVersion != RequiredVersion) { throw new BuildException("Wrong version of the NoesisGUI SDK installed in " + NoesisBasePath + ". Required version is " + RequiredVersionName); } PublicSystemIncludePaths.Add(NoesisIncludePath); if (Target.Platform == UnrealTargetPlatform.Win64) { string NoesisLibPath = NoesisBasePath + "Lib/windows_x86_64/"; PublicLibraryPaths.Add(NoesisLibPath); PublicAdditionalLibraries.Add("Noesis.lib"); string NoesisDllPath = "/NoesisSDK/Bin/windows_x86_64/Noesis.dll"; string NoesisDllTargetPath = "/Binaries/Win64/Noesis.dll"; if (Target.ProjectFile != null) { CopyNoesisDll(ModuleDirectory + NoesisDllPath, DirectoryReference.FromFile(Target.ProjectFile).ToString() + NoesisDllTargetPath); } CopyNoesisDll(ModuleDirectory + NoesisDllPath, ModuleDirectory + "/../.." + NoesisDllTargetPath); if (System.IO.File.Exists(Target.RelativeEnginePath + NoesisDllTargetPath)) { System.IO.File.Delete(Target.RelativeEnginePath + NoesisDllTargetPath); } if (Target.LinkType == TargetLinkType.Monolithic) { RuntimeDependencies.Add("$(ProjectDir)" + NoesisDllTargetPath); } else { RuntimeDependencies.Add("$(EngineDir)" + NoesisDllTargetPath); } } else if (Target.Platform == UnrealTargetPlatform.Mac) { string NoesisLibPath = NoesisBasePath + "Bin/osx/"; PublicLibraryPaths.Add(NoesisLibPath); PublicAdditionalLibraries.Add(NoesisLibPath + "Noesis.dylib"); string NoesisDylibPath = "/NoesisSDK/Bin/osx/Noesis.dylib"; RuntimeDependencies.Add(ModuleDirectory + NoesisDylibPath); } else if (Target.Platform == UnrealTargetPlatform.IOS) { string NoesisLibPath = NoesisBasePath + "Lib/ios/"; PublicLibraryPaths.Add(NoesisLibPath); PublicAdditionalLibraries.Add("Noesis"); PublicFrameworks.Add("CoreText"); } else if (Target.Platform == UnrealTargetPlatform.Android) { string NoesisLibPath = NoesisBasePath + "Bin/android_arm/"; PublicLibraryPaths.Add(NoesisLibPath); string NoesisLib64Path = NoesisBasePath + "Bin/android_arm64/"; PublicLibraryPaths.Add(NoesisLib64Path); PublicAdditionalLibraries.Add("Noesis"); string NoesisAplPath = "/Noesis_APL.xml"; AdditionalPropertiesForReceipt.Add("AndroidPlugin", ModuleDirectory + NoesisAplPath); } else if (Target.Platform == UnrealTargetPlatform.PS4) { string NoesisLibPath = NoesisBasePath + "Lib/ps4/"; PublicAdditionalLibraries.Add(NoesisLibPath + "Noesis.a"); } else if (Target.Platform == UnrealTargetPlatform.XboxOne) { string NoesisLibPath = NoesisBasePath + "Bin/xbox_one/"; PublicLibraryPaths.Add(NoesisLibPath); PublicAdditionalLibraries.Add("Noesis.lib"); } else if (Target.Platform == UnrealTargetPlatform.HTML5) { string NoesisLibPath = NoesisBasePath + "Bin/wasm/"; PublicAdditionalLibraries.Add(NoesisLibPath + "Noesis.bc"); } }
/// <summary> /// Execute all tests according to the provided context /// </summary> /// <param name="Context"></param> /// <returns></returns> public ExitCode RunTests(UnrealTestOptions ContextOptions) { if (ContextOptions.Verbose) { Gauntlet.Log.Level = Gauntlet.LogLevel.Verbose; } if (ContextOptions.VeryVerbose) { Gauntlet.Log.Level = Gauntlet.LogLevel.VeryVerbose; } if (ParseParam("log")) { if (!Directory.Exists(ContextOptions.LogDir)) { Directory.CreateDirectory(ContextOptions.LogDir); } // include test names and timestamp in log filename as multiple (parallel or sequential) Gauntlet tests may be outputting to same directory string LogPath = Path.Combine(ContextOptions.LogDir, string.Format("GauntletLog{0}-{1}.txt", ContextOptions.TestList.Aggregate(new StringBuilder(), (SB, T) => SB.AppendFormat("-{0}", T.ToString())).ToString(), DateTime.Now.ToString(@"yyyy.MM.dd.HH.mm.ss"))); Gauntlet.Log.Verbose("Writing Gauntlet log to {0}", LogPath); Gauntlet.Log.SaveToFile(LogPath); } // prune our temp folder Utils.SystemHelpers.CleanupMarkedDirectories(ContextOptions.TempDir, 7); if (string.IsNullOrEmpty(ContextOptions.Build)) { throw new AutomationException("No builds specified. Use -builds=p:\\path\\to\\build"); } if (typeof(UnrealBuildSource).IsAssignableFrom(ContextOptions.BuildSourceType) == false) { throw new AutomationException("Provided BuildSource type does not inherit from UnrealBuildSource"); } // make -test=none implicit if no test is supplied if (ContextOptions.TestList.Count == 0) { Gauntlet.Log.Info("No test specified, creating default test node"); ContextOptions.TestList.Add(TestRequest.CreateRequest("DefaultTest")); } bool EditorForAllRoles = Globals.Params.ParseParam("editor") || string.Equals(Globals.Params.ParseValue("build", ""), "editor", StringComparison.OrdinalIgnoreCase); if (EditorForAllRoles) { Gauntlet.Log.Verbose("Will use Editor for all roles"); } Dictionary <UnrealTargetRole, UnrealTestRoleContext> RoleContexts = new Dictionary <UnrealTargetRole, UnrealTestRoleContext>(); // Default platform to the current os UnrealTargetPlatform DefaultPlatform = BuildHostPlatform.Current.Platform; UnrealTargetConfiguration DefaultConfiguration = UnrealTargetConfiguration.Development; DirectoryReference UnrealPath = new DirectoryReference(Environment.CurrentDirectory); // todo, pass this in as a BuildSource and remove the COntextOption params specific to finding builds UnrealBuildSource BuildInfo = (UnrealBuildSource)Activator.CreateInstance(ContextOptions.BuildSourceType, new object[] { ContextOptions.ProjectPath, UnrealPath, ContextOptions.UsesSharedBuildType, ContextOptions.Build, ContextOptions.SearchPaths }); // Setup accounts SetupAccounts(); List <ITestNode> AllTestNodes = new List <ITestNode>(); bool InitializedDevices = false; HashSet <UnrealTargetPlatform> UsedPlatforms = new HashSet <UnrealTargetPlatform>(); // for all platforms we want to test... foreach (ArgumentWithParams PlatformWithParams in ContextOptions.PlatformList) { string PlatformString = PlatformWithParams.Argument; // combine global and platform-specific params Params CombinedParams = new Params(ContextOptions.Params.AllArguments.Concat(PlatformWithParams.AllArguments).ToArray()); UnrealTargetPlatform PlatformType = UnrealTargetPlatform.Parse(PlatformString); if (!InitializedDevices) { // Setup the devices and assign them to the executor SetupDevices(PlatformType, ContextOptions); InitializedDevices = true; } // Create a context for each process type to operate as foreach (UnrealTargetRole Type in Enum.GetValues(typeof(UnrealTargetRole))) { UnrealTestRoleContext Role = new UnrealTestRoleContext(); // Default to these Role.Type = Type; Role.Platform = DefaultPlatform; Role.Configuration = DefaultConfiguration; // globally, what was requested (e.g -platform=PS4 -configuration=Shipping) UnrealTargetPlatform RequestedPlatform = PlatformType; UnrealTargetConfiguration RequestedConfiguration = ContextOptions.Configuration; // look for FooConfiguration, FooPlatform overrides. // e.g. ServerConfiguration, ServerPlatform string PlatformRoleString = Globals.Params.ParseValue(Type.ToString() + "Platform", null); string ConfigString = Globals.Params.ParseValue(Type.ToString() + "Configuration", null); if (string.IsNullOrEmpty(PlatformRoleString) == false) { RequestedPlatform = UnrealTargetPlatform.Parse(PlatformRoleString); } if (string.IsNullOrEmpty(ConfigString) == false) { RequestedConfiguration = (UnrealTargetConfiguration)Enum.Parse(typeof(UnrealTargetConfiguration), ConfigString, true); } // look for -clientargs= and -editorclient etc Role.ExtraArgs = Globals.Params.ParseValue(Type.ToString() + "Args", ""); bool UsesEditor = EditorForAllRoles || Globals.Params.ParseParam("Editor" + Type.ToString()); if (UsesEditor) { Gauntlet.Log.Verbose("Will use Editor for role {0}", Type); } Role.Skip = Globals.Params.ParseParam("Skip" + Type.ToString()); if (Role.Skip) { Gauntlet.Log.Verbose("Will use NullPlatform to skip role {0}", Type); } // TODO - the below is a bit rigid, but maybe that's good enough since the "actually use the editor.." option // is specific to clients and servers // client can override platform and config if (Type.IsClient()) { Role.Platform = RequestedPlatform; Role.Configuration = RequestedConfiguration; if (UsesEditor) { Role.Type = UnrealTargetRole.EditorGame; Role.Platform = DefaultPlatform; Role.Configuration = UnrealTargetConfiguration.Development; } } else if (Type.IsServer()) { // server can only override config Role.Configuration = RequestedConfiguration; if (UsesEditor) { Role.Type = UnrealTargetRole.EditorServer; Role.Platform = DefaultPlatform; Role.Configuration = UnrealTargetConfiguration.Development; } } Gauntlet.Log.Verbose("Mapped Role {0} to RoleContext {1}", Type, Role); RoleContexts[Type] = Role; UsedPlatforms.Add(Role.Platform); } UnrealTestContext Context = new UnrealTestContext(BuildInfo, RoleContexts, ContextOptions); IEnumerable <ITestNode> TestNodes = CreateTestList(Context, CombinedParams, PlatformWithParams); AllTestNodes.AddRange(TestNodes); } bool AllTestsPassed = ExecuteTests(ContextOptions, AllTestNodes); // dispose now, not during shutdown gc, because this runs commands... DevicePool.Instance.Dispose(); DoCleanup(UsedPlatforms); return(AllTestsPassed ? ExitCode.Success : ExitCode.Error_TestFailure); }
/// <summary> /// Gets the dependency cache path and filename for the specified target. /// </summary> /// <param name="Target">Current build target</param> /// <returns>Cache Path</returns> public static FileReference GetDependencyCachePathForTarget(UEBuildTarget Target) { DirectoryReference PlatformIntermediatePath; if (Target.ProjectFile != null) { PlatformIntermediatePath = DirectoryReference.Combine(Target.ProjectFile.Directory, BuildConfiguration.PlatformIntermediateFolder); } else { PlatformIntermediatePath = new DirectoryReference(BuildConfiguration.PlatformIntermediatePath); } return FileReference.Combine(PlatformIntermediatePath, Target.GetTargetName(), "FlatCPPIncludes.bin"); }
/// <summary> /// Execute the task. /// </summary> /// <param name="Job">Information about the current job</param> /// <param name="BuildProducts">Set of build products produced by this node.</param> /// <param name="TagNameToFileSet">Mapping from tag names to the set of files they include</param> public override void Execute(JobContext Job, HashSet <FileReference> BuildProducts, Dictionary <string, HashSet <FileReference> > TagNameToFileSet) { // Get the project path, and check it exists FileReference ProjectFile = Parameters.Project; if (Parameters.Project != null && !FileReference.Exists(ProjectFile)) { throw new AutomationException("Couldn't find project '{0}'", ProjectFile.FullName); } // Get the directories used for staging this project DirectoryReference SourceEngineDir = CommandUtils.EngineDirectory; DirectoryReference SourceProjectDir = (ProjectFile == null)? SourceEngineDir : ProjectFile.Directory; // Get the output directories. We flatten the directory structure on output. DirectoryReference TargetDir = Parameters.ToDir; DirectoryReference TargetEngineDir = DirectoryReference.Combine(TargetDir, "Engine"); DirectoryReference TargetProjectDir = DirectoryReference.Combine(TargetDir, ProjectFile.GetFileNameWithoutExtension()); // Get the path to the receipt FileReference ReceiptFileName = TargetReceipt.GetDefaultPath(SourceProjectDir, Parameters.Target, Parameters.Platform, Parameters.Configuration, Parameters.Architecture); // Try to load it TargetReceipt Receipt; if (!TargetReceipt.TryRead(ReceiptFileName, out Receipt)) { throw new AutomationException("Couldn't read receipt '{0}'", ReceiptFileName); } // Stage all the build products needed at runtime HashSet <FileReference> SourceFiles = new HashSet <FileReference>(); foreach (BuildProduct BuildProduct in Receipt.BuildProducts) { SourceFiles.Add(BuildProduct.Path); } foreach (RuntimeDependency RuntimeDependency in Receipt.RuntimeDependencies.Where(x => x.Type != StagedFileType.UFS)) { SourceFiles.Add(RuntimeDependency.Path); } // Get all the target files List <FileReference> TargetFiles = new List <FileReference>(); foreach (FileReference SourceFile in SourceFiles) { // Get the destination file to copy to, mapping to the new engine and project directories as appropriate FileReference TargetFile; if (SourceFile.IsUnderDirectory(SourceEngineDir)) { TargetFile = FileReference.Combine(TargetEngineDir, SourceFile.MakeRelativeTo(SourceEngineDir)); } else { TargetFile = FileReference.Combine(TargetProjectDir, SourceFile.MakeRelativeTo(SourceProjectDir)); } // Fixup the case of the output file. Would expect Platform.DeployLowerCaseFilenames() to return true here, but seems not to be the case. if (Parameters.Platform == UnrealTargetPlatform.PS4) { TargetFile = FileReference.Combine(TargetDir, TargetFile.MakeRelativeTo(TargetDir).ToLowerInvariant()); } // Only copy the output file if it doesn't already exist. We can stage multiple targets to the same output directory. if (Parameters.Overwrite || !FileReference.Exists(TargetFile)) { DirectoryReference.CreateDirectory(TargetFile.Directory); CommandUtils.CopyFile(SourceFile.FullName, TargetFile.FullName); // Force all destination files to not readonly. CommandUtils.SetFileAttributes(TargetFile.FullName, ReadOnly: false); } // Add it to the list of target files TargetFiles.Add(TargetFile); } // Apply the optional tag to the build products foreach (string TagName in FindTagNamesFromList(Parameters.Tag)) { FindOrAddTagSet(TagNameToFileSet, TagName).UnionWith(TargetFiles); } // Add the target file to the list of build products BuildProducts.UnionWith(TargetFiles); }
/// <summary> /// Applies the filter to each element in a sequence, and returns the list of files that match /// </summary> /// <param name="FileNames">List of filenames</param> /// <returns>List of filenames which match the filter</returns> public IEnumerable<FileReference> ApplyTo(DirectoryReference BaseDirectory, IEnumerable<FileReference> FileNames) { return FileNames.Where(x => Matches(x.MakeRelativeTo(BaseDirectory))); }
public override void ExecuteBuild() { // Get the plugin filename string PluginParam = ParseParamValue("Plugin"); if (PluginParam == null) { throw new AutomationException("Missing -Plugin=... argument"); } // Check it exists FileReference PluginFile = new FileReference(PluginParam); if (!FileReference.Exists(PluginFile)) { throw new AutomationException("Plugin '{0}' not found", PluginFile.FullName); } // Get the output directory string PackageParam = ParseParamValue("Package"); if (PackageParam == null) { throw new AutomationException("Missing -Package=... argument"); } // Make sure the packaging directory is valid DirectoryReference PackageDir = new DirectoryReference(PackageParam); if (PluginFile.IsUnderDirectory(PackageDir)) { throw new AutomationException("Packaged plugin output directory must be different to source"); } if (PackageDir.IsUnderDirectory(DirectoryReference.Combine(CommandUtils.RootDirectory, "Engine"))) { throw new AutomationException("Output directory for packaged plugin must be outside engine directory"); } // Clear the output directory of existing stuff if (DirectoryReference.Exists(PackageDir)) { CommandUtils.DeleteDirectoryContents(PackageDir.FullName); } else { DirectoryReference.CreateDirectory(PackageDir); } // Create a placeholder FilterPlugin.ini with instructions on how to use it FileReference SourceFilterFile = FileReference.Combine(PluginFile.Directory, "Config", "FilterPlugin.ini"); if (!FileReference.Exists(SourceFilterFile)) { List <string> Lines = new List <string>(); Lines.Add("[FilterPlugin]"); Lines.Add("; This section lists additional files which will be packaged along with your plugin. Paths should be listed relative to the root plugin directory, and"); Lines.Add("; may include \"...\", \"*\", and \"?\" wildcards to match directories, files, and individual characters respectively."); Lines.Add(";"); Lines.Add("; Examples:"); Lines.Add("; /README.txt"); Lines.Add("; /Extras/..."); Lines.Add("; /Binaries/ThirdParty/*.dll"); DirectoryReference.CreateDirectory(SourceFilterFile.Directory); CommandUtils.WriteAllLines_NoExceptions(SourceFilterFile.FullName, Lines.ToArray()); } // Create a host project for the plugin. For script generator plugins, we need to have UHT be able to load it, which can only happen if it's enabled in a project. FileReference HostProjectFile = FileReference.Combine(PackageDir, "HostProject", "HostProject.uproject"); FileReference HostProjectPluginFile = CreateHostProject(HostProjectFile, PluginFile); // Read the plugin CommandUtils.Log("Reading plugin from {0}...", HostProjectPluginFile); PluginDescriptor Plugin = PluginDescriptor.FromFile(HostProjectPluginFile, false); // Compile the plugin for all the target platforms List <UnrealTargetPlatform> HostPlatforms = ParseParam("NoHostPlatform")? new List <UnrealTargetPlatform>() : new List <UnrealTargetPlatform> { BuildHostPlatform.Current.Platform }; List <UnrealTargetPlatform> TargetPlatforms = GetTargetPlatforms(this, BuildHostPlatform.Current.Platform); FileReference[] BuildProducts = CompilePlugin(HostProjectFile, HostProjectPluginFile, Plugin, HostPlatforms, TargetPlatforms, ""); // Package up the final plugin data PackagePlugin(HostProjectPluginFile, BuildProducts, PackageDir); // Remove the host project if (!ParseParam("NoDeleteHostProject")) { CommandUtils.DeleteDirectory(HostProjectFile.Directory.FullName); } }
/// <summary> /// Finds a list of files within a given directory which match the filter. /// </summary> /// <param name="DirectoryName">File to match</param> /// <returns>List of files that pass the filter</returns> public List<FileReference> ApplyToDirectory(DirectoryReference DirectoryName, string PrefixPath, bool bIgnoreSymlinks) { List<FileReference> MatchingFileNames = new List<FileReference>(); FindMatchesFromDirectory(new DirectoryInfo(DirectoryName.FullName), PrefixPath.Replace('\\', '/').TrimEnd('/') + "/", bIgnoreSymlinks, MatchingFileNames); return MatchingFileNames; }
/// <summary> /// Generate HTML documentation for all the tasks /// </summary> /// <param name="NameToTask">Map of task name to implementation</param> /// <param name="OutputFile">Output file</param> static void GenerateDocumentation(Dictionary <string, ScriptTask> NameToTask, FileReference OutputFile) { // Find all the assemblies containing tasks Assembly[] TaskAssemblies = NameToTask.Values.Select(x => x.ParametersClass.Assembly).Distinct().ToArray(); // Read documentation for each of them Dictionary <string, XmlElement> MemberNameToElement = new Dictionary <string, XmlElement>(); foreach (Assembly TaskAssembly in TaskAssemblies) { string XmlFileName = Path.ChangeExtension(TaskAssembly.Location, ".xml"); if (File.Exists(XmlFileName)) { // Read the document XmlDocument Document = new XmlDocument(); Document.Load(XmlFileName); // Parse all the members, and add them to the map foreach (XmlElement Element in Document.SelectNodes("/doc/members/member")) { string Name = Element.GetAttribute("name"); MemberNameToElement.Add(Name, Element); } } } // Create the output directory DirectoryReference.CreateDirectory(OutputFile.Directory); FileReference.MakeWriteable(OutputFile); Log("Writing {0}...", OutputFile); // Parse the engine version BuildVersion Version; if (!BuildVersion.TryRead(out Version)) { throw new AutomationException("Couldn't read Build.version"); } // Write the output file using (StreamWriter Writer = new StreamWriter(OutputFile.FullName)) { Writer.WriteLine("Availability: NoPublish"); Writer.WriteLine("Title: BuildGraph Predefined Tasks"); Writer.WriteLine("Crumbs: %ROOT%, Programming, Programming/Development, Programming/Development/BuildGraph, Programming/Development/BuildGraph/BuildGraphScriptTasks"); Writer.WriteLine("Description: This is a procedurally generated markdown page."); Writer.WriteLine("version: {0}.{1}", Version.MajorVersion, Version.MinorVersion); Writer.WriteLine("parent:Programming/Development/BuildGraph/BuildGraphScriptTasks"); Writer.WriteLine(); foreach (string TaskName in NameToTask.Keys.OrderBy(x => x)) { // Get the task object ScriptTask Task = NameToTask[TaskName]; // Get the documentation for this task XmlElement TaskElement; if (MemberNameToElement.TryGetValue("T:" + Task.TaskClass.FullName, out TaskElement)) { // Write the task heading Writer.WriteLine("### {0}", TaskName); Writer.WriteLine(); Writer.WriteLine(ConvertToMarkdown(TaskElement.SelectSingleNode("summary"))); Writer.WriteLine(); // Document the parameters List <string[]> Rows = new List <string[]>(); foreach (string ParameterName in Task.NameToParameter.Keys) { // Get the parameter data ScriptTaskParameter Parameter = Task.NameToParameter[ParameterName]; // Get the documentation for this parameter XmlElement ParameterElement; if (MemberNameToElement.TryGetValue("F:" + Parameter.FieldInfo.DeclaringType.FullName + "." + Parameter.Name, out ParameterElement)) { string TypeName = Parameter.FieldInfo.FieldType.Name; if (Parameter.ValidationType != TaskParameterValidationType.Default) { StringBuilder NewTypeName = new StringBuilder(Parameter.ValidationType.ToString()); for (int Idx = 1; Idx < NewTypeName.Length; Idx++) { if (Char.IsLower(NewTypeName[Idx - 1]) && Char.IsUpper(NewTypeName[Idx])) { NewTypeName.Insert(Idx, ' '); } } TypeName = NewTypeName.ToString(); } string[] Columns = new string[4]; Columns[0] = ParameterName; Columns[1] = TypeName; Columns[2] = Parameter.bOptional? "Optional" : "Required"; Columns[3] = ConvertToMarkdown(ParameterElement.SelectSingleNode("summary")); Rows.Add(Columns); } } // Always include the "If" attribute string[] IfColumns = new string[4]; IfColumns[0] = "If"; IfColumns[1] = "Condition"; IfColumns[2] = "Optional"; IfColumns[3] = "Whether to execute this task. It is ignored if this condition evaluates to false."; Rows.Add(IfColumns); // Get the width of each column int[] Widths = new int[4]; for (int Idx = 0; Idx < 4; Idx++) { Widths[Idx] = Rows.Max(x => x[Idx].Length); } // Format the markdown table string Format = String.Format("| {{0,-{0}}} | {{1,-{1}}} | {{2,-{2}}} | {{3,-{3}}} |", Widths[0], Widths[1], Widths[2], Widths[3]); Writer.WriteLine(Format, "", "", "", ""); Writer.WriteLine(Format, new string('-', Widths[0]), new string('-', Widths[1]), new string('-', Widths[2]), new string('-', Widths[3])); for (int Idx = 0; Idx < Rows.Count; Idx++) { Writer.WriteLine(Format, Rows[Idx][0], Rows[Idx][1], Rows[Idx][2], Rows[Idx][3]); } // Blank line before next task Writer.WriteLine(); } } } }
/// <summary> /// Check for the default configuration /// return true if the project uses the default build config /// </summary> public override bool HasDefaultBuildConfig(UnrealTargetPlatform Platform, DirectoryReference ProjectDirectoryName) { string[] BoolKeys = new string[] { "bDevForArmV7", "bDevForArm64", "bDevForArmV7S", "bShipForArmV7", "bShipForArm64", "bShipForArmV7S", "bShipForBitcode", "bGeneratedSYMFile", "bGeneratedSYMBundle" }; string[] StringKeys = new string[] { "MinimumiOSVersion", "AdditionalLinkerFlags", "AdditionalShippingLinkerFlags" }; // look up iOS specific settings if (!DoProjectSettingsMatchDefault(Platform, ProjectDirectoryName, "/Script/IOSRuntimeSettings.IOSRuntimeSettings", BoolKeys, null, StringKeys)) { return false; } // check the base settings return base.HasDefaultBuildConfig(Platform, ProjectDirectoryName); }
static public IEnumerable<DirectoryReference> EnumerateDirectories(DirectoryReference Directory) { DirectoryCache FoundDirectoryCache = FindOrCreateDirectoryCache(Directory); return FoundDirectoryCache.EnumerateDirectories(); }
private static void FindOutputFilesHelper(HashSet<FileReference> OutputFiles, DirectoryReference BaseDir, string SearchPrefix, PhysXTargetLib TargetLib) { if(!BaseDir.Exists()) { return; } foreach (FileReference FoundFile in BaseDir.EnumerateFileReferences(SearchPrefix)) { string FileNameUpper = FoundFile.GetFileName().ToString().ToUpper(); bool bIncludeFile = false; if(TargetLib == PhysXTargetLib.APEX) { bIncludeFile = FileGeneratedByAPEX(FileNameUpper); } else { bIncludeFile = !FileGeneratedByAPEX(FileNameUpper); } if(bIncludeFile) { OutputFiles.Add(FoundFile); } } }
public virtual DirectoryReference GetProjectRootForStage(DirectoryReference RuntimeRoot, StagedDirectoryReference RelativeProjectRootForStage) { return(DirectoryReference.Combine(RuntimeRoot, RelativeProjectRootForStage.Name)); }
public virtual void GenerateGameProperties(UnrealTargetConfiguration Configuration, StringBuilder VCProjectFileContent, TargetRules.TargetType TargetType, DirectoryReference RootDirectory, FileReference TargetFilePath) { // Do nothing }
/// <summary> /// Finds all targets for the project. /// </summary> /// <param name="Properties">Project properties.</param> /// <param name="ExtraSearchPaths">Additional search paths.</param> private static void DetectTargetsForProject(ProjectProperties Properties, List <string> ExtraSearchPaths = null) { Properties.Targets = new Dictionary <TargetType, SingleTargetProperties>(); FileReference TargetsDllFilename; string FullProjectPath = null; var GameFolders = new List <DirectoryReference>(); var RulesFolder = new DirectoryReference(GetRulesAssemblyFolder()); if (Properties.RawProjectPath != null) { CommandUtils.LogVerbose("Looking for targets for project {0}", Properties.RawProjectPath); TargetsDllFilename = FileReference.Combine(RulesFolder, String.Format("UATRules{0}.dll", Properties.RawProjectPath.GetHashCode())); FullProjectPath = CommandUtils.GetDirectoryName(Properties.RawProjectPath.FullName); GameFolders.Add(new DirectoryReference(FullProjectPath)); CommandUtils.LogVerbose("Searching for target rule files in {0}", FullProjectPath); } else { TargetsDllFilename = FileReference.Combine(RulesFolder, String.Format("UATRules{0}.dll", "_BaseEngine_")); } // the UBT code assumes a certain CWD, but artists don't have this CWD. var SourceDir = CommandUtils.CombinePaths(CommandUtils.CmdEnv.LocalRoot, "Engine", "Source"); bool DirPushed = false; if (CommandUtils.DirectoryExists_NoExceptions(SourceDir)) { CommandUtils.PushDir(SourceDir); DirPushed = true; } var ExtraSearchDirectories = (ExtraSearchPaths == null)? null : ExtraSearchPaths.Select(x => new DirectoryReference(x)).ToList(); var TargetScripts = RulesCompiler.FindAllRulesSourceFiles(RulesCompiler.RulesFileType.Target, GameFolders: GameFolders, ForeignPlugins: null, AdditionalSearchPaths: ExtraSearchDirectories, bIncludeEnterprise: false); if (DirPushed) { CommandUtils.PopDir(); } if (!CommandUtils.IsNullOrEmpty(TargetScripts)) { // We only care about project target script so filter out any scripts not in the project folder, or take them all if we are just doing engine stuff var ProjectTargetScripts = new List <FileReference>(); foreach (var TargetScript in TargetScripts) { if (FullProjectPath == null || TargetScript.IsUnderDirectory(new DirectoryReference(FullProjectPath))) { ProjectTargetScripts.Add(TargetScript); } } TargetScripts = ProjectTargetScripts; } if (!CommandUtils.IsNullOrEmpty(TargetScripts)) { CommandUtils.LogVerbose("Found {0} target rule files:", TargetScripts.Count); foreach (var Filename in TargetScripts) { CommandUtils.LogVerbose(" {0}", Filename); } // Check if the scripts require compilation bool DoNotCompile = false; if (!CommandUtils.IsBuildMachine && !CheckIfScriptAssemblyIsOutOfDate(TargetsDllFilename, TargetScripts)) { Log.TraceVerbose("Targets DLL {0} is up to date.", TargetsDllFilename); DoNotCompile = true; } if (!DoNotCompile && CommandUtils.FileExists_NoExceptions(TargetsDllFilename.FullName)) { if (!CommandUtils.DeleteFile_NoExceptions(TargetsDllFilename.FullName, true)) { DoNotCompile = true; CommandUtils.LogVerbose("Could not delete {0} assuming it is up to date and reusable for a recursive UAT call.", TargetsDllFilename); } } CompileAndLoadTargetsAssembly(Properties, TargetsDllFilename, DoNotCompile, TargetScripts); } }
static public IEnumerable<DirectoryReference> EnumerateDirectoriesRecursively(DirectoryReference Directory) { DirectoryCache FoundDirectoryCache = FindOrCreateDirectoryCache(Directory); foreach (DirectoryReference SubDirectory in FoundDirectoryCache.EnumerateDirectories()) { yield return SubDirectory; foreach (DirectoryReference ChildSubDirectory in EnumerateDirectoriesRecursively(SubDirectory)) { yield return ChildSubDirectory; } } }
/// <summary> /// Execute the task. /// </summary> /// <param name="Job">Information about the current job</param> /// <param name="BuildProducts">Set of build products produced by this node.</param> /// <param name="TagNameToFileSet">Mapping from tag names to the set of files they include</param> /// <returns>True if the task succeeded</returns> public override bool Execute(JobContext Job, HashSet <FileReference> BuildProducts, Dictionary <string, HashSet <FileReference> > TagNameToFileSet) { // Set the Engine directory DirectoryReference EngineDir = DirectoryReference.Combine(CommandUtils.RootDirectory, "Engine"); if (!String.IsNullOrEmpty(Parameters.EngineDir)) { EngineDir = DirectoryReference.Combine(CommandUtils.RootDirectory, Parameters.EngineDir); } // Set the Project directory DirectoryReference ProjectDir = DirectoryReference.Combine(CommandUtils.RootDirectory, "Engine"); if (!String.IsNullOrEmpty(Parameters.ProjectDir)) { ProjectDir = DirectoryReference.Combine(CommandUtils.RootDirectory, Parameters.ProjectDir); } // Resolve the input list IEnumerable <FileReference> TargetFiles = ResolveFilespec(CommandUtils.RootDirectory, Parameters.Files, TagNameToFileSet); HashSet <FileReference> Files = new HashSet <FileReference>(); HashSet <string> WildcardDependencies = new HashSet <string>(); foreach (FileReference TargetFile in TargetFiles) { // check all files are .target files if (TargetFile.GetExtension() != ".target") { CommandUtils.LogError("Invalid file passed to TagReceipt task ({0})", TargetFile.FullName); continue; } // Read the receipt TargetReceipt Receipt; if (!TargetReceipt.TryRead(TargetFile.FullName, out Receipt)) { CommandUtils.LogWarning("Unable to load file using TagReceipt task ({0})", TargetFile.FullName); continue; } // Convert the paths to absolute Receipt.ExpandPathVariables(EngineDir, ProjectDir); if (Parameters.BuildProducts) { foreach (BuildProduct BuildProduct in Receipt.BuildProducts) { if (String.IsNullOrEmpty(Parameters.BuildProductType) || BuildProduct.Type == BuildProductType) { Files.Add(new FileReference(BuildProduct.Path)); } } } if (Parameters.RuntimeDependencies) { foreach (RuntimeDependency RuntimeDependency in Receipt.RuntimeDependencies) { if (String.IsNullOrEmpty(Parameters.StagedFileType) || RuntimeDependency.Type == StagedFileType) { // If it doesn't contain any wildcards, just add the pattern directly if (FileFilter.FindWildcardIndex(RuntimeDependency.Path) == -1) { // Only add files that exist as dependencies are assumed to always exist FileReference DependencyPath = new FileReference(RuntimeDependency.Path); if (FileReference.Exists(DependencyPath)) { Files.Add(DependencyPath); } else { // Give a warning about files that don't exist so that we can clean up build.cs files CommandUtils.LogWarning("File listed as RuntimeDependency in {0} does not exist ({1})", TargetFile.FullName, DependencyPath.FullName); } } else { WildcardDependencies.Add(RuntimeDependency.Path); } } } } if (Parameters.PrecompiledBuildDependencies) { foreach (string PrecompiledBuildDependency in Receipt.PrecompiledBuildDependencies) { // If it doesn't contain any wildcards, just add the pattern directly if (FileFilter.FindWildcardIndex(PrecompiledBuildDependency) == -1) { // Only add files that exist as dependencies are assumed to always exist FileReference DependencyPath = new FileReference(PrecompiledBuildDependency); if (FileReference.Exists(DependencyPath)) { Files.Add(DependencyPath); } else { // Give a warning about files that don't exist so that we can clean up build.cs files CommandUtils.LogWarning("File listed as PrecompiledBuildDependency in {0} does not exist ({1})", TargetFile.FullName, DependencyPath.FullName); } } else { WildcardDependencies.Add(PrecompiledBuildDependency); } } } if (Parameters.PrecompiledRuntimeDependencies) { foreach (string PrecompiledRuntimeDependency in Receipt.PrecompiledRuntimeDependencies) { // If it doesn't contain any wildcards, just add the pattern directly if (FileFilter.FindWildcardIndex(PrecompiledRuntimeDependency) == -1) { // Only add files that exist as dependencies are assumed to always exist FileReference DependencyPath = new FileReference(PrecompiledRuntimeDependency); if (FileReference.Exists(DependencyPath)) { Files.Add(DependencyPath); } else { // Give a warning about files that don't exist so that we can clean up build.cs files CommandUtils.LogWarning("File listed as PrecompiledRuntimeDependency in {0} does not exist ({1})", TargetFile.FullName, DependencyPath.FullName); } } else { WildcardDependencies.Add(PrecompiledRuntimeDependency); } } } } // Turn any wildcards into a file list Files.UnionWith(ResolveFilespecWithExcludePatterns(CommandUtils.RootDirectory, WildcardDependencies.ToList(), new List <string>(), TagNameToFileSet)); // Apply the tag to all the matching files FindOrAddTagSet(TagNameToFileSet, Parameters.With).UnionWith(Files); return(true); }
static List <BuildProduct> GetBuildProductsFromReceipts(DirectoryReference EngineDir, DirectoryReference ProjectDir, List <string> ReceiptFileNames) { List <BuildProduct> BuildProducts = new List <BuildProduct>(); foreach (string ReceiptFileName in ReceiptFileNames) { TargetReceipt Receipt; if (!TargetReceipt.TryRead(ReceiptFileName, out Receipt)) { throw new AutomationException("Missing or invalid target receipt ({0})", ReceiptFileName); } Receipt.ExpandPathVariables(EngineDir, ProjectDir); BuildProducts.AddRange(Receipt.BuildProducts); } return(BuildProducts); }
/// <summary> /// Execute the task. /// </summary> /// <param name="Job">Information about the current job</param> /// <param name="BuildProducts">Set of build products produced by this node.</param> /// <param name="TagNameToFileSet">Mapping from tag names to the set of files they include</param> public override void Execute(JobContext Job, HashSet <FileReference> BuildProducts, Dictionary <string, HashSet <FileReference> > TagNameToFileSet) { // Parse all the source patterns FilePattern SourcePattern = new FilePattern(CommandUtils.RootDirectory, Parameters.From); // Parse the target pattern FilePattern TargetPattern = new FilePattern(CommandUtils.RootDirectory, Parameters.To); // Apply the filter to the source files HashSet <FileReference> Files = null; if (!String.IsNullOrEmpty(Parameters.Files)) { SourcePattern = SourcePattern.AsDirectoryPattern(); Files = ResolveFilespec(SourcePattern.BaseDirectory, Parameters.Files, TagNameToFileSet); } // Build the file mapping Dictionary <FileReference, FileReference> TargetFileToSourceFile = FilePattern.CreateMapping(Files, ref SourcePattern, ref TargetPattern); // If we're not overwriting, remove any files where the destination file already exists. if (!Parameters.Overwrite) { TargetFileToSourceFile = TargetFileToSourceFile.Where(File => { if (FileReference.Exists(File.Key)) { CommandUtils.Log("Not copying existing file {0}", File.Key); return(false); } return(true); }).ToDictionary(Pair => Pair.Key, Pair => Pair.Value); } // Check we got some files if (TargetFileToSourceFile.Count == 0) { CommandUtils.Log("No files found matching '{0}'", SourcePattern); return; } // If the target is on a network share, retry creating the first directory until it succeeds DirectoryReference FirstTargetDirectory = TargetFileToSourceFile.First().Key.Directory; if (!DirectoryReference.Exists(FirstTargetDirectory)) { const int MaxNumRetries = 15; for (int NumRetries = 0;; NumRetries++) { try { DirectoryReference.CreateDirectory(FirstTargetDirectory); if (NumRetries == 1) { Log.TraceInformation("Created target directory {0} after 1 retry.", FirstTargetDirectory); } else if (NumRetries > 1) { Log.TraceInformation("Created target directory {0} after {1} retries.", FirstTargetDirectory, NumRetries); } break; } catch (Exception Ex) { if (NumRetries == 0) { Log.TraceInformation("Unable to create directory '{0}' on first attempt. Retrying {1} times...", FirstTargetDirectory, MaxNumRetries); } Log.TraceLog(" {0}", Ex); if (NumRetries >= 15) { throw new AutomationException(Ex, "Unable to create target directory '{0}' after {1} retries.", FirstTargetDirectory, NumRetries); } Thread.Sleep(2000); } } } // Copy them all KeyValuePair <FileReference, FileReference>[] FilePairs = TargetFileToSourceFile.ToArray(); CommandUtils.Log("Copying {0} file{1} from {2} to {3}...", FilePairs.Length, (FilePairs.Length == 1)? "" : "s", SourcePattern.BaseDirectory, TargetPattern.BaseDirectory); CommandUtils.ThreadedCopyFiles(FilePairs.Select(x => x.Value.FullName).ToList(), FilePairs.Select(x => x.Key.FullName).ToList(), bQuiet: true); // Update the list of build products BuildProducts.UnionWith(TargetFileToSourceFile.Keys); // Apply the optional output tag to them foreach (string TagName in FindTagNamesFromList(Parameters.Tag)) { FindOrAddTagSet(TagNameToFileSet, TagName).UnionWith(TargetFileToSourceFile.Keys); } }
static public bool DirectoryExists(DirectoryReference Directory) { DirectoryCache FoundDirectoryCache = FindOrCreateDirectoryCache(Directory); return FoundDirectoryCache.Exists; }
static void PackagePlugin(FileReference SourcePluginFile, IEnumerable <FileReference> BuildProducts, DirectoryReference TargetDir) { DirectoryReference SourcePluginDir = SourcePluginFile.Directory; // Copy all the files to the output directory FileReference[] SourceFiles = FilterPluginFiles(SourcePluginFile, BuildProducts).ToArray(); foreach (FileReference SourceFile in SourceFiles) { FileReference TargetFile = FileReference.Combine(TargetDir, SourceFile.MakeRelativeTo(SourcePluginDir)); CommandUtils.CopyFile(SourceFile.FullName, TargetFile.FullName); CommandUtils.SetFileAttributes(TargetFile.FullName, ReadOnly: false); } // Get the output plugin filename FileReference TargetPluginFile = FileReference.Combine(TargetDir, SourcePluginFile.GetFileName()); PluginDescriptor NewDescriptor = PluginDescriptor.FromFile(TargetPluginFile, false); NewDescriptor.bEnabledByDefault = false; NewDescriptor.bInstalled = true; NewDescriptor.Save(TargetPluginFile.FullName, false); }
/// <summary> /// UBT startup order is fairly fragile, and relies on globals that may or may not be safe to use yet. /// This function is for super early startup stuff that should not access Configuration classes (anything loaded by XmlConfg). /// This should be very minimal startup code. /// </summary> /// <param name="Arguments">Cmdline arguments</param> private static void DoStartupStuffThatCannotAccessConfigurationClasses(string[] Arguments) { // Helpers used for stats tracking. StartTime = DateTime.UtcNow; // Do super early log init as a safeguard. We'll re-init with proper config options later. PreInitLogging(); // ensure we can resolve any external assemblies that are not in the same folder as our assembly. AssemblyUtils.InstallAssemblyResolver(Path.GetDirectoryName(Assembly.GetEntryAssembly().GetOriginalLocation())); // Copy off the arguments to allow checking for command-line arguments elsewhere CmdLine = new List<string>(Arguments); // Grab the environment. InitialEnvironment = Environment.GetEnvironmentVariables(); if (InitialEnvironment.Count < 1) { throw new BuildException("Environment could not be read"); } // Change the working directory to be the Engine/Source folder. We are likely running from Engine/Binaries/DotNET // This is critical to be done early so any code that relies on the current directory being Engine/Source will work. // UEBuildConfiguration.PostReset is susceptible to this, so we must do this before configs are loaded. string EngineSourceDirectory = Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().GetOriginalLocation()), "..", "..", "..", "Engine", "Source"); //@todo.Rocket: This is a workaround for recompiling game code in editor // The working directory when launching is *not* what we would expect if (Directory.Exists(EngineSourceDirectory) == false) { // We are assuming UBT always runs from <>/Engine/Binaries/DotNET/... EngineSourceDirectory = Assembly.GetExecutingAssembly().GetOriginalLocation(); EngineSourceDirectory = EngineSourceDirectory.Replace("\\", "/"); Int32 EngineIdx = EngineSourceDirectory.IndexOf("/Engine/Binaries/DotNET/", StringComparison.InvariantCultureIgnoreCase); if (EngineIdx != 0) { EngineSourceDirectory = Path.Combine(EngineSourceDirectory.Substring(0, EngineIdx), "Engine", "Source"); } } if (Directory.Exists(EngineSourceDirectory)) // only set the directory if it exists, this should only happen if we are launching the editor from an artist sync { Directory.SetCurrentDirectory(EngineSourceDirectory); } }
private static bool RequiresTempTarget(FileReference RawProjectPath, List <UnrealTargetPlatform> ClientTargetPlatforms, bool AssetNativizationRequested) { // check to see if we already have a Target.cs file if (File.Exists(Path.Combine(Path.GetDirectoryName(RawProjectPath.FullName), "Source", RawProjectPath.GetFileNameWithoutExtension() + ".Target.cs"))) { return(false); } else if (Directory.Exists(Path.Combine(Path.GetDirectoryName(RawProjectPath.FullName), "Source"))) { // wasn't one in the main Source directory, let's check all sub-directories //@todo: may want to read each target.cs to see if it has a target corresponding to the project name as a final check FileInfo[] Files = (new DirectoryInfo(Path.Combine(Path.GetDirectoryName(RawProjectPath.FullName), "Source")).GetFiles("*.Target.cs", SearchOption.AllDirectories)); if (Files.Length > 0) { return(false); } } // // once we reach this point, we can surmise that this is an asset- // only (code free) project if (AssetNativizationRequested) { // we're going to be converting some of the project's assets // into native code, so we require a distinct target (executable) // be generated for this project return(true); } if (ClientTargetPlatforms != null) { foreach (UnrealTargetPlatform ClientPlatform in ClientTargetPlatforms) { EncryptionAndSigning.CryptoSettings Settings = EncryptionAndSigning.ParseCryptoSettings(RawProjectPath.Directory, ClientPlatform); if (Settings.IsAnyEncryptionEnabled() || Settings.bEnablePakSigning) { return(true); } } } // no Target file, now check to see if build settings have changed List <UnrealTargetPlatform> TargetPlatforms = ClientTargetPlatforms; if (ClientTargetPlatforms == null || ClientTargetPlatforms.Count < 1) { // No client target platforms, add all in TargetPlatforms = new List <UnrealTargetPlatform>(); foreach (UnrealTargetPlatform TargetPlatformType in Enum.GetValues(typeof(UnrealTargetPlatform))) { if (TargetPlatformType != UnrealTargetPlatform.Unknown) { TargetPlatforms.Add(TargetPlatformType); } } } // Change the working directory to be the Engine/Source folder. We are running from Engine/Binaries/DotNET DirectoryReference oldCWD = DirectoryReference.GetCurrentDirectory(); try { DirectoryReference EngineSourceDirectory = DirectoryReference.Combine(CommandUtils.EngineDirectory, "Source"); if (!DirectoryReference.Exists(EngineSourceDirectory)) // only set the directory if it exists, this should only happen if we are launching the editor from an artist sync { EngineSourceDirectory = DirectoryReference.Combine(CommandUtils.EngineDirectory, "Binaries"); } Directory.SetCurrentDirectory(EngineSourceDirectory.FullName); // Read the project descriptor, and find all the plugins available to this project ProjectDescriptor Project = ProjectDescriptor.FromFile(RawProjectPath); List <PluginInfo> AvailablePlugins = Plugins.ReadAvailablePlugins(CommandUtils.EngineDirectory, RawProjectPath, Project.AdditionalPluginDirectories); // check the target platforms for any differences in build settings or additional plugins bool RetVal = false; foreach (UnrealTargetPlatform TargetPlatformType in TargetPlatforms) { if (!Automation.IsEngineInstalled() && !PlatformExports.HasDefaultBuildConfig(RawProjectPath, TargetPlatformType)) { RetVal = true; break; } // find if there are any plugins enabled or disabled which differ from the default foreach (PluginInfo Plugin in AvailablePlugins) { bool bPluginEnabledForProject = Plugins.IsPluginEnabledForProject(Plugin, Project, TargetPlatformType, TargetType.Game); if ((bPluginEnabledForProject != Plugin.EnabledByDefault) || (bPluginEnabledForProject && Plugin.Descriptor.bInstalled)) { // NOTE: this code was only marking plugins that compiled for the platform to upgrade to code project, however // this doesn't work in practice, because the runtime code will look for the plugin, without a .uplugin file, // and will fail. This is the safest way to make sure all platforms are acting the same. However, if you // whitelist the plugin in the .uproject file, the above UProjectInfo.IsPluginEnabledForProject check won't pass // so you won't get in here. Leaving this commented out code in there, because someone is bound to come looking // for why a non-whitelisted platform module is causing a project to convert to code-based. // As an aside, if you run the project with UE4Game (not your Project's binary) from the debugger, it will work // _in this case_ because the .uplugin file will have been staged, and there is no needed library // if(Plugin.Descriptor.Modules.Any(Module => Module.IsCompiledInConfiguration(TargetPlatformType, TargetType.Game, bBuildDeveloperTools: false, bBuildEditor: false))) { RetVal = true; break; } } } } return(RetVal); } finally { // Change back to the original directory Directory.SetCurrentDirectory(oldCWD.FullName); } }