/// <summary> /// Discover and fill in the project info /// </summary> public static void FillProjectInfo() { DateTime StartTime = DateTime.Now; List <DirectoryReference> DirectoriesToSearch = new List <DirectoryReference>(); // Find all the .uprojectdirs files contained in the root folder and add their entries to the search array string EngineSourceDirectory = Path.GetFullPath(Path.Combine(RootDirectory, "Engine", "Source")); foreach (FileReference ProjectDirsFile in DirectoryReference.EnumerateFiles(UnrealBuildTool.RootDirectory, "*.uprojectdirs", SearchOption.TopDirectoryOnly)) { Log.TraceVerbose("\tFound uprojectdirs file {0}", ProjectDirsFile.FullName); foreach (string Line in File.ReadAllLines(ProjectDirsFile.FullName)) { string TrimLine = Line.Trim(); if (!TrimLine.StartsWith(";")) { DirectoryReference BaseProjectDir = DirectoryReference.Combine(UnrealBuildTool.RootDirectory, TrimLine); if (BaseProjectDir.IsUnderDirectory(UnrealBuildTool.RootDirectory)) { DirectoriesToSearch.Add(BaseProjectDir); } else { Log.TraceWarning("Project search path '{0}' is not under root directory, ignoring.", TrimLine); } } } } Log.TraceVerbose("\tFound {0} directories to search", DirectoriesToSearch.Count); foreach (DirectoryReference DirToSearch in DirectoriesToSearch) { Log.TraceVerbose("\t\tSearching {0}", DirToSearch.FullName); if (DirectoryReference.Exists(DirToSearch)) { foreach (DirectoryReference SubDir in DirectoryReference.EnumerateDirectories(DirToSearch, "*", SearchOption.TopDirectoryOnly)) { Log.TraceVerbose("\t\t\tFound subdir {0}", SubDir.FullName); foreach (FileReference UProjFile in DirectoryReference.EnumerateFiles(SubDir, "*.uproject", SearchOption.TopDirectoryOnly)) { Log.TraceVerbose("\t\t\t\t{0}", UProjFile.FullName); AddProject(UProjFile); } } } else { Log.TraceVerbose("ProjectInfo: Skipping directory {0} from .uprojectdirs file as it doesn't exist.", DirToSearch); } } DateTime StopTime = DateTime.Now; if (UnrealBuildTool.bPrintPerformanceInfo) { TimeSpan TotalProjectInfoTime = StopTime - StartTime; Log.TraceInformation("FillProjectInfo took {0} milliseconds", TotalProjectInfoTime.TotalMilliseconds); } }
/// <summary> /// Sets the Visual C++ INCLUDE environment variable /// </summary> static List <string> GetVisualCppIncludePaths(WindowsCompiler Compiler, DirectoryReference VisualCppDir, DirectoryReference VisualCppToolchainDir, string UniversalCRTDir, string UniversalCRTVersion, string NetFXSDKDir, string WindowsSDKDir, string WindowsSDKLibVersion) { List <string> IncludePaths = new List <string>(); // Add the standard Visual C++ include paths if (Compiler == WindowsCompiler.VisualStudio2017) { DirectoryReference StdIncludeDir = DirectoryReference.Combine(VisualCppToolchainDir, "INCLUDE"); if (DirectoryReference.Exists(StdIncludeDir)) { IncludePaths.Add(StdIncludeDir.FullName); } DirectoryReference AtlMfcIncludeDir = DirectoryReference.Combine(VisualCppToolchainDir, "ATLMFC", "INCLUDE"); if (DirectoryReference.Exists(AtlMfcIncludeDir)) { IncludePaths.Add(AtlMfcIncludeDir.FullName); } } else { DirectoryReference StdIncludeDir = DirectoryReference.Combine(VisualCppDir, "INCLUDE"); if (DirectoryReference.Exists(StdIncludeDir)) { IncludePaths.Add(StdIncludeDir.FullName); } DirectoryReference AtlMfcIncludeDir = DirectoryReference.Combine(VisualCppDir, "ATLMFC", "INCLUDE"); if (DirectoryReference.Exists(AtlMfcIncludeDir)) { IncludePaths.Add(AtlMfcIncludeDir.FullName); } } // Add the universal CRT paths if (!String.IsNullOrEmpty(UniversalCRTDir) && !String.IsNullOrEmpty(UniversalCRTVersion)) { IncludePaths.Add(Path.Combine(UniversalCRTDir, "include", UniversalCRTVersion, "ucrt")); } // Add the NETFXSDK include path if (!String.IsNullOrEmpty(NetFXSDKDir)) { IncludePaths.Add(Path.Combine(NetFXSDKDir, "include", "um")); // 2015 } // Add the Windows SDK paths if (Compiler >= WindowsCompiler.VisualStudio2015 && WindowsPlatform.bUseWindowsSDK10) { IncludePaths.Add(Path.Combine(WindowsSDKDir, "include", WindowsSDKLibVersion, "shared")); IncludePaths.Add(Path.Combine(WindowsSDKDir, "include", WindowsSDKLibVersion, "um")); IncludePaths.Add(Path.Combine(WindowsSDKDir, "include", WindowsSDKLibVersion, "winrt")); } else { IncludePaths.Add(Path.Combine(WindowsSDKDir, "include", "shared")); IncludePaths.Add(Path.Combine(WindowsSDKDir, "include", "um")); IncludePaths.Add(Path.Combine(WindowsSDKDir, "include", "winrt")); } // Add the existing include paths string ExistingIncludePaths = Environment.GetEnvironmentVariable("INCLUDE"); if (ExistingIncludePaths != null) { IncludePaths.AddRange(ExistingIncludePaths.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries)); } // Set the environment variable return(IncludePaths); }
/// <summary> /// Sets the Visual C++ LIB environment variable /// </summary> static List <string> GetVisualCppLibraryPaths(WindowsCompiler Compiler, DirectoryReference VisualCppDir, DirectoryReference VisualCppToolchainDir, string UniversalCRTDir, string UniversalCRTVersion, string NetFXSDKDir, string WindowsSDKDir, string WindowsSDKLibVersion, CppPlatform Platform) { List <string> LibraryPaths = new List <string>(); // Add the standard Visual C++ library paths if (Compiler == WindowsCompiler.VisualStudio2017) { if (Platform == CppPlatform.Win32) { DirectoryReference StdLibraryDir = DirectoryReference.Combine(VisualCppToolchainDir, "lib", "x86"); if (DirectoryReference.Exists(StdLibraryDir)) { LibraryPaths.Add(StdLibraryDir.FullName); } } else { DirectoryReference StdLibraryDir = DirectoryReference.Combine(VisualCppToolchainDir, "lib", "x64"); if (DirectoryReference.Exists(StdLibraryDir)) { LibraryPaths.Add(StdLibraryDir.FullName); } } } else { if (Platform == CppPlatform.Win32) { DirectoryReference StdLibraryDir = DirectoryReference.Combine(VisualCppDir, "LIB"); if (DirectoryReference.Exists(StdLibraryDir)) { LibraryPaths.Add(StdLibraryDir.FullName); } DirectoryReference AtlMfcLibraryDir = DirectoryReference.Combine(VisualCppDir, "ATLMFC", "LIB"); if (DirectoryReference.Exists(AtlMfcLibraryDir)) { LibraryPaths.Add(AtlMfcLibraryDir.FullName); } } else { DirectoryReference StdLibraryDir = DirectoryReference.Combine(VisualCppDir, "LIB", "amd64"); if (DirectoryReference.Exists(StdLibraryDir)) { LibraryPaths.Add(StdLibraryDir.FullName); } DirectoryReference AtlMfcLibraryDir = DirectoryReference.Combine(VisualCppDir, "ATLMFC", "LIB", "amd64"); if (DirectoryReference.Exists(AtlMfcLibraryDir)) { LibraryPaths.Add(AtlMfcLibraryDir.FullName); } } } // Add the Universal CRT if (!String.IsNullOrEmpty(UniversalCRTDir) && !String.IsNullOrEmpty(UniversalCRTVersion)) { if (Platform == CppPlatform.Win32) { LibraryPaths.Add(Path.Combine(UniversalCRTDir, "lib", UniversalCRTVersion, "ucrt", "x86")); } else { LibraryPaths.Add(Path.Combine(UniversalCRTDir, "lib", UniversalCRTVersion, "ucrt", "x64")); } } // Add the NETFXSDK include path if (!String.IsNullOrEmpty(NetFXSDKDir)) { if (Platform == CppPlatform.Win32) { LibraryPaths.Add(Path.Combine(NetFXSDKDir, "lib", "um", "x86")); } else { LibraryPaths.Add(Path.Combine(NetFXSDKDir, "lib", "um", "x64")); } } // Add the standard Windows SDK paths if (Platform == CppPlatform.Win32) { LibraryPaths.Add(Path.Combine(WindowsSDKDir, "lib", WindowsSDKLibVersion, "um", "x86")); } else { LibraryPaths.Add(Path.Combine(WindowsSDKDir, "lib", WindowsSDKLibVersion, "um", "x64")); } // Add the existing library paths string ExistingLibraryPaths = Environment.GetEnvironmentVariable("LIB"); if (ExistingLibraryPaths != null) { LibraryPaths.AddRange(ExistingLibraryPaths.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries)); } return(LibraryPaths); }
/// <summary> /// /// </summary> /// <param name="RulesFileType"></param> /// <param name="GameFolders"></param> /// <param name="ForeignPlugins"></param> /// <param name="AdditionalSearchPaths"></param> /// <param name="bIncludeEngine"></param> /// <param name="bIncludeEnterprise"></param> /// <returns></returns> public static List <FileReference> FindAllRulesSourceFiles(RulesFileType RulesFileType, List <DirectoryReference> GameFolders, List <FileReference> ForeignPlugins, List <DirectoryReference> AdditionalSearchPaths, bool bIncludeEngine = true, bool bIncludeEnterprise = true) { List <DirectoryReference> Folders = new List <DirectoryReference>(); // Add all engine source (including third party source) if (bIncludeEngine) { Folders.Add(UnrealBuildTool.EngineSourceDirectory); } if (bIncludeEnterprise) { Folders.Add(UnrealBuildTool.EnterpriseSourceDirectory); } // @todo plugin: Disallow modules from including plugin modules as dependency modules? (except when the module is part of that plugin) // Get all the root folders for plugins List <DirectoryReference> RootFolders = new List <DirectoryReference>(); if (bIncludeEngine) { RootFolders.Add(UnrealBuildTool.EngineDirectory); } if (bIncludeEnterprise) { RootFolders.Add(UnrealBuildTool.EnterpriseDirectory); } if (GameFolders != null) { RootFolders.AddRange(GameFolders); } // Find all the plugin source directories foreach (DirectoryReference RootFolder in RootFolders) { DirectoryReference PluginsFolder = DirectoryReference.Combine(RootFolder, "Plugins"); foreach (FileReference PluginFile in Plugins.EnumeratePlugins(PluginsFolder)) { Folders.Add(DirectoryReference.Combine(PluginFile.Directory, "Source")); } } // Add all the extra plugin folders if (ForeignPlugins != null) { foreach (FileReference ForeignPlugin in ForeignPlugins) { Folders.Add(DirectoryReference.Combine(ForeignPlugin.Directory, "Source")); } } // Add in the game folders to search if (GameFolders != null) { foreach (DirectoryReference GameFolder in GameFolders) { DirectoryReference GameSourceFolder = DirectoryReference.Combine(GameFolder, "Source"); Folders.Add(GameSourceFolder); DirectoryReference GameIntermediateSourceFolder = DirectoryReference.Combine(GameFolder, "Intermediate", "Source"); Folders.Add(GameIntermediateSourceFolder); } } // Process the additional search path, if sent in if (AdditionalSearchPaths != null) { foreach (DirectoryReference AdditionalSearchPath in AdditionalSearchPaths) { if (AdditionalSearchPath != null) { if (DirectoryReference.Exists(AdditionalSearchPath)) { Folders.Add(AdditionalSearchPath); } else { throw new BuildException("Couldn't find AdditionalSearchPath for rules source files '{0}'", AdditionalSearchPath); } } } } // Iterate over all the folders to check List <FileReference> SourceFiles = new List <FileReference>(); HashSet <FileReference> UniqueSourceFiles = new HashSet <FileReference>(); foreach (DirectoryReference Folder in Folders) { IReadOnlyList <FileReference> SourceFilesForFolder = FindAllRulesFiles(Folder, RulesFileType); foreach (FileReference SourceFile in SourceFilesForFolder) { if (UniqueSourceFiles.Add(SourceFile)) { SourceFiles.Add(SourceFile); } } } return(SourceFiles); }
/// <summary> /// Checks if the editor is currently running and this is a hot-reload /// </summary> public static bool ShouldDoHotReloadFromIDE(BuildConfiguration BuildConfiguration, TargetDescriptor TargetDesc) { // Check if Hot-reload is disabled globally for this project ConfigHierarchy Hierarchy = ConfigCache.ReadHierarchy(ConfigHierarchyType.Engine, DirectoryReference.FromFile(TargetDesc.ProjectFile), TargetDesc.Platform); bool bAllowHotReloadFromIDE; if (Hierarchy.TryGetValue("BuildConfiguration", "bAllowHotReloadFromIDE", out bAllowHotReloadFromIDE) && !bAllowHotReloadFromIDE) { return(false); } if (!BuildConfiguration.bAllowHotReloadFromIDE) { return(false); } // Check if we're using LiveCode instead ConfigHierarchy EditorPerProjectHierarchy = ConfigCache.ReadHierarchy(ConfigHierarchyType.EditorPerProjectUserSettings, DirectoryReference.FromFile(TargetDesc.ProjectFile), TargetDesc.Platform); bool bEnableLiveCode; if (EditorPerProjectHierarchy.GetBool("/Script/LiveCoding.LiveCodingSettings", "bEnabled", out bEnableLiveCode) && bEnableLiveCode) { return(false); } bool bIsRunning = false; // @todo ubtmake: Kind of cheating here to figure out if an editor target. At this point we don't have access to the actual target description, and // this code must be able to execute before we create or load module rules DLLs so that hot reload can work with bUseUBTMakefiles if (TargetDesc.Name.EndsWith("Editor", StringComparison.OrdinalIgnoreCase)) { string EditorBaseFileName = "UE4Editor"; if (TargetDesc.Configuration != UnrealTargetConfiguration.Development) { EditorBaseFileName = String.Format("{0}-{1}-{2}", EditorBaseFileName, TargetDesc.Platform, TargetDesc.Configuration); } FileReference EditorLocation; if (TargetDesc.Platform == UnrealTargetPlatform.Win64) { EditorLocation = FileReference.Combine(UnrealBuildTool.EngineDirectory, "Binaries", "Win64", String.Format("{0}.exe", EditorBaseFileName)); } else if (TargetDesc.Platform == UnrealTargetPlatform.Mac) { EditorLocation = FileReference.Combine(UnrealBuildTool.EngineDirectory, "Binaries", "Mac", String.Format("{0}.app/Contents/MacOS/{0}", EditorBaseFileName)); } else if (TargetDesc.Platform == UnrealTargetPlatform.Linux) { EditorLocation = FileReference.Combine(UnrealBuildTool.EngineDirectory, "Binaries", "Linux", EditorBaseFileName); } else { throw new BuildException("Unknown editor filename for this platform"); } using (Timeline.ScopeEvent("Finding editor processes for hot-reload")) { DirectoryReference EditorRunsDir = DirectoryReference.Combine(UnrealBuildTool.EngineDirectory, "Intermediate", "EditorRuns"); if (!DirectoryReference.Exists(EditorRunsDir)) { return(false); } if (BuildHostPlatform.Current.Platform == UnrealTargetPlatform.Win64) { foreach (FileReference EditorInstanceFile in DirectoryReference.EnumerateFiles(EditorRunsDir)) { int ProcessId; if (!Int32.TryParse(EditorInstanceFile.GetFileName(), out ProcessId)) { FileReference.Delete(EditorInstanceFile); continue; } Process RunningProcess; try { RunningProcess = Process.GetProcessById(ProcessId); } catch { RunningProcess = null; } if (RunningProcess == null) { FileReference.Delete(EditorInstanceFile); continue; } FileReference MainModuleFile; try { MainModuleFile = new FileReference(RunningProcess.MainModule.FileName); } catch { MainModuleFile = null; } if (!bIsRunning && EditorLocation == MainModuleFile) { bIsRunning = true; } } } else { FileInfo[] EditorRunsFiles = new DirectoryInfo(EditorRunsDir.FullName).GetFiles(); BuildHostPlatform.ProcessInfo[] Processes = BuildHostPlatform.Current.GetProcesses(); foreach (FileInfo File in EditorRunsFiles) { int PID; BuildHostPlatform.ProcessInfo Proc = null; if (!Int32.TryParse(File.Name, out PID) || (Proc = Processes.FirstOrDefault(P => P.PID == PID)) == default(BuildHostPlatform.ProcessInfo)) { // Delete stale files (it may happen if editor crashes). File.Delete(); continue; } // Don't break here to allow clean-up of other stale files. if (!bIsRunning) { // Otherwise check if the path matches. bIsRunning = new FileReference(Proc.Filename) == EditorLocation; } } } } } return(bIsRunning); }
public override bool ExecuteActions(List <Action> Actions, bool bLogDetailedActionStats) { if (Actions.Count == 0) { return(true); } // Clean the intermediate directory in case there are any leftovers from previous builds if (DirectoryReference.Exists(IntermediateDir)) { DirectoryReference.Delete(IntermediateDir, true); } DirectoryReference.CreateDirectory(IntermediateDir); if (!DirectoryReference.Exists(IntermediateDir)) { throw new BuildException($"Failed to create directory \"{IntermediateDir}\"."); } // Build the json script file to describe all the actions and their dependencies var ActionIds = Actions.ToDictionary(a => a, a => Guid.NewGuid().ToString()); File.WriteAllText(ScriptFile.FullName, Json.Serialize(new Dictionary <string, object>() { ["jobs"] = Actions.ToDictionary(a => ActionIds[a], a => { var Job = new Dictionary <string, object>() { ["title"] = a.StatusDescription, ["command"] = $"\"{a.CommandPath}\" {a.CommandArguments}", ["working_directory"] = a.WorkingDirectory.FullName, ["dependencies"] = a.PrerequisiteActions.Select(p => ActionIds[p]).ToArray(), ["run_locally"] = !(a.bCanExecuteRemotely && a.bCanExecuteRemotelyWithSNDBS) }; if (a.PrerequisiteItems.Count > 0) { Job["explicit_input_files"] = a.PrerequisiteItems.Select(i => new Dictionary <string, object>() { ["filename"] = i.AbsolutePath }).ToList(); } if (EnableEcho) { var EchoString = string.Join(" ", string.IsNullOrWhiteSpace(a.CommandDescription) ? string.Empty : $"[{a.CommandDescription}]", a.StatusDescription); if (!string.IsNullOrWhiteSpace(EchoString)) { Job["echo"] = EchoString; } } return(Job); }) })); PrepareToolTemplates(); bool bHasRewrites = GenerateSNDBSIncludeRewriteRules(); var LocalProcess = new Process(); LocalProcess.StartInfo = new ProcessStartInfo(SNDBSExecutable, $"-q -p \"Unreal Engine Tasks\" -s \"{ScriptFile}\" -templates \"{IntermediateDir}\"{(bHasRewrites ? $" --include-rewrite-rules \"{IncludeRewriteRulesFile}\"" : "")}"); LocalProcess.OutputDataReceived += (Sender, Args) => Log.TraceInformation("{0}", Args.Data); LocalProcess.ErrorDataReceived += (Sender, Args) => Log.TraceInformation("{0}", Args.Data); return(Utils.RunLocalProcess(LocalProcess) == 0); }
/// <summary> /// Creates an environment with the given settings /// </summary> /// <param name="Compiler">The compiler version to use</param> /// <param name="Platform">The platform to target</param> /// <param name="Architecture">The Architecture to target</param> /// <param name="CompilerVersion">The specific toolchain version to use</param> /// <param name="WindowsSdkVersion">Version of the Windows SDK to use</param> /// <param name="SuppliedSdkDirectoryForVersion">If specified, this is the SDK directory to use, otherwise, attempt to look up via registry. If specified, the WindowsSdkVersion is used directly</param> /// <returns>New environment object with paths for the given settings</returns> public static VCEnvironment Create(WindowsCompiler Compiler, UnrealTargetPlatform Platform, WindowsArchitecture Architecture, string CompilerVersion, string WindowsSdkVersion, string SuppliedSdkDirectoryForVersion) { // Get the compiler version info VersionNumber SelectedCompilerVersion; DirectoryReference SelectedCompilerDir; if (!WindowsPlatform.TryGetToolChainDir(Compiler, CompilerVersion, out SelectedCompilerVersion, out SelectedCompilerDir)) { throw new BuildException("{0}{1} must be installed in order to build this target.", WindowsPlatform.GetCompilerName(Compiler), String.IsNullOrEmpty(CompilerVersion)? "" : String.Format(" ({0})", CompilerVersion)); } // Get the toolchain info WindowsCompiler ToolChain; VersionNumber SelectedToolChainVersion; DirectoryReference SelectedToolChainDir; if (Compiler == WindowsCompiler.Clang || Compiler == WindowsCompiler.Intel) { if (WindowsPlatform.TryGetToolChainDir(WindowsCompiler.VisualStudio2019, null, out SelectedToolChainVersion, out SelectedToolChainDir)) { ToolChain = WindowsCompiler.VisualStudio2019; } else if (WindowsPlatform.TryGetToolChainDir(WindowsCompiler.VisualStudio2017, null, out SelectedToolChainVersion, out SelectedToolChainDir)) { ToolChain = WindowsCompiler.VisualStudio2017; } else { throw new BuildException("{0} or {1} must be installed in order to build this target.", WindowsPlatform.GetCompilerName(WindowsCompiler.VisualStudio2019), WindowsPlatform.GetCompilerName(WindowsCompiler.VisualStudio2017)); } } else { ToolChain = Compiler; SelectedToolChainVersion = SelectedCompilerVersion; SelectedToolChainDir = SelectedCompilerDir; } // Get the actual Windows SDK directory VersionNumber SelectedWindowsSdkVersion; DirectoryReference SelectedWindowsSdkDir; if (SuppliedSdkDirectoryForVersion != null) { SelectedWindowsSdkDir = new DirectoryReference(SuppliedSdkDirectoryForVersion); SelectedWindowsSdkVersion = VersionNumber.Parse(WindowsSdkVersion); if (!DirectoryReference.Exists(SelectedWindowsSdkDir)) { throw new BuildException("Windows SDK{0} must be installed at {1}.", String.IsNullOrEmpty(WindowsSdkVersion) ? "" : String.Format(" ({0})", WindowsSdkVersion), SuppliedSdkDirectoryForVersion); } } else { if (!WindowsPlatform.TryGetWindowsSdkDir(WindowsSdkVersion, out SelectedWindowsSdkVersion, out SelectedWindowsSdkDir)) { throw new BuildException("Windows SDK{0} must be installed in order to build this target.", String.IsNullOrEmpty(WindowsSdkVersion) ? "" : String.Format(" ({0})", WindowsSdkVersion)); } } return(new VCEnvironment(Platform, Compiler, SelectedCompilerDir, SelectedCompilerVersion, Architecture, ToolChain, SelectedToolChainDir, SelectedToolChainVersion, SelectedWindowsSdkDir, SelectedWindowsSdkVersion)); }
/// <summary> /// Gets all build products produced by this binary /// </summary> /// <param name="Target">The target being built</param> /// <param name="ToolChain">The platform toolchain</param> /// <param name="BuildProducts">Mapping of produced build product to type</param> /// <param name="bCreateDebugInfo">Whether debug info is enabled for this binary</param> public void GetBuildProducts(ReadOnlyTargetRules Target, UEToolChain ToolChain, Dictionary <FileReference, BuildProductType> BuildProducts, bool bCreateDebugInfo) { // Add all the precompiled outputs foreach (UEBuildModuleCPP Module in Modules.OfType <UEBuildModuleCPP>()) { if (Module.Rules.bPrecompile) { if (Module.GeneratedCodeDirectory != null && DirectoryReference.Exists(Module.GeneratedCodeDirectory)) { foreach (FileReference GeneratedCodeFile in DirectoryReference.EnumerateFiles(Module.GeneratedCodeDirectory)) { // Exclude timestamp files, since they're always updated and cause collisions between builds if (!GeneratedCodeFile.GetFileName().Equals("Timestamp", StringComparison.OrdinalIgnoreCase) && !GeneratedCodeFile.HasExtension(".cpp")) { BuildProducts.Add(GeneratedCodeFile, BuildProductType.BuildResource); } } } if (Target.LinkType == TargetLinkType.Monolithic) { FileReference PrecompiledManifestLocation = Module.PrecompiledManifestLocation; BuildProducts.Add(PrecompiledManifestLocation, BuildProductType.BuildResource); PrecompiledManifest ModuleManifest = PrecompiledManifest.Read(PrecompiledManifestLocation); foreach (FileReference OutputFile in ModuleManifest.OutputFiles) { if (!BuildProducts.ContainsKey(OutputFile)) { BuildProducts.Add(OutputFile, BuildProductType.BuildResource); } } } } } // Add all the binary outputs if (!Target.bDisableLinking) { // Get the type of build products we're creating BuildProductType OutputType = BuildProductType.RequiredResource; switch (Type) { case UEBuildBinaryType.Executable: OutputType = BuildProductType.Executable; break; case UEBuildBinaryType.DynamicLinkLibrary: OutputType = BuildProductType.DynamicLibrary; break; case UEBuildBinaryType.StaticLibrary: OutputType = BuildProductType.BuildResource; break; } // Add the primary build products string[] DebugExtensions = UEBuildPlatform.GetBuildPlatform(Target.Platform).GetDebugInfoExtensions(Target, Type); foreach (FileReference OutputFilePath in OutputFilePaths) { AddBuildProductAndDebugFiles(OutputFilePath, OutputType, DebugExtensions, BuildProducts, ToolChain, bCreateDebugInfo); } // Add the console app, if there is one if (Type == UEBuildBinaryType.Executable && bBuildAdditionalConsoleApp) { foreach (FileReference OutputFilePath in OutputFilePaths) { AddBuildProductAndDebugFiles(GetAdditionalConsoleAppPath(OutputFilePath), OutputType, DebugExtensions, BuildProducts, ToolChain, bCreateDebugInfo); } } // Add any additional build products from the modules in this binary, including additional bundle resources/dylibs on Mac. List <string> Libraries = new List <string>(); List <UEBuildBundleResource> BundleResources = new List <UEBuildBundleResource>(); GatherAdditionalResources(Libraries, BundleResources); // Add any extra files from the toolchain ToolChain.ModifyBuildProducts(Target, this, Libraries, BundleResources, BuildProducts); } }
/// <summary> /// Main entry point /// </summary> /// <param name="Arguments">Command-line arguments</param> /// <returns>One of the values of ECompilationResult</returns> public override int Execute(CommandLineArguments Arguments) { Arguments.ApplyTo(this); // Create the build configuration object, and read the settings BuildConfiguration BuildConfiguration = new BuildConfiguration(); XmlConfig.ApplyTo(BuildConfiguration); Arguments.ApplyTo(BuildConfiguration); // Parse all the targets being built List <TargetDescriptor> TargetDescriptors = TargetDescriptor.ParseCommandLine(Arguments, BuildConfiguration.bUsePrecompiled, bSkipRulesCompile); if (TargetDescriptors.Count == 0) { throw new BuildException("No targets specified to clean"); } // Also add implicit descriptors for cleaning UnrealBuildTool if (!BuildConfiguration.bDoNotBuildUHT) { const string UnrealHeaderToolTarget = "UnrealHeaderTool"; // Get a list of project files to clean UHT for List <FileReference> ProjectFiles = new List <FileReference>(); foreach (TargetDescriptor TargetDesc in TargetDescriptors) { if (TargetDesc.Name != UnrealHeaderToolTarget && !RemoteMac.HandlesTargetPlatform(TargetDesc.Platform)) { if (ProjectFiles.Count == 0) { ProjectFiles.Add(null); } if (TargetDesc.ProjectFile != null && !ProjectFiles.Contains(TargetDesc.ProjectFile)) { ProjectFiles.Add(TargetDesc.ProjectFile); } } } // Add descriptors for cleaning UHT with all these projects if (ProjectFiles.Count > 0) { UnrealTargetConfiguration Configuration = BuildConfiguration.bForceDebugUnrealHeaderTool ? UnrealTargetConfiguration.Debug : UnrealTargetConfiguration.Development; string Architecture = UEBuildPlatform.GetBuildPlatform(BuildHostPlatform.Current.Platform).GetDefaultArchitecture(null); foreach (FileReference ProjectFile in ProjectFiles) { TargetDescriptors.Add(new TargetDescriptor(ProjectFile, UnrealHeaderToolTarget, BuildHostPlatform.Current.Platform, Configuration, Architecture, null)); } } } // Output the list of targets that we're cleaning Log.TraceInformation("Cleaning {0} binaries...", StringUtils.FormatList(TargetDescriptors.Select(x => x.Name).Distinct())); // Loop through all the targets, and clean them all HashSet <FileReference> FilesToDelete = new HashSet <FileReference>(); HashSet <DirectoryReference> DirectoriesToDelete = new HashSet <DirectoryReference>(); foreach (TargetDescriptor TargetDescriptor in TargetDescriptors) { // Create the rules assembly RulesAssembly RulesAssembly = RulesCompiler.CreateTargetRulesAssembly(TargetDescriptor.ProjectFile, TargetDescriptor.Name, bSkipRulesCompile, BuildConfiguration.bUsePrecompiled, TargetDescriptor.ForeignPlugin); // Create the rules object ReadOnlyTargetRules Target = new ReadOnlyTargetRules(RulesAssembly.CreateTargetRules(TargetDescriptor.Name, TargetDescriptor.Platform, TargetDescriptor.Configuration, TargetDescriptor.Architecture, TargetDescriptor.ProjectFile, TargetDescriptor.AdditionalArguments)); // Find the base folders that can contain binaries List <DirectoryReference> BaseDirs = new List <DirectoryReference>(); BaseDirs.Add(UnrealBuildTool.EngineDirectory); BaseDirs.Add(UnrealBuildTool.EnterpriseDirectory); foreach (FileReference Plugin in Plugins.EnumeratePlugins(Target.ProjectFile)) { BaseDirs.Add(Plugin.Directory); } if (Target.ProjectFile != null) { BaseDirs.Add(Target.ProjectFile.Directory); } // If we're running a precompiled build, remove anything under the engine folder BaseDirs.RemoveAll(x => RulesAssembly.IsReadOnly(x)); // Get all the names which can prefix build products List <string> NamePrefixes = new List <string>(); if (Target.Type != TargetType.Program) { NamePrefixes.Add(UEBuildTarget.GetAppNameForTargetType(Target.Type)); } NamePrefixes.Add(Target.Name); // Get the suffixes for this configuration List <string> NameSuffixes = new List <string>(); if (Target.Configuration == Target.UndecoratedConfiguration) { NameSuffixes.Add(""); } NameSuffixes.Add(String.Format("-{0}-{1}", Target.Platform.ToString(), Target.Configuration.ToString())); if (!String.IsNullOrEmpty(Target.Architecture)) { NameSuffixes.AddRange(NameSuffixes.ToArray().Select(x => x + Target.Architecture)); } // Add all the makefiles and caches to be deleted FilesToDelete.Add(TargetMakefile.GetLocation(Target.ProjectFile, Target.Name, Target.Platform, Target.Configuration)); FilesToDelete.UnionWith(SourceFileMetadataCache.GetFilesToClean(Target.ProjectFile)); FilesToDelete.UnionWith(ActionHistory.GetFilesToClean(Target.ProjectFile, Target.Name, Target.Platform, Target.Type, Target.Architecture)); // Add all the intermediate folders to be deleted foreach (DirectoryReference BaseDir in BaseDirs) { foreach (string NamePrefix in NamePrefixes) { DirectoryReference GeneratedCodeDir = DirectoryReference.Combine(BaseDir, "Intermediate", "Build", Target.Platform.ToString(), NamePrefix, "Inc"); if (DirectoryReference.Exists(GeneratedCodeDir)) { DirectoriesToDelete.Add(GeneratedCodeDir); } DirectoryReference IntermediateDir = DirectoryReference.Combine(BaseDir, "Intermediate", "Build", Target.Platform.ToString(), NamePrefix, Target.Configuration.ToString()); if (DirectoryReference.Exists(IntermediateDir)) { DirectoriesToDelete.Add(IntermediateDir); } } } // List of additional files and directories to clean, specified by the target platform List <FileReference> AdditionalFilesToDelete = new List <FileReference>(); List <DirectoryReference> AdditionalDirectoriesToDelete = new List <DirectoryReference>(); // Add all the build products from this target string[] NamePrefixesArray = NamePrefixes.Distinct().ToArray(); string[] NameSuffixesArray = NameSuffixes.Distinct().ToArray(); foreach (DirectoryReference BaseDir in BaseDirs) { DirectoryReference BinariesDir = DirectoryReference.Combine(BaseDir, "Binaries", Target.Platform.ToString()); if (DirectoryReference.Exists(BinariesDir)) { UEBuildPlatform.GetBuildPlatform(Target.Platform).FindBuildProductsToClean(BinariesDir, NamePrefixesArray, NameSuffixesArray, AdditionalFilesToDelete, AdditionalDirectoriesToDelete); } } // Get all the additional intermediate folders created by this platform UEBuildPlatform.GetBuildPlatform(Target.Platform).FindAdditionalBuildProductsToClean(Target, AdditionalFilesToDelete, AdditionalDirectoriesToDelete); // Add the platform's files and directories to the main list FilesToDelete.UnionWith(AdditionalFilesToDelete); DirectoriesToDelete.UnionWith(AdditionalDirectoriesToDelete); } // Delete all the directories, then all the files. By sorting the list of directories before we delete them, we avoid spamming the log if a parent directory is deleted first. foreach (DirectoryReference DirectoryToDelete in DirectoriesToDelete.OrderBy(x => x.FullName)) { if (DirectoryReference.Exists(DirectoryToDelete)) { Log.TraceVerbose(" Deleting {0}{1}...", DirectoryToDelete, Path.DirectorySeparatorChar); try { DirectoryReference.Delete(DirectoryToDelete, true); } catch (Exception Ex) { throw new BuildException(Ex, "Unable to delete {0} ({1})", DirectoryToDelete, Ex.Message.TrimEnd()); } } } foreach (FileReference FileToDelete in FilesToDelete.OrderBy(x => x.FullName)) { if (FileReference.Exists(FileToDelete)) { Log.TraceVerbose(" Deleting " + FileToDelete); try { FileReference.Delete(FileToDelete); } catch (Exception Ex) { throw new BuildException(Ex, "Unable to delete {0} ({1})", FileToDelete, Ex.Message.TrimEnd()); } } } // Also clean all the remote targets for (int Idx = 0; Idx < TargetDescriptors.Count; Idx++) { TargetDescriptor TargetDescriptor = TargetDescriptors[Idx]; if (RemoteMac.HandlesTargetPlatform(TargetDescriptor.Platform)) { RemoteMac RemoteMac = new RemoteMac(TargetDescriptor.ProjectFile); RemoteMac.Clean(TargetDescriptor); } } return(0); }
/// <summary> /// Creates a rules assembly with the given parameters. /// </summary> /// <param name="ProjectFileName">The project file to create rules for. Null for the engine.</param> /// <param name="bUsePrecompiled">Whether to use a precompiled engine</param> /// <param name="bSkipCompile">Whether to skip compilation for this assembly</param> /// <returns>New rules assembly</returns> public static RulesAssembly CreateProjectRulesAssembly(FileReference ProjectFileName, bool bUsePrecompiled, bool bSkipCompile) { // Check if there's an existing assembly for this project RulesAssembly ProjectRulesAssembly; if (!LoadedAssemblyMap.TryGetValue(ProjectFileName, out ProjectRulesAssembly)) { ProjectDescriptor Project = ProjectDescriptor.FromFile(ProjectFileName); // Create the parent assembly RulesAssembly Parent; if (Project.IsEnterpriseProject) { Parent = CreateEnterpriseRulesAssembly(bUsePrecompiled, bSkipCompile); } else { Parent = CreateEngineRulesAssembly(bUsePrecompiled, bSkipCompile); } DirectoryReference MainProjectDirectory = ProjectFileName.Directory; DirectoryReference MainProjectSourceDirectory = DirectoryReference.Combine(MainProjectDirectory, "Source"); // Create a scope for things in this assembly RulesScope Scope = new RulesScope("Project", Parent.Scope); // Create a new context for modules created by this assembly ModuleRulesContext DefaultModuleContext = new ModuleRulesContext(Scope, MainProjectDirectory); DefaultModuleContext.bCanBuildDebugGame = true; DefaultModuleContext.bCanHotReload = true; DefaultModuleContext.bClassifyAsGameModuleForUHT = true; DefaultModuleContext.bCanUseForSharedPCH = false; // gather modules from project and platforms Dictionary <FileReference, ModuleRulesContext> ModuleFiles = new Dictionary <FileReference, ModuleRulesContext>(); List <FileReference> TargetFiles = new List <FileReference>(); // Find all the rules/plugins under the project source directories foreach (DirectoryReference ProjectDirectory in UnrealBuildTool.GetAllProjectDirectories(ProjectFileName)) { DirectoryReference ProjectSourceDirectory = DirectoryReference.Combine(ProjectDirectory, "Source"); AddModuleRulesWithContext(ProjectSourceDirectory, DefaultModuleContext, ModuleFiles); TargetFiles.AddRange(FindAllRulesFiles(ProjectSourceDirectory, RulesFileType.Target)); } // Find all the project plugins List <PluginInfo> ProjectPlugins = new List <PluginInfo>(); ProjectPlugins.AddRange(Plugins.ReadProjectPlugins(MainProjectDirectory)); // Add the project's additional plugin directories plugins too if (Project.AdditionalPluginDirectories != null) { foreach (string AdditionalPluginDirectory in Project.AdditionalPluginDirectories) { ProjectPlugins.AddRange(Plugins.ReadAdditionalPlugins(MainProjectDirectory, AdditionalPluginDirectory)); } } // Find all the plugin module rules FindModuleRulesForPlugins(ProjectPlugins, DefaultModuleContext, ModuleFiles); // Add the games project's intermediate source folder DirectoryReference ProjectIntermediateSourceDirectory = DirectoryReference.Combine(MainProjectDirectory, "Intermediate", "Source"); if (DirectoryReference.Exists(ProjectIntermediateSourceDirectory)) { AddModuleRulesWithContext(ProjectIntermediateSourceDirectory, DefaultModuleContext, ModuleFiles); TargetFiles.AddRange(FindAllRulesFiles(ProjectIntermediateSourceDirectory, RulesFileType.Target)); } // Compile the assembly. If there are no module or target files, just use the parent assembly. FileReference AssemblyFileName = FileReference.Combine(MainProjectDirectory, "Intermediate", "Build", "BuildRules", ProjectFileName.GetFileNameWithoutExtension() + "ModuleRules" + FrameworkAssemblyExtension); if (ModuleFiles.Count == 0 && TargetFiles.Count == 0) { ProjectRulesAssembly = Parent; } else { ProjectRulesAssembly = new RulesAssembly(Scope, MainProjectDirectory, ProjectPlugins, ModuleFiles, TargetFiles, AssemblyFileName, bContainsEngineModules: false, DefaultBuildSettings: null, bReadOnly: UnrealBuildTool.IsProjectInstalled(), bSkipCompile: bSkipCompile, Parent: Parent); } LoadedAssemblyMap.Add(ProjectFileName, ProjectRulesAssembly); } return(ProjectRulesAssembly); }