/** * Checks the class header files and determines if generated UObject code files are out of date in comparison. * @param UObjectModules Modules that we generate headers for * * @return True if the code files are out of date * */ private static bool AreGeneratedCodeFilesOutOfDate(List <UHTModuleInfo> UObjectModules) { bool bIsOutOfDate = false; // Get UnrealHeaderTool timestamp. If it's newer than generated headers, they need to be rebuilt too. var HeaderToolTimestamp = CheckIfUnrealHeaderToolIsUpToDate(); // Get CoreUObject.generated.cpp timestamp. If the source files are older than the CoreUObject generated code, we'll // need to regenerate code for the module DateTime?CoreGeneratedTimestamp = null; { // Find the CoreUObject module foreach (var Module in UObjectModules) { if (Module.ModuleName.Equals("CoreUObject", StringComparison.InvariantCultureIgnoreCase)) { CoreGeneratedTimestamp = GetCoreGeneratedTimestamp(Module.ModuleName, Path.GetDirectoryName(Module.GeneratedCPPFilenameBase)); break; } } if (CoreGeneratedTimestamp == null) { throw new BuildException("Could not find CoreUObject in list of all UObjectModules"); } } foreach (var Module in UObjectModules) { // In Rocket, we skip checking timestamps for modules that don't exist within the project's directory if (UnrealBuildTool.RunningRocket()) { // @todo Rocket: This could be done in a better way I'm sure if (!Utils.IsFileUnderDirectory(Module.ModuleDirectory, UnrealBuildTool.GetUProjectPath())) { // Engine or engine plugin module - Rocket does not regenerate them so don't compare their timestamps continue; } } // Make sure we have an existing folder for generated code. If not, then we definitely need to generate code! var GeneratedCodeDirectory = Path.GetDirectoryName(Module.GeneratedCPPFilenameBase); var TestDirectory = (FileSystemInfo) new DirectoryInfo(GeneratedCodeDirectory); if (TestDirectory.Exists) { // Grab our special "Timestamp" file that we saved after the last set of headers were generated string TimestampFile = Path.Combine(GeneratedCodeDirectory, @"Timestamp"); var SavedTimestampFileInfo = (FileSystemInfo) new FileInfo(TimestampFile); if (SavedTimestampFileInfo.Exists) { // Make sure the last UHT run completed after UnrealHeaderTool.exe was compiled last, and after the CoreUObject headers were touched last. var SavedTimestamp = SavedTimestampFileInfo.LastWriteTime; if (SavedTimestamp.CompareTo(HeaderToolTimestamp) > 0 && SavedTimestamp.CompareTo(CoreGeneratedTimestamp) > 0) { // Iterate over our UObjects headers and figure out if any of them have changed var AllUObjectHeaders = new List <FileItem>(); AllUObjectHeaders.AddRange(Module.PublicUObjectClassesHeaders); AllUObjectHeaders.AddRange(Module.PublicUObjectHeaders); AllUObjectHeaders.AddRange(Module.PrivateUObjectHeaders); foreach (var HeaderFile in AllUObjectHeaders) { var HeaderFileTimestamp = HeaderFile.Info.LastWriteTime; // Has the source header changed since we last generated headers successfully? if (SavedTimestamp.CompareTo(HeaderFileTimestamp) < 0) { bIsOutOfDate = true; break; } // When we're running in assembler mode, outdatedness cannot be inferred by checking the directory timestamp // of the source headers. We don't care if source files were added or removed in this mode, because we're only // able to process the known UObject headers that are in the Makefile. If UObject header files are added/removed, // we expect the user to re-run GenerateProjectFiles which will force UBTMakefile outdatedness. // @todo fastubt: Possibly, we should never be doing this check these days. if (UnrealBuildTool.IsGatheringBuild || !UnrealBuildTool.IsAssemblingBuild) { // Also check the timestamp on the directory the source file is in. If the directory timestamp has // changed, new source files may have been added or deleted. We don't know whether the new/deleted // files were actually UObject headers, but because we don't know all of the files we processed // in the previous run, we need to assume our generated code is out of date if the directory timestamp // is newer. var HeaderDirectoryTimestamp = new DirectoryInfo(Path.GetDirectoryName(HeaderFile.AbsolutePath)).LastWriteTime; if (SavedTimestamp.CompareTo(HeaderDirectoryTimestamp) < 0) { bIsOutOfDate = true; break; } } } } else { // Generated code is older UnrealHeaderTool.exe or CoreUObject headers. Out of date! bIsOutOfDate = true; } } else { // Timestamp file was missing (possibly deleted/cleaned), so headers are out of date bIsOutOfDate = true; } } else { // Generated code directory is missing entirely! bIsOutOfDate = true; } // If even one module is out of date, we're done! UHT does them all in one fell swoop.; if (bIsOutOfDate) { break; } } return(bIsOutOfDate); }
private void SetupXPSupportFromConfiguration() { string[] CmdLine = Environment.GetCommandLineArgs(); bool SupportWindowsXPIfAvailable = false; SupportWindowsXPIfAvailable = CmdLine.Contains("-winxp", StringComparer.InvariantCultureIgnoreCase); // ...check if it was supported from a config. if (!SupportWindowsXPIfAvailable) { ConfigCacheIni Ini = new ConfigCacheIni(UnrealTargetPlatform.Win64, "Engine", UnrealBuildTool.GetUProjectPath()); string MinimumOS; if (Ini.GetString("/Script/WindowsTargetPlatform.WindowsTargetSettings", "MinimumOSVersion", out MinimumOS)) { if (string.IsNullOrEmpty(MinimumOS) == false) { SupportWindowsXPIfAvailable = MinimumOS == "MSOS_XP"; } } } SupportWindowsXP = SupportWindowsXPIfAvailable; }
private bool WriteQMakePro() { // Some more stuff borrowed from Mac side of things. List <string> IncludeDirectories = new List <string>(); List <string> SystemIncludeDirectories = new List <string>(); List <string> DefinesAndValues = new List <string> (); // DefineList.Add (""); var QMakeIncludesFileName = MasterProjectName + "Includes.pri"; var QMakeIncludesPriFileContent = new StringBuilder(); var QMakeDefinesFileName = MasterProjectName + "Defines.pri"; var QMakeDefinesPriFileContent = new StringBuilder(); string GameProjectPath = ""; string GameProjectFile = ""; string GameProjectRootPath = ""; string BuildCommand = ""; string QMakeGameProjectFile = ""; foreach (var CurProject in GeneratedProjectFiles) { QMakefileProjectFile QMakeProject = CurProject as QMakefileProjectFile; if (QMakeProject == null) { System.Console.WriteLine("QMakeProject == null"); continue; } foreach (var CurPath in QMakeProject.IntelliSenseIncludeSearchPaths) { AddIncludeDirectory(ref IncludeDirectories, CurPath, Path.GetDirectoryName(QMakeProject.ProjectFilePath)); // System.Console.WriteLine ("Not empty now? CurPath == ", CurPath); } foreach (var CurPath in QMakeProject.IntelliSenseSystemIncludeSearchPaths) { AddIncludeDirectory(ref SystemIncludeDirectories, CurPath, Path.GetDirectoryName(QMakeProject.ProjectFilePath)); } } // Iterate through all the defines for the projects that are generated by // UnrealBuildTool.exe // !RAKE: move to seperate function QMakeDefinesPriFileContent.Append("DEFINES += \\\n"); foreach (var CurProject in GeneratedProjectFiles) { QMakefileProjectFile QMakeProject = CurProject as QMakefileProjectFile; if (QMakeProject == null) { System.Console.WriteLine("QMakeProject == null"); continue; } foreach (var CurDefine in QMakeProject.IntelliSensePreprocessorDefinitions) { String define = ""; String value = ""; SplitDefinitionAndValue(CurDefine, out define, out value); if (!DefinesAndValues.Contains(define)) { // System.Console.WriteLine (CurDefine); if (string.IsNullOrEmpty(value)) { DefinesAndValues.Add("\t"); DefinesAndValues.Add(String.Format("{0}=", define)); DefinesAndValues.Add(" \\\n"); } else { DefinesAndValues.Add("\t"); DefinesAndValues.Add(define); DefinesAndValues.Add("="); DefinesAndValues.Add(value); DefinesAndValues.Add(" \\\n"); } } } } foreach (var Def in DefinesAndValues) { QMakeDefinesPriFileContent.Append(Def); } // Iterate through all the include paths that // UnrealBuildTool.exe generates // !RAKE: Move to seperate function QMakeIncludesPriFileContent.Append("INCLUDEPATH += \\\n"); foreach (var CurPath in IncludeDirectories) { QMakeIncludesPriFileContent.Append("\t"); QMakeIncludesPriFileContent.Append(CurPath); QMakeIncludesPriFileContent.Append(" \\\n"); } foreach (var CurPath in SystemIncludeDirectories) { QMakeIncludesPriFileContent.Append("\t"); QMakeIncludesPriFileContent.Append(CurPath); QMakeIncludesPriFileContent.Append(" \\\n"); } QMakeIncludesPriFileContent.Append("\n"); if (!String.IsNullOrEmpty(GameProjectName)) { GameProjectPath = UnrealBuildTool.GetUProjectPath(); GameProjectFile = UnrealBuildTool.GetUProjectFile(); QMakeGameProjectFile = "gameProjectFile=" + GameProjectFile + "\n"; BuildCommand = "build=mono $$unrealRootPath/Engine/Binaries/DotNET/UnrealBuildTool.exe\n\n"; } else { BuildCommand = "build=bash $$unrealRootPath/Engine/Build/BatchFiles/Linux/Build.sh\n"; } var UnrealRootPath = Path.GetFullPath(ProjectFileGenerator.RootRelativePath); var FileName = MasterProjectName + ".pro"; var QMakeSourcePriFileName = MasterProjectName + "Source.pri"; var QMakeHeaderPriFileName = MasterProjectName + "Header.pri"; var QMakeConfigPriFileName = MasterProjectName + "Config.pri"; var QMakeFileContent = new StringBuilder(); var QMakeSourcePriFileContent = new StringBuilder(); var QMakeHeaderPriFileContent = new StringBuilder(); var QMakeConfigPriFileContent = new StringBuilder(); var QMakeSectionEnd = " \n\n"; var QMakeSourceFilesList = "SOURCES += \\ \n"; var QMakeHeaderFilesList = "HEADERS += \\ \n"; var QMakeConfigFilesList = "OTHER_FILES += \\ \n"; var QMakeTargetList = "QMAKE_EXTRA_TARGETS += \\ \n"; if (!String.IsNullOrEmpty(GameProjectName)) { GameProjectRootPath = GameProjectName + "RootPath=" + GameProjectPath + "\n\n"; } QMakeFileContent.Append( "# UnrealEngine.pro generated by QMakefileGenerator.cs\n" + "# *DO NOT EDIT*\n\n" + "TEMPLATE = aux\n" + "CONFIG -= console\n" + "CONFIG -= app_bundle\n" + "CONFIG -= qt\n\n" + "TARGET = UE4 \n\n" + "unrealRootPath=" + UnrealRootPath + "\n" + GameProjectRootPath + QMakeGameProjectFile + BuildCommand + "args=$(ARGS)\n\n" + "include(" + QMakeSourcePriFileName + ")\n" + "include(" + QMakeHeaderPriFileName + ")\n" + "include(" + QMakeConfigPriFileName + ")\n" + "include(" + QMakeIncludesFileName + ")\n" + "include(" + QMakeDefinesFileName + ")\n\n" ); // Create SourceFiles, HeaderFiles, and ConfigFiles sections. var AllModuleFiles = DiscoverModules(); foreach (string CurModuleFile in AllModuleFiles) { var FoundFiles = SourceFileSearch.FindModuleSourceFiles(CurModuleFile, ExcludeNoRedistFiles: bExcludeNoRedistFiles); foreach (string CurSourceFile in FoundFiles) { string SourceFileRelativeToRoot = Utils.MakePathRelativeTo(CurSourceFile, Path.Combine(EngineRelativePath)); // Exclude some directories that we don't compile (note that we still want Windows/Mac etc for code navigation) if (!SourceFileRelativeToRoot.Contains("Source/ThirdParty/")) { if (SourceFileRelativeToRoot.EndsWith(".cpp")) { if (!SourceFileRelativeToRoot.StartsWith("..") && !Path.IsPathRooted(SourceFileRelativeToRoot)) { QMakeSourceFilesList += ("\t\"" + "$$unrealRootPath/Engine/" + SourceFileRelativeToRoot + "\" \\\n"); } else { if (String.IsNullOrEmpty(GameProjectName)) { QMakeSourceFilesList += ("\t\"" + SourceFileRelativeToRoot.Substring(3) + "\" \\\n"); } else if (!String.IsNullOrEmpty(GameProjectName)) { QMakeSourceFilesList += ("\t\"$$" + GameProjectName + "RootPath/" + Utils.MakePathRelativeTo(CurSourceFile, GameProjectPath) + "\" \\\n"); } else { System.Console.WriteLine("Error!, you should not be here."); } } } if (SourceFileRelativeToRoot.EndsWith(".h")) { if (!SourceFileRelativeToRoot.StartsWith("..") && !Path.IsPathRooted(SourceFileRelativeToRoot)) { // SourceFileRelativeToRoot = "Engine/" + SourceFileRelativeToRoot; QMakeHeaderFilesList += ("\t\"" + "$$unrealRootPath/Engine/" + SourceFileRelativeToRoot + "\" \\\n"); } else { if (String.IsNullOrEmpty(GameProjectName)) { // SourceFileRelativeToRoot = SourceFileRelativeToRoot.Substring (3); QMakeHeaderFilesList += ("\t\"" + SourceFileRelativeToRoot.Substring(3) + "\" \\\n"); } else if (!String.IsNullOrEmpty(GameProjectName)) { QMakeHeaderFilesList += ("\t\"$$" + GameProjectName + "RootPath/" + Utils.MakePathRelativeTo(CurSourceFile, GameProjectPath) + "\" \\\n"); } else { System.Console.WriteLine("Error!, you should not be here."); } } } if (SourceFileRelativeToRoot.EndsWith(".cs")) { if (!SourceFileRelativeToRoot.StartsWith("..") && !Path.IsPathRooted(SourceFileRelativeToRoot)) { // SourceFileRelativeToRoot = "Engine/" + SourceFileRelativeToRoot; QMakeConfigFilesList += ("\t\"" + "$$unrealRootPath/Engine/" + SourceFileRelativeToRoot + "\" \\\n"); } else { if (String.IsNullOrEmpty(GameProjectName)) { // SourceFileRelativeToRoot = SourceFileRelativeToRoot.Substring (3); QMakeConfigFilesList += ("\t\"" + SourceFileRelativeToRoot.Substring(3) + "\" \\\n"); } else if (!String.IsNullOrEmpty(GameProjectName)) { QMakeConfigFilesList += ("\t\"$$" + GameProjectName + "RootPath/" + Utils.MakePathRelativeTo(CurSourceFile, GameProjectPath) + "\" \\\n"); } else { System.Console.WriteLine("Error!, you should not be here."); } } } } } } // Add section end to section strings; QMakeSourceFilesList += QMakeSectionEnd; QMakeHeaderFilesList += QMakeSectionEnd; QMakeConfigFilesList += QMakeSectionEnd; // Append sections to the QMakeLists.txt file QMakeSourcePriFileContent.Append(QMakeSourceFilesList); QMakeHeaderPriFileContent.Append(QMakeHeaderFilesList); QMakeConfigPriFileContent.Append(QMakeConfigFilesList); string QMakeProjectCmdArg = ""; foreach (string TargetFilePath in DiscoverTargets()) { var TargetName = Utils.GetFilenameWithoutAnyExtensions(TargetFilePath); // Remove both ".cs" and ". foreach (UnrealTargetConfiguration CurConfiguration in Enum.GetValues(typeof(UnrealTargetConfiguration))) { if (CurConfiguration != UnrealTargetConfiguration.Unknown && CurConfiguration != UnrealTargetConfiguration.Development) { if (UnrealBuildTool.IsValidConfiguration(CurConfiguration)) { if (TargetName == GameProjectName || TargetName == (GameProjectName + "Editor")) { QMakeProjectCmdArg = " -project=\"\\\"$$gameProjectFile\\\"\""; } var ConfName = Enum.GetName(typeof(UnrealTargetConfiguration), CurConfiguration); QMakeFileContent.Append(String.Format("{0}-Linux-{1}.commands = $$build {0} Linux {1} {2} $$args\n", TargetName, ConfName, QMakeProjectCmdArg)); QMakeTargetList += "\t" + TargetName + "-Linux-" + ConfName + " \\\n"; // , TargetName, ConfName); } } } if (TargetName == GameProjectName || TargetName == (GameProjectName + "Editor")) { QMakeProjectCmdArg = " -project=\"\\\"$$gameProjectFile\\\"\""; } QMakeFileContent.Append(String.Format("{0}.commands = $$build {0} Linux Development {1} $$args\n\n", TargetName, QMakeProjectCmdArg)); QMakeTargetList += "\t" + TargetName + " \\\n"; } QMakeFileContent.Append(QMakeTargetList.TrimEnd('\\')); var FullFileName = Path.Combine(MasterProjectRelativePath, FileName); var FullQMakeDefinesFileName = Path.Combine(MasterProjectRelativePath, QMakeDefinesFileName); var FullQMakeIncludesFileName = Path.Combine(MasterProjectRelativePath, QMakeIncludesFileName); var FullQMakeSourcePriFileName = Path.Combine(MasterProjectRelativePath, QMakeSourcePriFileName); var FullQMakeHeaderPriFileName = Path.Combine(MasterProjectRelativePath, QMakeHeaderPriFileName); var FullQMakeConfigPriFileName = Path.Combine(MasterProjectRelativePath, QMakeConfigPriFileName); WriteFileIfChanged(FullQMakeDefinesFileName, QMakeDefinesPriFileContent.ToString()); WriteFileIfChanged(FullQMakeIncludesFileName, QMakeIncludesPriFileContent.ToString()); WriteFileIfChanged(FullQMakeSourcePriFileName, QMakeSourcePriFileContent.ToString()); WriteFileIfChanged(FullQMakeHeaderPriFileName, QMakeHeaderPriFileContent.ToString()); WriteFileIfChanged(FullQMakeConfigPriFileName, QMakeConfigPriFileContent.ToString()); return(WriteFileIfChanged(FullFileName, QMakeFileContent.ToString())); }
public static void ParseArchitectures() { // look in ini settings for what platforms to compile for ConfigCacheIni Ini = new ConfigCacheIni(UnrealTargetPlatform.Android, "Engine", UnrealBuildTool.GetUProjectPath()); List <string> ProjectArches = new List <string>(); bool bBuild = true; if (Ini.GetBool("/Script/AndroidRuntimeSettings.AndroidRuntimeSettings", "bBuildForArmV7", out bBuild) && bBuild) { ProjectArches.Add("-armv7"); } if (Ini.GetBool("/Script/AndroidRuntimeSettings.AndroidRuntimeSettings", "bBuildForArm64", out bBuild) && bBuild) { ProjectArches.Add("-arm64"); } if (Ini.GetBool("/Script/AndroidRuntimeSettings.AndroidRuntimeSettings", "bBuildForx86", out bBuild) && bBuild) { ProjectArches.Add("-x86"); } if (Ini.GetBool("/Script/AndroidRuntimeSettings.AndroidRuntimeSettings", "bBuildForx8664", out bBuild) && bBuild) { ProjectArches.Add("-x86_64"); } // force armv7 if something went wrong if (ProjectArches.Count == 0) { ProjectArches.Add("-armv7"); } Arches = ProjectArches.ToArray(); // Parse selected GPU architectures List <string> ProjectGPUArches = new List <string>(); if (Ini.GetBool("/Script/AndroidRuntimeSettings.AndroidRuntimeSettings", "bBuildForES2", out bBuild) && bBuild) { ProjectGPUArches.Add("-es2"); } if (Ini.GetBool("/Script/AndroidRuntimeSettings.AndroidRuntimeSettings", "bBuildForES31", out bBuild) && bBuild) { ProjectGPUArches.Add("-es31"); } if (Ini.GetBool("/Script/AndroidRuntimeSettings.AndroidRuntimeSettings", "bBuildForGL4", out bBuild) && bBuild) { ProjectGPUArches.Add("-gl4"); } if (ProjectGPUArches.Count == 0) { ProjectGPUArches.Add("-es2"); } GPUArchitectures = ProjectGPUArches.ToArray(); List <string> FullArchCombinations = new List <string>(); foreach (string Arch in Arches) { foreach (string GPUArch in GPUArchitectures) { FullArchCombinations.Add(Arch + GPUArch); } } AllComboNames = FullArchCombinations.ToArray(); }
static public string GetNdkApiLevel() { // ask the .ini system for what version to use ConfigCacheIni Ini = new ConfigCacheIni(UnrealTargetPlatform.Android, "Engine", UnrealBuildTool.GetUProjectPath()); string NDKLevel; Ini.GetString("/Script/AndroidPlatformEditor.AndroidSDKSettings", "NDKAPILevel", out NDKLevel); if (NDKLevel == "latest") { // get a list of NDK platforms string PlatformsDir = Environment.ExpandEnvironmentVariables("%NDKROOT%/platforms"); if (!Directory.Exists(PlatformsDir)) { throw new BuildException("No platforms found in {0}", PlatformsDir); } // return the largest of them NDKLevel = GetLargestApiLevel(Directory.GetDirectories(PlatformsDir)); } return(NDKLevel); }
public virtual void ParseProjectSettings() { ConfigCacheIni Ini = new ConfigCacheIni(GetPlatform(), "Engine", UnrealBuildTool.GetUProjectPath()); bool bValue = UEBuildConfiguration.bCompileAPEX; if (Ini.GetBool("/Script/BuildSettings.BuildSettings", "bCompileApex", out bValue)) { UEBuildConfiguration.bCompileAPEX = bValue; } bValue = UEBuildConfiguration.bCompileBox2D; if (Ini.GetBool("/Script/BuildSettings.BuildSettings", "bCompileBox2D", out bValue)) { UEBuildConfiguration.bCompileBox2D = bValue; } bValue = UEBuildConfiguration.bCompileICU; if (Ini.GetBool("/Script/BuildSettings.BuildSettings", "bCompileICU", out bValue)) { UEBuildConfiguration.bCompileICU = bValue; } bValue = UEBuildConfiguration.bCompileSimplygon; if (Ini.GetBool("/Script/BuildSettings.BuildSettings", "bCompileSimplygon", out bValue)) { UEBuildConfiguration.bCompileSimplygon = bValue; } bValue = UEBuildConfiguration.bCompileLeanAndMeanUE; if (Ini.GetBool("/Script/BuildSettings.BuildSettings", "bCompileLeanAndMeanUE", out bValue)) { UEBuildConfiguration.bCompileLeanAndMeanUE = bValue; } bValue = UEBuildConfiguration.bIncludeADO; if (Ini.GetBool("/Script/BuildSettings.BuildSettings", "bIncludeADO", out bValue)) { UEBuildConfiguration.bIncludeADO = bValue; } bValue = UEBuildConfiguration.bCompileRecast; if (Ini.GetBool("/Script/BuildSettings.BuildSettings", "bCompileRecast", out bValue)) { UEBuildConfiguration.bCompileRecast = bValue; } bValue = UEBuildConfiguration.bCompileSpeedTree; if (Ini.GetBool("/Script/BuildSettings.BuildSettings", "bCompileSpeedTree", out bValue)) { UEBuildConfiguration.bCompileSpeedTree = bValue; } bValue = UEBuildConfiguration.bCompileWithPluginSupport; if (Ini.GetBool("/Script/BuildSettings.BuildSettings", "bCompileWithPluginSupport", out bValue)) { UEBuildConfiguration.bCompileWithPluginSupport = bValue; } bValue = UEBuildConfiguration.bCompilePhysXVehicle; if (Ini.GetBool("/Script/BuildSettings.BuildSettings", "bCompilePhysXVehicle", out bValue)) { UEBuildConfiguration.bCompilePhysXVehicle = bValue; } bValue = UEBuildConfiguration.bCompileFreeType; if (Ini.GetBool("/Script/BuildSettings.BuildSettings", "bCompileFreeType", out bValue)) { UEBuildConfiguration.bCompileFreeType = bValue; } bValue = UEBuildConfiguration.bCompileForSize; if (Ini.GetBool("/Script/BuildSettings.BuildSettings", "bCompileForSize", out bValue)) { UEBuildConfiguration.bCompileForSize = bValue; } bValue = UEBuildConfiguration.bCompileCEF3; if (Ini.GetBool("/Script/BuildSettings.BuildSettings", "bCompileCEF3", out bValue)) { UEBuildConfiguration.bCompileCEF3 = bValue; } }
/// <summary> /// Collects all header files included in a CPPFile /// </summary> /// <param name="CPPFile"></param> /// <param name="Result"></param> /// <param name="FileToRead"></param> /// <param name="FileContents"></param> /// <param name="InstalledFolder"></param> /// <param name="StartIndex"></param> /// <param name="EndIndex"></param> private static void CollectHeaders(FileItem CPPFile, List <DependencyInclude> Result, string FileToRead, string FileContents, string InstalledFolder, int StartIndex, int EndIndex) { Match M = CPPHeaderRegex.Match(FileContents, StartIndex, EndIndex - StartIndex); CaptureCollection CC = M.Groups["HeaderFile"].Captures; Result.Capacity = Math.Max(Result.Count + CC.Count, Result.Capacity); foreach (Capture C in CC) { string HeaderValue = C.Value; if (HeaderValue.IndexOfAny(Path.GetInvalidPathChars()) != -1) { throw new BuildException("In {0}: An #include statement contains invalid characters. You might be missing a double-quote character. (\"{1}\")", FileToRead, C.Value); } //@TODO: The intermediate exclusion is to work around autogenerated absolute paths in Module.SomeGame.cpp style files bool bIsIntermediateOrThirdParty = FileToRead.Contains("Intermediate") || FileToRead.Contains("ThirdParty"); bool bCheckForBackwardSlashes = FileToRead.StartsWith(InstalledFolder); if (UnrealBuildTool.HasUProjectFile()) { bCheckForBackwardSlashes |= Utils.IsFileUnderDirectory(FileToRead, UnrealBuildTool.GetUProjectPath()); } if (bCheckForBackwardSlashes && !bIsIntermediateOrThirdParty) { if (HeaderValue.IndexOf('\\', 0) >= 0) { throw new BuildException("In {0}: #include \"{1}\" contains backslashes ('\\'), please use forward slashes ('/') instead.", FileToRead, C.Value); } } HeaderValue = Utils.CleanDirectorySeparators(HeaderValue); Result.Add(new DependencyInclude(HeaderValue)); } // also look for #import in objective C files string Ext = Path.GetExtension(CPPFile.AbsolutePath).ToUpperInvariant(); if (Ext == ".MM" || Ext == ".M") { M = MMHeaderRegex.Match(FileContents, StartIndex, EndIndex - StartIndex); CC = M.Groups["HeaderFile"].Captures; Result.Capacity += CC.Count; foreach (Capture C in CC) { Result.Add(new DependencyInclude(C.Value)); } } }