/** Takes the given path and tries to rebase it relative to the project or solution directory variables. */ public string NormalizeProjectPath(string InputPath) { // If the path is rooted in an environment variable, leave it be. if (InputPath.StartsWith("$(")) { return(InputPath); } // Otherwise make sure it's absolute string FullInputPath = Utils.CleanDirectorySeparators(Path.GetFullPath(InputPath)); // Try to make it relative to the solution directory. string FullSolutionPath = Utils.CleanDirectorySeparators(Path.GetFullPath(ProjectFileGenerator.MasterProjectRelativePath)); if (FullSolutionPath.Last() != Path.DirectorySeparatorChar) { FullSolutionPath += Path.DirectorySeparatorChar; } if (FullInputPath.StartsWith(FullSolutionPath)) { FullInputPath = Utils.MakePathRelativeTo(Utils.CleanDirectorySeparators(FullInputPath), Path.GetDirectoryName(Path.GetFullPath(ProjectFilePath))); } else { FullInputPath = Utils.CleanDirectorySeparators(FullInputPath); } // Otherwise return the input return(FullInputPath); }
private void ParseSourceFilesIntoGroups() { foreach (SourceFile CurSourceFile in SourceFiles) { EddieSourceFile SourceFile = CurSourceFile as EddieSourceFile; string FileName = SourceFile.Reference.GetFileName(); string FileExtension = Path.GetExtension(FileName); string FilePath = SourceFile.Reference.MakeRelativeTo(ProjectFilePath.Directory); string FilePathMac = Utils.CleanDirectorySeparators(FilePath, '/'); string ProjectRelativeSourceFile = CurSourceFile.Reference.MakeRelativeTo(ProjectFilePath.Directory); string RelativeSourceDirectory = Path.GetDirectoryName(ProjectRelativeSourceFile); // Use the specified relative base folder if (CurSourceFile.BaseFolder != null) // NOTE: We are looking for null strings, not empty strings! { RelativeSourceDirectory = Path.GetDirectoryName(CurSourceFile.Reference.MakeRelativeTo(CurSourceFile.BaseFolder)); } EddieFolder Group = FindFolderByRelativePath(ref Folders, RelativeSourceDirectory); if (Group != null) { if (FileName.EndsWith(".build.cs") || FileName.EndsWith(".Build.cs") || FileName.EndsWith(".csproj")) { Group.bIsModuleFolder = true; Group.WorksetPath = ProjectFilePath.FullName + "." + Group.Name + ".wkst"; } Group.FullPath = Path.GetDirectoryName(SourceFile.Reference.FullName); Group.Files.Add(SourceFile); } } }
/// <summary> /// Constructor /// </summary> /// <param name="InName">Name of the module</param> /// <param name="InType">Type of the module, for UHT</param> /// <param name="InModuleDirectory">Base directory for the module</param> /// <param name="InRules">Rules for this module</param> /// <param name="InRulesFile">Path to the rules file</param> /// <param name="InRuntimeDependencies">List of runtime dependencies</param> public UEBuildModule(string InName, UHTModuleType InType, DirectoryReference InModuleDirectory, ModuleRules InRules, FileReference InRulesFile, List <RuntimeDependency> InRuntimeDependencies) { Name = InName; Type = InType; ModuleDirectory = InModuleDirectory; Rules = InRules; RulesFile = InRulesFile; NormalizedModuleIncludePath = Utils.CleanDirectorySeparators(ModuleDirectory.MakeRelativeTo(UnrealBuildTool.EngineSourceDirectory), '/'); ModuleApiDefine = Name.ToUpperInvariant() + "_API"; PublicDefinitions = HashSetFromOptionalEnumerableStringParameter(InRules.Definitions); PublicIncludePaths = HashSetFromOptionalEnumerableStringParameter(InRules.PublicIncludePaths); PublicSystemIncludePaths = HashSetFromOptionalEnumerableStringParameter(InRules.PublicSystemIncludePaths); PublicLibraryPaths = HashSetFromOptionalEnumerableStringParameter(InRules.PublicLibraryPaths); PublicAdditionalLibraries = HashSetFromOptionalEnumerableStringParameter(InRules.PublicAdditionalLibraries); PublicFrameworks = HashSetFromOptionalEnumerableStringParameter(InRules.PublicFrameworks); PublicWeakFrameworks = HashSetFromOptionalEnumerableStringParameter(InRules.PublicWeakFrameworks); PublicAdditionalFrameworks = InRules.PublicAdditionalFrameworks == null ? new HashSet <UEBuildFramework>() : new HashSet <UEBuildFramework>(InRules.PublicAdditionalFrameworks); PublicAdditionalShadowFiles = HashSetFromOptionalEnumerableStringParameter(InRules.PublicAdditionalShadowFiles); PublicAdditionalBundleResources = InRules.AdditionalBundleResources == null ? new HashSet <UEBuildBundleResource>() : new HashSet <UEBuildBundleResource>(InRules.AdditionalBundleResources); PublicDelayLoadDLLs = HashSetFromOptionalEnumerableStringParameter(InRules.PublicDelayLoadDLLs); PrivateIncludePaths = HashSetFromOptionalEnumerableStringParameter(InRules.PrivateIncludePaths); RuntimeDependencies = InRuntimeDependencies; IsRedistributableOverride = InRules.IsRedistributableOverride; WhitelistRestrictedFolders = new HashSet <DirectoryReference>(InRules.WhitelistRestrictedFolders.Select(x => DirectoryReference.Combine(ModuleDirectory, x))); }
/** * Generates bodies of all sections that contain a list of source files plus a dictionary of project navigator groups. */ public void GenerateSectionsContents(ref string PBXBuildFileSection, ref string PBXFileReferenceSection, ref string PBXSourcesBuildPhaseSection, ref Dictionary <string, XcodeFileGroup> Groups) { StringBuilder FileSection = new StringBuilder(); StringBuilder ReferenceSection = new StringBuilder(); StringBuilder BuildPhaseSection = new StringBuilder(); foreach (var CurSourceFile in SourceFiles) { XcodeSourceFile SourceFile = CurSourceFile as XcodeSourceFile; string FileName = Path.GetFileName(SourceFile.FilePath); string FileExtension = Path.GetExtension(FileName); string FilePath = Utils.MakePathRelativeTo(SourceFile.FilePath, XcodeProjectFileGenerator.MasterProjectRelativePath); string FilePathMac = Utils.CleanDirectorySeparators(FilePath, '/'); // Xcode doesn't parse the project file correctly if the build files don't use the same file reference ID, // so you can't just manually add an entry for UE4CmdLineRun.m, because the ID will conflict with the // ID that gets generated above implicitly by "XcodeSourceFile SourceFile = CurSourceFile as XcodeSourceFile;" // At the same time, it is necessary to manually add an entry for it, because we're compiling the unit test with // exactly one source file. // This is ugly, but the project file generator wasn't designed to handle special cases like this, // so we're left with little choice. if (FileName == "UE4CmdLineRun.m") { SourceFile.ReplaceGUIDS(UE4CmdLineRunFileGuid, UE4CmdLineRunFileRefGuid); } if (IsGeneratedProject) { FileSection.Append(string.Format("\t\t{0} /* {1} in {2} */ = {{isa = PBXBuildFile; fileRef = {3} /* {1} */; }};" + ProjectFileGenerator.NewLine, SourceFile.FileGUID, FileName, GetFileCategory(FileExtension), SourceFile.FileRefGUID)); } ReferenceSection.Append(string.Format("\t\t{0} /* {1} */ = {{isa = PBXFileReference; lastKnownFileType = {2}; name = \"{1}\"; path = \"{3}\"; sourceTree = SOURCE_ROOT; }};" + ProjectFileGenerator.NewLine, SourceFile.FileRefGUID, FileName, GetFileType(FileExtension), FilePathMac)); if (IsPartOfUE4XcodeHelperTarget(SourceFile)) { BuildPhaseSection.Append("\t\t\t\t" + SourceFile.FileGUID + " /* " + FileName + " in Sources */," + ProjectFileGenerator.NewLine); } string GroupPath = Path.GetFullPath(Path.GetDirectoryName(SourceFile.FilePath)); XcodeFileGroup Group = FindGroupByFullPath(ref Groups, GroupPath); if (Group != null) { Group.Files.Add(SourceFile); } } PBXBuildFileSection += FileSection.ToString(); PBXFileReferenceSection += ReferenceSection.ToString(); PBXSourcesBuildPhaseSection += BuildPhaseSection.ToString(); }
private static string ConvertPathToCygwin(string InPath) { if (InPath == null) { return(null); } return("/cygdrive/" + Utils.CleanDirectorySeparators(InPath.Replace(":", ""), '/')); }
public DirectoryCache(string BaseDirectory) { if (Directory.Exists(BaseDirectory)) { BaseDirectory = Utils.CleanDirectorySeparators(BaseDirectory); var FoundFiles = Directory.GetFiles(BaseDirectory); foreach (var File in FoundFiles) { Files.Add(Utils.CleanDirectorySeparators(File).ToLowerInvariant()); } } }
/// <summary> /// Return any custom paths for VisualStudio this platform requires /// This include ReferencePath, LibraryPath, LibraryWPath, IncludePath and ExecutablePath. /// </summary> /// <param name="InPlatform">The UnrealTargetPlatform being built</param> /// <param name="InConfiguration">The configuration being built</param> /// <param name="TargetType">The type of target (game or program)</param> /// <param name="TargetRulesPath">Path to the target.cs file</param> /// <param name="ProjectFilePath">Path to the project file</param> /// <param name="NMakeOutputPath"></param> /// <param name="InProjectFileFormat">Format for the generated project files</param> /// <param name="ProjectFileBuilder">The project file content</param> /// <returns>The custom path lines for the project file; Empty string if it doesn't require one</returns> public override void GetVisualStudioPathsEntries(UnrealTargetPlatform InPlatform, UnrealTargetConfiguration InConfiguration, TargetType TargetType, FileReference TargetRulesPath, FileReference ProjectFilePath, FileReference NMakeOutputPath, VCProjectFileFormat InProjectFileFormat, StringBuilder ProjectFileBuilder) { base.GetVisualStudioPathsEntries(InPlatform, InConfiguration, TargetType, TargetRulesPath, ProjectFilePath, NMakeOutputPath, InProjectFileFormat, ProjectFileBuilder); if (IsVSLuminSupportInstalled(InProjectFileFormat) && TargetType == TargetType.Game && InPlatform == UnrealTargetPlatform.Lumin) { // When generating for a blueprint only project, use the blueprint only project's path to generate the visual studio path entries bool bGetEntriesForBlueprintOnlyProject = BPOnlyProjectPath != null; string MLSDK = Utils.CleanDirectorySeparators(Environment.GetEnvironmentVariable("MLSDK"), '\\'); string GameName = bGetEntriesForBlueprintOnlyProject ? BPOnlyProjectPath.GetFileNameWithoutExtension() : TargetRulesPath.GetFileNameWithoutExtension(); GameName = Path.GetFileNameWithoutExtension(GameName); string PackagePath = bGetEntriesForBlueprintOnlyProject ? BPOnlyProjectPath.Directory.FullName + "\\Binaries\\Lumin" : Utils.MakePathRelativeTo(NMakeOutputPath.Directory.FullName, ProjectFilePath.Directory.FullName); string PackageFile = PackagePath; string PackageName = GameName; if (InConfiguration != UnrealTargetConfiguration.Development) { PackageName = GameName + "-" + InPlatform.ToString() + "-" + InConfiguration.ToString(); } PackageFile = Path.Combine(PackageFile, PackageName + ".mpk"); // Can't use $(NMakeOutput) directly since that is defined after <ELFFile> tag and thus ends up being translated as an empty string. string ELFFile = bGetEntriesForBlueprintOnlyProject ? PackagePath : Utils.MakePathRelativeTo(NMakeOutputPath.Directory.FullName, ProjectFilePath.Directory.FullName); // Provide path to stripped executable so all symbols are resolved from the external sym file instead. ELFFile = Path.Combine(ELFFile, "..\\..\\Intermediate\\Lumin\\Mabu\\Binaries", NMakeOutputPath.GetFileName()); string DebuggerFlavor = "MLDebugger"; string SymFile = Utils.MakePathRelativeTo(NMakeOutputPath.Directory.FullName, ProjectFilePath.Directory.FullName); SymFile = Path.Combine(SymFile, "..\\..\\Intermediate\\Lumin\\Mabu\\Binaries", Path.ChangeExtension(NMakeOutputPath.GetFileName(), ".sym")); // following are defaults for debugger options string Attach = "false"; string EnableAutoStop = "true"; string AutoStopAtFunction = "main"; string EnablePrettyPrinting = "true"; string MLDownloadOnStart = "true"; string CustomPathEntriesTemplate = "<MLSDK>{0}</MLSDK>" + ProjectFileGenerator.NewLine + "<PackageFile>{1}</PackageFile>" + ProjectFileGenerator.NewLine + "<ELFFile>{2}</ELFFile>" + ProjectFileGenerator.NewLine + "<DebuggerFlavor>{3}</DebuggerFlavor>" + ProjectFileGenerator.NewLine + "<Attach>{4}</Attach>" + ProjectFileGenerator.NewLine + "<EnableAutoStop>{5}</EnableAutoStop>" + ProjectFileGenerator.NewLine + "<AutoStopAtFunction>{6}</AutoStopAtFunction>" + ProjectFileGenerator.NewLine + "<EnablePrettyPrinting>{7}</EnablePrettyPrinting>" + ProjectFileGenerator.NewLine + "<MLDownloadOnStart>{8}</MLDownloadOnStart>" + ProjectFileGenerator.NewLine; // No need to provide SymFile path. The file is automatically picked up when it resides in the same folder and has the same name as the ElfFile // "<SymFile>{9}</SymFile>" + ProjectFileGenerator.NewLine; ProjectFileBuilder.Append(ProjectFileGenerator.NewLine + string.Format(CustomPathEntriesTemplate, MLSDK, PackageFile, ELFFile, DebuggerFlavor, Attach, EnableAutoStop, AutoStopAtFunction, EnablePrettyPrinting, MLDownloadOnStart)); } }
/// <summary> /// Return any custom paths for VisualStudio this platform requires /// This include ReferencePath, LibraryPath, LibraryWPath, IncludePath and ExecutablePath. /// </summary> /// <param name="InPlatform">The UnrealTargetPlatform being built</param> /// <param name="InConfiguration">The configuration being built</param> /// <param name="TargetType">The type of target (game or program)</param> /// <param name="TargetRulesPath">Path to the target.cs file</param> /// <param name="ProjectFilePath">Path to the project file</param> /// <param name="NMakeOutputPath"></param> /// <param name="InProjectFileFormat">Format for the generated project files</param> /// <param name="ProjectFileBuilder">The project file content</param> /// <returns>The custom path lines for the project file; Empty string if it doesn't require one</returns> public override void GetVisualStudioPathsEntries(UnrealTargetPlatform InPlatform, UnrealTargetConfiguration InConfiguration, TargetType TargetType, FileReference TargetRulesPath, FileReference ProjectFilePath, FileReference NMakeOutputPath, VCProjectFileFormat InProjectFileFormat, StringBuilder ProjectFileBuilder) { base.GetVisualStudioPathsEntries(InPlatform, InConfiguration, TargetType, TargetRulesPath, ProjectFilePath, NMakeOutputPath, InProjectFileFormat, ProjectFileBuilder); if (IsVSLuminSupportInstalled(InProjectFileFormat) && TargetType == TargetType.Game && InPlatform == UnrealTargetPlatform.Lumin) { string MLSDK = Utils.CleanDirectorySeparators(Environment.GetEnvironmentVariable("MLSDK"), '\\'); // TODO: Check if MPK name can be other than the project name. string GameName = TargetRulesPath.GetFileNameWithoutExtension(); GameName = Path.GetFileNameWithoutExtension(GameName); string PackageFile = Utils.MakePathRelativeTo(NMakeOutputPath.Directory.FullName, ProjectFilePath.Directory.FullName); string PackageName = GameName; if (InConfiguration != UnrealTargetConfiguration.Development) { PackageName = GameName + "-" + InPlatform.ToString() + "-" + InConfiguration.ToString(); } PackageFile = Path.Combine(PackageFile, PackageName + ".mpk"); // TODO: Fix NMakeOutput to have the the correct architecture name and then set ELFFile to $(NMakeOutput) string ELFFile = Utils.MakePathRelativeTo(NMakeOutputPath.Directory.FullName, ProjectFilePath.Directory.FullName); ELFFile = Path.Combine(ELFFile, "..\\..\\Intermediate\\Lumin\\Mabu\\Packaged\\bin\\" + GameName); string DebuggerFlavor = "MLDebugger"; string SymFile = Utils.MakePathRelativeTo(NMakeOutputPath.Directory.FullName, ProjectFilePath.Directory.FullName); SymFile = Path.Combine(SymFile, "..\\..\\Intermediate\\Lumin\\Mabu\\Binaries", Path.ChangeExtension(NMakeOutputPath.GetFileName(), ".sym")); // following are defaults for debugger options string Attach = "false"; string EnableAutoStop = "true"; string AutoStopAtFunction = "main"; string EnablePrettyPrinting = "true"; string MLDownloadOnStart = "true"; string CustomPathEntriesTemplate = "<MLSDK>{0}</MLSDK>" + ProjectFileGenerator.NewLine + "<PackageFile>{1}</PackageFile>" + ProjectFileGenerator.NewLine + "<ELFFile>{2}</ELFFile>" + ProjectFileGenerator.NewLine + "<DebuggerFlavor>{3}</DebuggerFlavor>" + ProjectFileGenerator.NewLine + "<Attach>{4}</Attach>" + ProjectFileGenerator.NewLine + "<EnableAutoStop>{5}</EnableAutoStop>" + ProjectFileGenerator.NewLine + "<AutoStopAtFunction>{6}</AutoStopAtFunction>" + ProjectFileGenerator.NewLine + "<EnablePrettyPrinting>{7}</EnablePrettyPrinting>" + ProjectFileGenerator.NewLine + "<MLDownloadOnStart>{8}</MLDownloadOnStart>" + ProjectFileGenerator.NewLine + "<SymFile>{9}</SymFile>" + ProjectFileGenerator.NewLine; ProjectFileBuilder.Append(ProjectFileGenerator.NewLine + string.Format(CustomPathEntriesTemplate, MLSDK, PackageFile, ELFFile, DebuggerFlavor, Attach, EnableAutoStop, AutoStopAtFunction, EnablePrettyPrinting, MLDownloadOnStart, SymFile)); } }
/// <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)); } } }
static public bool FileExists(string FileFullPath) { string FileDirectory = Utils.CleanDirectorySeparators(Path.GetDirectoryName(FileFullPath)); string DirectoriesKey = FileDirectory.ToLowerInvariant(); DirectoryCache FoundDirectoryCache; if (!Directories.TryGetValue(DirectoriesKey, out FoundDirectoryCache)) { // First time we've seen this directory. Gather information about files. FoundDirectoryCache = new DirectoryCache(FileDirectory); Directories.Add(DirectoriesKey, FoundDirectoryCache); } // Try to find the file in this directory return(FoundDirectoryCache.HasFile(FileFullPath)); }
private void AppendCleanedPathToList(StringBuilder List, String SourceFileRelativeToRoot, String FullName, String GameProjectPath) { if (!SourceFileRelativeToRoot.StartsWith("..") && !Path.IsPathRooted(SourceFileRelativeToRoot)) { List.Append("\t\"${UE4_ROOT_PATH}/Engine/" + Utils.CleanDirectorySeparators(SourceFileRelativeToRoot, '/') + "\"\n"); } else { if (String.IsNullOrEmpty(GameProjectName)) { List.Append("\t\"" + Utils.CleanDirectorySeparators(SourceFileRelativeToRoot, '/').Substring(3) + "\"\n"); } else { string RelativeGameSourcePath = Utils.MakePathRelativeTo(FullName, GameProjectPath); List.Append("\t\"${GAME_ROOT_PATH}/" + Utils.CleanDirectorySeparators(RelativeGameSourcePath, '/') + "\"\n"); } } }
/// <summary> /// Collects all header files included in a source file /// </summary> /// <param name="ProjectFile"></param> /// <param name="SourceFile"></param> /// <param name="FileToRead"></param> /// <param name="FileContents"></param> /// <param name="InstalledFolder"></param> /// <param name="StartIndex"></param> /// <param name="EndIndex"></param> private static List <DependencyInclude> CollectHeaders(FileReference ProjectFile, FileReference SourceFile, string FileToRead, string FileContents, string InstalledFolder, int StartIndex, int EndIndex) { List <DependencyInclude> Result = new List <DependencyInclude>(); Match M = CPPHeaderRegex.Match(FileContents, StartIndex, EndIndex - StartIndex); CaptureCollection Captures = M.Groups["HeaderFile"].Captures; Result.Capacity = Result.Count; foreach (Capture C in Captures) { 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 bCheckForBackwardSlashes = FileToRead.StartsWith(InstalledFolder) || ((ProjectFile != null) && new FileReference(FileToRead).IsUnderDirectory(ProjectFile.Directory)); if (bCheckForBackwardSlashes && !FileToRead.Contains("Intermediate") && !FileToRead.Contains("ThirdParty") && 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 if (SourceFile.HasExtension(".MM") || SourceFile.HasExtension(".M")) { M = MMHeaderRegex.Match(FileContents, StartIndex, EndIndex - StartIndex); Captures = M.Groups["HeaderFile"].Captures; Result.Capacity += Captures.Count; foreach (Capture C in Captures) { Result.Add(new DependencyInclude(C.Value)); } } return(Result); }
public override CPPOutput CompileCPPFiles(UEBuildTarget Target, CPPEnvironment CompileEnvironment, List <FileItem> SourceFiles, string ModuleName) { var EnvVars = VCEnvironment.SetEnvironment(CompileEnvironment.Config.Target.Platform, false); StringBuilder Arguments = new StringBuilder(); AppendCLArguments_Global(CompileEnvironment, EnvVars, Arguments); // Add include paths to the argument list. foreach (string IncludePath in CompileEnvironment.Config.CPPIncludeInfo.IncludePaths) { string IncludePathRelative = Utils.CleanDirectorySeparators(Utils.MakePathRelativeTo(IncludePath, Path.Combine(ProjectFileGenerator.RootRelativePath, "Engine/Source")), '/'); Arguments.AppendFormat(" /I \"{0}\"", IncludePathRelative); } foreach (string IncludePath in CompileEnvironment.Config.CPPIncludeInfo.SystemIncludePaths) { string IncludePathRelative = Utils.CleanDirectorySeparators(Utils.MakePathRelativeTo(IncludePath, Path.Combine(ProjectFileGenerator.RootRelativePath, "Engine/Source")), '/'); Arguments.AppendFormat(" /I \"{0}\"", IncludePathRelative); } if (CompileEnvironment.Config.CLRMode == CPPCLRMode.CLREnabled) { // Add .NET framework assembly paths. This is needed so that C++/CLI projects // can reference assemblies with #using, without having to hard code a path in the // .cpp file to the assembly's location. foreach (string AssemblyPath in CompileEnvironment.Config.SystemDotNetAssemblyPaths) { Arguments.AppendFormat(" /AI \"{0}\"", AssemblyPath); } // Add explicit .NET framework assembly references foreach (string AssemblyName in CompileEnvironment.Config.FrameworkAssemblyDependencies) { Arguments.AppendFormat(" /FU \"{0}\"", AssemblyName); } // Add private assembly references foreach (PrivateAssemblyInfo CurAssemblyInfo in CompileEnvironment.PrivateAssemblyDependencies) { Arguments.AppendFormat(" /FU \"{0}\"", CurAssemblyInfo.FileItem.AbsolutePath); } } // Add preprocessor definitions to the argument list. foreach (string Definition in CompileEnvironment.Config.Definitions) { // Escape all quotation marks so that they get properly passed with the command line. var DefinitionArgument = Definition.Contains("\"") ? Definition.Replace("\"", "\\\"") : Definition; Arguments.AppendFormat(" /D\"{0}\"", DefinitionArgument); } var BuildPlatform = UEBuildPlatform.GetBuildPlatformForCPPTargetPlatform(CompileEnvironment.Config.Target.Platform); // Create a compile action for each source file. CPPOutput Result = new CPPOutput(); foreach (FileItem SourceFile in SourceFiles) { Action CompileAction = new Action(ActionType.Compile); CompileAction.CommandDescription = "Compile"; StringBuilder FileArguments = new StringBuilder(); bool bIsPlainCFile = Path.GetExtension(SourceFile.AbsolutePath).ToUpperInvariant() == ".C"; // Add the C++ source file and its included files to the prerequisite item list. AddPrerequisiteSourceFile(Target, BuildPlatform, CompileEnvironment, SourceFile, CompileAction.PrerequisiteItems); // If this is a CLR file then make sure our dependent assemblies are added as prerequisites if (CompileEnvironment.Config.CLRMode == CPPCLRMode.CLREnabled) { foreach (PrivateAssemblyInfo CurPrivateAssemblyDependency in CompileEnvironment.PrivateAssemblyDependencies) { CompileAction.PrerequisiteItems.Add(CurPrivateAssemblyDependency.FileItem); } } bool bEmitsObjectFile = true; if (CompileEnvironment.Config.PrecompiledHeaderAction == PrecompiledHeaderAction.Create) { // Generate a CPP File that just includes the precompiled header. string PCHCPPFilename = "PCH." + ModuleName + "." + CompileEnvironment.Config.PrecompiledHeaderIncludeFilename.GetFileName() + ".cpp"; FileReference PCHCPPPath = FileReference.Combine(CompileEnvironment.Config.OutputDirectory, PCHCPPFilename); FileItem PCHCPPFile = FileItem.CreateIntermediateTextFile( PCHCPPPath, string.Format("#include \"{0}\"\r\n", CompileEnvironment.Config.PrecompiledHeaderIncludeFilename) ); // Make sure the original source directory the PCH header file existed in is added as an include // path -- it might be a private PCH header and we need to make sure that its found! string OriginalPCHHeaderDirectory = Path.GetDirectoryName(SourceFile.AbsolutePath); FileArguments.AppendFormat(" /I \"{0}\"", OriginalPCHHeaderDirectory); var PrecompiledFileExtension = UEBuildPlatform.GetBuildPlatform(UnrealTargetPlatform.UWP).GetBinaryExtension(UEBuildBinaryType.PrecompiledHeader); // Add the precompiled header file to the produced items list. FileItem PrecompiledHeaderFile = FileItem.GetItemByFileReference( FileReference.Combine( CompileEnvironment.Config.OutputDirectory, Path.GetFileName(SourceFile.AbsolutePath) + PrecompiledFileExtension ) ); CompileAction.ProducedItems.Add(PrecompiledHeaderFile); Result.PrecompiledHeaderFile = PrecompiledHeaderFile; // Add the parameters needed to compile the precompiled header file to the command-line. FileArguments.AppendFormat(" /Yc\"{0}\"", CompileEnvironment.Config.PrecompiledHeaderIncludeFilename); FileArguments.AppendFormat(" /Fp\"{0}\"", PrecompiledHeaderFile.AbsolutePath); // If we're creating a PCH that will be used to compile source files for a library, we need // the compiled modules to retain a reference to PCH's module, so that debugging information // will be included in the library. This is also required to avoid linker warning "LNK4206" // when linking an application that uses this library. if (CompileEnvironment.Config.bIsBuildingLibrary) { // NOTE: The symbol name we use here is arbitrary, and all that matters is that it is // unique per PCH module used in our library string FakeUniquePCHSymbolName = CompileEnvironment.Config.PrecompiledHeaderIncludeFilename.GetFileNameWithoutExtension(); FileArguments.AppendFormat(" /Yl{0}", FakeUniquePCHSymbolName); } FileArguments.AppendFormat(" \"{0}\"", PCHCPPFile.AbsolutePath); CompileAction.StatusDescription = PCHCPPFilename; } else { if (CompileEnvironment.Config.PrecompiledHeaderAction == PrecompiledHeaderAction.Include) { CompileAction.bIsUsingPCH = true; CompileAction.PrerequisiteItems.Add(CompileEnvironment.PrecompiledHeaderFile); FileArguments.AppendFormat(" /Yu\"{0}\"", CompileEnvironment.Config.PCHHeaderNameInCode); FileArguments.AppendFormat(" /Fp\"{0}\"", CompileEnvironment.PrecompiledHeaderFile.AbsolutePath); // Is it unsafe to always force inclusion? Clang is doing it, and .generated.cpp files // won't work otherwise, because they're not located in the context of the module, // so they can't access the module's PCH without an absolute path. //if( CompileEnvironment.Config.bForceIncludePrecompiledHeader ) { // Force include the precompiled header file. This is needed because we may have selected a // precompiled header that is different than the first direct include in the C++ source file, but // we still need to make sure that our precompiled header is the first thing included! FileArguments.AppendFormat(" /FI\"{0}\"", CompileEnvironment.Config.PCHHeaderNameInCode); } } // Add the source file path to the command-line. FileArguments.AppendFormat(" \"{0}\"", SourceFile.AbsolutePath); CompileAction.StatusDescription = Path.GetFileName(SourceFile.AbsolutePath); } if (bEmitsObjectFile) { var ObjectFileExtension = UEBuildPlatform.GetBuildPlatform(UnrealTargetPlatform.UWP).GetBinaryExtension(UEBuildBinaryType.Object); // Add the object file to the produced item list. FileItem ObjectFile = FileItem.GetItemByFileReference( FileReference.Combine( CompileEnvironment.Config.OutputDirectory, Path.GetFileName(SourceFile.AbsolutePath) + ObjectFileExtension ) ); CompileAction.ProducedItems.Add(ObjectFile); Result.ObjectFiles.Add(ObjectFile); FileArguments.AppendFormat(" /Fo\"{0}\"", ObjectFile.AbsolutePath); } // Create PDB files if we were configured to do that. // // Also, when debug info is off and XGE is enabled, force PDBs, otherwise it will try to share // a PDB file, which causes PCH creation to be serial rather than parallel (when debug info is disabled) // --> See https://udn.epicgames.com/lists/showpost.php?id=50619&list=unprog3 if (BuildConfiguration.bUsePDBFiles || (BuildConfiguration.bAllowXGE && !CompileEnvironment.Config.bCreateDebugInfo)) { string PDBFileName; bool bActionProducesPDB = false; // All files using the same PCH are required to share the same PDB that was used when compiling the PCH if (CompileEnvironment.Config.PrecompiledHeaderAction == PrecompiledHeaderAction.Include) { PDBFileName = "PCH." + ModuleName + "." + CompileEnvironment.Config.PrecompiledHeaderIncludeFilename.GetFileName(); } // Files creating a PCH use a PDB per file. else if (CompileEnvironment.Config.PrecompiledHeaderAction == PrecompiledHeaderAction.Create) { PDBFileName = "PCH." + ModuleName + "." + CompileEnvironment.Config.PrecompiledHeaderIncludeFilename.GetFileName(); bActionProducesPDB = true; } // Ungrouped C++ files use a PDB per file. else if (!bIsPlainCFile) { PDBFileName = Path.GetFileName(SourceFile.AbsolutePath); bActionProducesPDB = true; } // Group all plain C files that doesn't use PCH into the same PDB else { PDBFileName = "MiscPlainC"; } // Specify the PDB file that the compiler should write to. FileItem PDBFile = FileItem.GetItemByFileReference( FileReference.Combine( CompileEnvironment.Config.OutputDirectory, PDBFileName + ".pdb" ) ); FileArguments.AppendFormat(" /Fd\"{0}\"", PDBFile.AbsolutePath); // Only use the PDB as an output file if we want PDBs and this particular action is // the one that produces the PDB (as opposed to no debug info, where the above code // is needed, but not the output PDB, or when multiple files share a single PDB, so // only the action that generates it should count it as output directly) if (BuildConfiguration.bUsePDBFiles && bActionProducesPDB) { CompileAction.ProducedItems.Add(PDBFile); Result.DebugDataFiles.Add(PDBFile); } } // Add C or C++ specific compiler arguments. if (bIsPlainCFile) { AppendCLArguments_C(FileArguments); } else { AppendCLArguments_CPP(CompileEnvironment, FileArguments); } CompileAction.WorkingDirectory = UnrealBuildTool.EngineSourceDirectory.FullName; CompileAction.CommandPath = EnvVars.CompilerPath; CompileAction.CommandArguments = Arguments.ToString() + FileArguments.ToString() + CompileEnvironment.Config.AdditionalArguments; if (CompileEnvironment.Config.PrecompiledHeaderAction == PrecompiledHeaderAction.Create) { Log.TraceVerbose("Creating PCH: " + CompileEnvironment.Config.PrecompiledHeaderIncludeFilename); Log.TraceVerbose(" Command: " + CompileAction.CommandArguments); } else { Log.TraceVerbose(" Compiling: " + CompileAction.StatusDescription); Log.TraceVerbose(" Command: " + CompileAction.CommandArguments); } // VC++ always outputs the source file name being compiled, so we don't need to emit this ourselves CompileAction.bShouldOutputStatusDescription = false; // Don't farm out creation of precompiled headers as it is the critical path task. CompileAction.bCanExecuteRemotely = CompileEnvironment.Config.PrecompiledHeaderAction != PrecompiledHeaderAction.Create || BuildConfiguration.bAllowRemotelyCompiledPCHs ; // @todo: XGE has problems remote compiling C++/CLI files that use .NET Framework 4.0 if (CompileEnvironment.Config.CLRMode == CPPCLRMode.CLREnabled) { CompileAction.bCanExecuteRemotely = false; } } return(Result); }
public bool HasFile(string File) { return(Files.Contains(Utils.CleanDirectorySeparators(File).ToLowerInvariant())); }
/// <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="ExcludeNoRedistFiles">True if files under NoRedist subdirectories should be excluded</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 <string> FindFiles(List <string> DirectoriesToSearch, bool ExcludeNoRedistFiles, List <string> SubdirectoryNamesToExclude = null, bool SearchSubdirectories = true, bool IncludePrivateSourceCode = true) { // Certain file types should never be added to project files var ExcludedFileTypes = new string[] { ".vcxproj", // Visual Studio project files ".vcxproj.filters", // Visual Studio filter file ".vcxproj.user", // Visual Studio project user file ".vcxproj.vspscc", // Visual Studio source control state ".sln", // Visual Studio solution file ".sdf", // Visual Studio embedded symbol database file ".suo", // Visual Studio solution option files ".sln.docstates.suo", // Visual Studio temp file ".tmp", // Temp files used by P4 diffing (e.g. t6884t87698.tmp) ".csproj", // Visual Studio C# project files ".userprefs", // MonoDevelop project settings ".DS_Store", // Mac Desktop Services Store hidden files }; var ExcludedFileNames = new string[] { "DO_NOT_DELETE.txt", // Placeholder .txt file in P4 }; var FoundFiles = new List <string>(); foreach (var SearchDirectory in DirectoriesToSearch) { var FoundFileUnderIntermediateDirectory = string.Empty; // Look for files to add to the project within this module's directory // NOTE: Due to issue with current Mono release (2.10.x), Directory.EnumerateFiles does not // work correctly. Therefore, the logic here is encapsulated inside a delegate, and called // with either the result of EnumerateFiles or GetFiles, depending on platform. FileSearchDelegate DoSearch = delegate(IEnumerable <string> FileList) { foreach (var CurSourceFilePath in FileList) { // Get the part of the path that is relative to the module folder var RelativeSourceFilePath = CurSourceFilePath.Substring(SearchDirectory.Length + 1); bool IncludeThisFile = true; if (IncludeThisFile) { if (!IncludePrivateSourceCode) { // We consider to be Private source every file under the module's Source directory that is not either: // - Under Public sub-folder // - Ends in a C# build script file extension bool IsBuildScript = RelativeSourceFilePath.EndsWith(".Build.cs", StringComparison.InvariantCultureIgnoreCase) || RelativeSourceFilePath.EndsWith(".Target.cs", StringComparison.InvariantCultureIgnoreCase); if (!IsBuildScript && !RelativeSourceFilePath.StartsWith("Public" + Path.DirectorySeparatorChar, StringComparison.InvariantCultureIgnoreCase) && !(RelativeSourceFilePath.IndexOf(Path.DirectorySeparatorChar + "Public" + Path.DirectorySeparatorChar, StringComparison.InvariantCultureIgnoreCase) != -1)) { IncludeThisFile = false; } } } if (IncludeThisFile) { // Skip NoRedist files if necessary if (ExcludeNoRedistFiles) { if (RelativeSourceFilePath.StartsWith("NoRedist" + Path.DirectorySeparatorChar, StringComparison.InvariantCultureIgnoreCase) || RelativeSourceFilePath.IndexOf(Path.DirectorySeparatorChar + "NoRedist" + Path.DirectorySeparatorChar, StringComparison.InvariantCultureIgnoreCase) != -1) { IncludeThisFile = false; } } } // Mask out blacklisted folders if (IncludeThisFile && SubdirectoryNamesToExclude != null) { foreach (var BlacklistedSubdirectoryName in SubdirectoryNamesToExclude) { if (RelativeSourceFilePath.StartsWith(BlacklistedSubdirectoryName + Path.DirectorySeparatorChar, StringComparison.InvariantCultureIgnoreCase) || RelativeSourceFilePath.IndexOf(Path.DirectorySeparatorChar + BlacklistedSubdirectoryName + Path.DirectorySeparatorChar, StringComparison.InvariantCultureIgnoreCase) != -1) { IncludeThisFile = false; break; } } } // Mask out blacklisted file extensions if (IncludeThisFile) { foreach (var BlacklistedFileExtension in ExcludedFileTypes) { if (RelativeSourceFilePath.EndsWith(BlacklistedFileExtension, StringComparison.InvariantCultureIgnoreCase)) { IncludeThisFile = false; break; } } if (IncludeThisFile) { foreach (var BlacklistedFileName in ExcludedFileNames) { if (Path.GetFileName(RelativeSourceFilePath).Equals(BlacklistedFileName, StringComparison.InvariantCultureIgnoreCase)) { IncludeThisFile = false; break; } } } } // Watch out for "Intermediate" folders. Module folders should not usually have an Intermediate subfolder, but we'll check for this in case // there is something stale or broken; Our module is not going to compile properly if it tries to pull in existing intermediates as source! if (IncludeThisFile) { if (RelativeSourceFilePath.StartsWith("Intermediate" + Path.DirectorySeparatorChar, StringComparison.InvariantCultureIgnoreCase) || RelativeSourceFilePath.IndexOf(Path.DirectorySeparatorChar + "Intermediate" + Path.DirectorySeparatorChar, StringComparison.InvariantCultureIgnoreCase) != -1) { if (!String.IsNullOrEmpty(FoundFileUnderIntermediateDirectory)) { // Save off at least one example of a file that was bad, so that we can print a warning later FoundFileUnderIntermediateDirectory = CurSourceFilePath; } IncludeThisFile = false; } } if (IncludeThisFile) { // Don't add duplicates if (!FoundFiles.Contains(CurSourceFilePath)) { FoundFiles.Add(CurSourceFilePath); } } } }; // call the delegate to do the work, based on platform (see note above) if (!Utils.IsRunningOnMono) { DoSearch(Directory.EnumerateFiles(Utils.CleanDirectorySeparators(SearchDirectory), "*.*", SearchSubdirectories ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly)); } else { DoSearch(Directory.GetFiles(Utils.CleanDirectorySeparators(SearchDirectory), "*.*", SearchSubdirectories ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly).AsEnumerable()); } if (!string.IsNullOrEmpty(FoundFileUnderIntermediateDirectory)) { Console.WriteLine("WARNING: UnrealBuildTool skipped at least one file in an Intermediate folder while gathering module files in directory '{0}' (file: '{1}'). This is unexpected, please remove this Intermediate directory.", SearchDirectory, FoundFileUnderIntermediateDirectory); } } return(FoundFiles); }
public override void PreBuildSync() { // no need to sync on the Mac! if (BuildHostPlatform.Current.Platform == UnrealTargetPlatform.Mac) { return; } if (bUseRPCUtil) { string ExtString = ""; // look only for useful extensions foreach (string Ext in RsyncExtensions) { // for later ls ExtString += Ext.StartsWith(".") ? ("*" + Ext) : Ext; ExtString += " "; } List <string> BatchUploadCommands = new List <string>(); // for each directory we visited, add all the files in that directory foreach (string Dir in RsyncDirs) { List <string> LocalFilenames = new List <string>(); if (!Directory.Exists(Dir)) { Directory.CreateDirectory(Dir); } // look only for useful extensions foreach (string Ext in RsyncExtensions) { string[] Files = Directory.GetFiles(Dir, "*" + Ext); foreach (string SyncFile in Files) { // remember all local files LocalFilenames.Add(Path.GetFileName(SyncFile)); string RemoteFilePath = ConvertPath(SyncFile); // an upload command is local name and remote name BatchUploadCommands.Add(SyncFile + ";" + RemoteFilePath); } } } // batch upload RPCUtilHelper.BatchUpload(BatchUploadCommands.ToArray()); } else { List <string> RelativeRsyncDirs = new List <string>(); foreach (string Dir in RsyncDirs) { RelativeRsyncDirs.Add(Utils.CleanDirectorySeparators(Dir.Replace(":", ""), '/') + "/"); } // write out directories to copy string RSyncPathsFile = Path.GetTempFileName(); string IncludeFromFile = Path.GetTempFileName(); File.WriteAllLines(RSyncPathsFile, RelativeRsyncDirs.ToArray()); File.WriteAllLines(IncludeFromFile, RsyncExtensions); // source and destination paths in the format rsync wants string CygRootPath = "/cygdrive"; // ConvertPathToCygwin(Path.GetFullPath("")); string RemotePath = string.Format("{0}{1}", UserDevRootMac, Environment.MachineName); // get the executable dir for SSH, so Rsync can call it easily string ExeDir = Path.GetDirectoryName(ResolvedSSHExe); Process RsyncProcess = new Process(); if (ExeDir != "") { RsyncProcess.StartInfo.WorkingDirectory = ExeDir; } // --exclude='*' ??? why??? RsyncProcess.StartInfo.FileName = ResolvedRSyncExe; RsyncProcess.StartInfo.Arguments = string.Format( "-vzae \"{0}\" --rsync-path=\"mkdir -p {2} && rsync\" --chmod=ug=rwX,o=rxX --delete --files-from=\"{4}\" --include-from=\"{5}\" --include='*/' --exclude='*.o' --exclude='Timestamp' '{1}' {6}@{3}:'{2}'", ResolvedRsyncAuthentication, CygRootPath, RemotePath, RemoteServerName, ConvertPathToCygwin(RSyncPathsFile), ConvertPathToCygwin(IncludeFromFile), RSyncUsername); Console.WriteLine("Command: " + RsyncProcess.StartInfo.Arguments); RsyncProcess.OutputDataReceived += new DataReceivedEventHandler(OutputReceivedForRsync); RsyncProcess.ErrorDataReceived += new DataReceivedEventHandler(OutputReceivedForRsync); // run rsync Utils.RunLocalProcess(RsyncProcess); File.Delete(IncludeFromFile); File.Delete(RSyncPathsFile); } // we can now clear out the set of files RsyncDirs.Clear(); RsyncExtensions.Clear(); }
private bool WriteCMakeLists() { string BuildCommand; const string CMakeSectionEnd = " )\n\n"; StringBuilder CMakefileContent = new StringBuilder(); // Create Engine/Project specific lists StringBuilder CMakeEngineSourceFilesList = new StringBuilder("set(ENGINE_SOURCE_FILES \n"); StringBuilder CMakeProjectSourceFilesList = new StringBuilder("set(PROJECT_SOURCE_FILES \n"); StringBuilder CMakeEngineHeaderFilesList = new StringBuilder("set(ENGINE_HEADER_FILES \n"); StringBuilder CMakeProjectHeaderFilesList = new StringBuilder("set(PROJECT_HEADER_FILES \n"); StringBuilder CMakeEngineCSFilesList = new StringBuilder("set(ENGINE_CSHARP_FILES \n"); StringBuilder CMakeProjectCSFilesList = new StringBuilder("set(PROJECT_CSHARP_FILES \n"); StringBuilder CMakeEngineConfigFilesList = new StringBuilder("set(ENGINE_CONFIG_FILES \n"); StringBuilder CMakeProjectConfigFilesList = new StringBuilder("set(PROJECT_CONFIG_FILES \n"); StringBuilder CMakeEngineShaderFilesList = new StringBuilder("set(ENGINE_SHADER_FILES \n"); StringBuilder CMakeProjectShaderFilesList = new StringBuilder("set(PROJECT_SHADER_FILES \n"); StringBuilder IncludeDirectoriesList = new StringBuilder("include_directories( \n"); StringBuilder PreprocessorDefinitionsList = new StringBuilder("add_definitions( \n"); string UE4RootPath = Utils.CleanDirectorySeparators(UnrealBuildTool.RootDirectory.FullName, '/'); string CMakeGameRootPath = ""; string GameProjectPath = ""; string CMakeGameProjectFile = ""; string HostArchitecture; string SetCompiler = ""; switch (BuildHostPlatform.Current.Platform) { case UnrealTargetPlatform.Win64: { HostArchitecture = "Win64"; BuildCommand = "call \"" + UE4RootPath + "/Engine/Build/BatchFiles/Build.bat\""; break; } case UnrealTargetPlatform.Mac: { HostArchitecture = "Mac"; BuildCommand = "cd \"" + UE4RootPath + "\" && bash \"" + UE4RootPath + "/Engine/Build/BatchFiles/" + HostArchitecture + "/Build.sh\""; bIncludeIOSTargets = true; bIncludeTVOSTargets = true; break; } case UnrealTargetPlatform.Linux: { HostArchitecture = "Linux"; BuildCommand = "cd \"" + UE4RootPath + "\" && bash \"" + UE4RootPath + "/Engine/Build/BatchFiles/" + HostArchitecture + "/Build.sh\""; string CompilerPath = LinuxCommon.WhichClang(); if (CompilerPath == null) { CompilerPath = LinuxCommon.WhichGcc(); } SetCompiler = "set(CMAKE_CXX_COMPILER " + CompilerPath + ")\n\n"; break; } default: { throw new BuildException("ERROR: CMakefileGenerator does not support this platform"); } } if (IsProjectBuild) { GameProjectPath = OnlyGameProject.Directory.FullName; CMakeGameRootPath = Utils.CleanDirectorySeparators(OnlyGameProject.Directory.FullName, '/'); CMakeGameProjectFile = Utils.CleanDirectorySeparators(OnlyGameProject.FullName, '/'); } // Additional CMake file definitions string EngineHeadersFilePath = FileReference.Combine(IntermediateProjectFilesPath, CMakeEngineHeadersFileName).ToNormalizedPath(); string ProjectHeadersFilePath = FileReference.Combine(IntermediateProjectFilesPath, CMakeProjectHeadersFileName).ToNormalizedPath(); string EngineSourcesFilePath = FileReference.Combine(IntermediateProjectFilesPath, CMakeEngineSourcesFileName).ToNormalizedPath(); string ProjectSourcesFilePath = FileReference.Combine(IntermediateProjectFilesPath, CMakeProjectSourcesFileName).ToNormalizedPath(); string ProjectFilePath = FileReference.Combine(IntermediateProjectFilesPath, CMakeProjectSourcesFileName).ToNormalizedPath(); string IncludeFilePath = FileReference.Combine(IntermediateProjectFilesPath, CMakeIncludesFileName).ToNormalizedPath(); string EngineConfigsFilePath = FileReference.Combine(IntermediateProjectFilesPath, CMakeEngineConfigsFileName).ToNormalizedPath(); string ProjectConfigsFilePath = FileReference.Combine(IntermediateProjectFilesPath, CMakeProjectConfigsFileName).ToNormalizedPath(); string EngineCSFilePath = FileReference.Combine(IntermediateProjectFilesPath, CMakeEngineCSFileName).ToNormalizedPath(); string ProjectCSFilePath = FileReference.Combine(IntermediateProjectFilesPath, CMakeProjectCSFileName).ToNormalizedPath(); string EngineShadersFilePath = FileReference.Combine(IntermediateProjectFilesPath, CMakeEngineShadersFileName).ToNormalizedPath(); string ProjectShadersFilePath = FileReference.Combine(IntermediateProjectFilesPath, CMakeProjectShadersFileName).ToNormalizedPath(); string DefinitionsFilePath = FileReference.Combine(IntermediateProjectFilesPath, CMakeDefinitionsFileName).ToNormalizedPath(); CMakefileContent.Append( "# Makefile generated by CMakefileGenerator.cs (v1.2)\n" + "# *DO NOT EDIT*\n\n" + "cmake_minimum_required (VERSION 2.6)\n" + "project (UE4)\n\n" + "# CMake Flags\n" + "set(CMAKE_CXX_STANDARD 14)\n" + // Need to keep this updated "set(CMAKE_CXX_USE_RESPONSE_FILE_FOR_OBJECTS 1 CACHE BOOL \"\" FORCE)\n" + "set(CMAKE_CXX_USE_RESPONSE_FILE_FOR_INCLUDES 1 CACHE BOOL \"\" FORCE)\n\n" + SetCompiler + "# Standard Includes\n" + "include(\"" + IncludeFilePath + "\")\n" + "include(\"" + DefinitionsFilePath + "\")\n" + "include(\"" + EngineHeadersFilePath + "\")\n" + "include(\"" + ProjectHeadersFilePath + "\")\n" + "include(\"" + EngineSourcesFilePath + "\")\n" + "include(\"" + ProjectSourcesFilePath + "\")\n" + "include(\"" + EngineCSFilePath + "\")\n" + "include(\"" + ProjectCSFilePath + "\")\n\n" ); List <string> IncludeDirectories = new List <string>(); List <string> PreprocessorDefinitions = new List <string>(); foreach (ProjectFile CurProject in GeneratedProjectFiles) { foreach (string IncludeSearchPath in CurProject.IntelliSenseIncludeSearchPaths) { string IncludeDirectory = GetIncludeDirectory(IncludeSearchPath, Path.GetDirectoryName(CurProject.ProjectFilePath.FullName)); if (IncludeDirectory != null && !IncludeDirectories.Contains(IncludeDirectory)) { if (IncludeDirectory.Contains(UnrealBuildTool.RootDirectory.FullName)) { IncludeDirectories.Add(IncludeDirectory.Replace(UnrealBuildTool.RootDirectory.FullName, UE4RootPath)); } else { // If the path isn't rooted, then it is relative to the game root if (!Path.IsPathRooted(IncludeDirectory)) { IncludeDirectories.Add(CMakeGameRootPath + "/" + IncludeDirectory); } else { // This is a rooted path like /usr/local/sometool/include IncludeDirectories.Add(IncludeDirectory); } } } } foreach (string PreProcessorDefinition in CurProject.IntelliSensePreprocessorDefinitions) { string Definition = PreProcessorDefinition.Replace("TEXT(\"", "").Replace("\")", "").Replace("()=", "="); string AlternateDefinition = Definition.Contains("=0") ? Definition.Replace("=0", "=1") : Definition.Replace("=1", "=0"); if (Definition.Equals("WITH_EDITORONLY_DATA=0")) { Definition = AlternateDefinition; } if (!PreprocessorDefinitions.Contains(Definition) && !PreprocessorDefinitions.Contains(AlternateDefinition) && !Definition.StartsWith("UE_ENGINE_DIRECTORY") && !Definition.StartsWith("ORIGINAL_FILE_NAME")) { PreprocessorDefinitions.Add(Definition); } } } // Create SourceFiles, HeaderFiles, and ConfigFiles sections. List <FileReference> AllModuleFiles = DiscoverModules(FindGameProjects()); foreach (FileReference CurModuleFile in AllModuleFiles) { List <FileReference> FoundFiles = SourceFileSearch.FindModuleSourceFiles(CurModuleFile); foreach (FileReference CurSourceFile in FoundFiles) { string SourceFileRelativeToRoot = CurSourceFile.MakeRelativeTo(UnrealBuildTool.EngineDirectory); // Exclude files/folders on a per-platform basis. if (!IsPathExcludedOnPlatform(SourceFileRelativeToRoot, BuildHostPlatform.Current.Platform)) { if (SourceFileRelativeToRoot.EndsWith(".cpp")) { AppendCleanedPathToList(CMakeEngineSourceFilesList, CMakeProjectSourceFilesList, SourceFileRelativeToRoot, CurSourceFile.FullName, GameProjectPath, UE4RootPath, CMakeGameRootPath); } else if (SourceFileRelativeToRoot.EndsWith(".h")) { AppendCleanedPathToList(CMakeEngineHeaderFilesList, CMakeProjectHeaderFilesList, SourceFileRelativeToRoot, CurSourceFile.FullName, GameProjectPath, UE4RootPath, CMakeGameRootPath); } else if (SourceFileRelativeToRoot.EndsWith(".cs")) { AppendCleanedPathToList(CMakeEngineCSFilesList, CMakeProjectCSFilesList, SourceFileRelativeToRoot, CurSourceFile.FullName, GameProjectPath, UE4RootPath, CMakeGameRootPath); } else if (SourceFileRelativeToRoot.EndsWith(".usf") || SourceFileRelativeToRoot.EndsWith(".ush")) { AppendCleanedPathToList(CMakeEngineShaderFilesList, CMakeProjectShaderFilesList, SourceFileRelativeToRoot, CurSourceFile.FullName, GameProjectPath, UE4RootPath, CMakeGameRootPath); } else if (SourceFileRelativeToRoot.EndsWith(".ini")) { AppendCleanedPathToList(CMakeEngineConfigFilesList, CMakeProjectConfigFilesList, SourceFileRelativeToRoot, CurSourceFile.FullName, GameProjectPath, UE4RootPath, CMakeGameRootPath); } } } } foreach (string IncludeDirectory in IncludeDirectories) { IncludeDirectoriesList.Append("\t\"" + Utils.CleanDirectorySeparators(IncludeDirectory, '/') + "\"\n"); } foreach (string PreprocessorDefinition in PreprocessorDefinitions) { int EqPos = PreprocessorDefinition.IndexOf("="); if (EqPos >= 0) { string Key = PreprocessorDefinition.Substring(0, EqPos); string Value = PreprocessorDefinition.Substring(EqPos).Replace("\"", "\\\""); PreprocessorDefinitionsList.Append("\t\"-D" + Key + Value + "\"\n"); } else { PreprocessorDefinitionsList.Append("\t\"-D" + PreprocessorDefinition + "\"\n"); } } // Add Engine/Shaders files (game are added via modules) List <FileReference> EngineShaderFiles = SourceFileSearch.FindFiles(DirectoryReference.Combine(UnrealBuildTool.EngineDirectory, "Shaders")); foreach (FileReference CurSourceFile in EngineShaderFiles) { string SourceFileRelativeToRoot = CurSourceFile.MakeRelativeTo(UnrealBuildTool.EngineDirectory); if (SourceFileRelativeToRoot.EndsWith(".usf") || SourceFileRelativeToRoot.EndsWith(".ush")) { AppendCleanedPathToList(CMakeEngineShaderFilesList, CMakeProjectShaderFilesList, SourceFileRelativeToRoot, CurSourceFile.FullName, GameProjectPath, UE4RootPath, CMakeGameRootPath); } } // Add Engine/Config ini files (game are added via modules) List <FileReference> EngineConfigFiles = SourceFileSearch.FindFiles(DirectoryReference.Combine(UnrealBuildTool.EngineDirectory, "Config")); foreach (FileReference CurSourceFile in EngineConfigFiles) { string SourceFileRelativeToRoot = CurSourceFile.MakeRelativeTo(UnrealBuildTool.EngineDirectory); if (SourceFileRelativeToRoot.EndsWith(".ini")) { AppendCleanedPathToList(CMakeEngineConfigFilesList, CMakeProjectConfigFilesList, SourceFileRelativeToRoot, CurSourceFile.FullName, GameProjectPath, UE4RootPath, CMakeGameRootPath); } } // Add section end to section strings; CMakeEngineSourceFilesList.Append(CMakeSectionEnd); CMakeEngineHeaderFilesList.Append(CMakeSectionEnd); CMakeEngineCSFilesList.Append(CMakeSectionEnd); CMakeEngineConfigFilesList.Append(CMakeSectionEnd); CMakeEngineShaderFilesList.Append(CMakeSectionEnd); CMakeProjectSourceFilesList.Append(CMakeSectionEnd); CMakeProjectHeaderFilesList.Append(CMakeSectionEnd); CMakeProjectCSFilesList.Append(CMakeSectionEnd); CMakeProjectConfigFilesList.Append(CMakeSectionEnd); CMakeProjectShaderFilesList.Append(CMakeSectionEnd); IncludeDirectoriesList.Append(CMakeSectionEnd); PreprocessorDefinitionsList.Append(CMakeSectionEnd); if (bIncludeShaderSource) { CMakefileContent.Append("# Optional Shader Include\n"); if (!IsProjectBuild || bIncludeEngineSource) { CMakefileContent.Append("include(\"" + EngineShadersFilePath + "\")\n"); CMakefileContent.Append("set_source_files_properties(${ENGINE_SHADER_FILES} PROPERTIES HEADER_FILE_ONLY TRUE)\n"); } CMakefileContent.Append("include(\"" + ProjectShadersFilePath + "\")\n"); CMakefileContent.Append("set_source_files_properties(${PROJECT_SHADER_FILES} PROPERTIES HEADER_FILE_ONLY TRUE)\n"); CMakefileContent.Append("source_group(\"Shader Files\" REGULAR_EXPRESSION .*.usf)\n\n"); } if (bIncludeConfigFiles) { CMakefileContent.Append("# Optional Config Include\n"); if (!IsProjectBuild || bIncludeEngineSource) { CMakefileContent.Append("include(\"" + EngineConfigsFilePath + "\")\n"); CMakefileContent.Append("set_source_files_properties(${ENGINE_CONFIG_FILES} PROPERTIES HEADER_FILE_ONLY TRUE)\n"); } CMakefileContent.Append("include(\"" + ProjectConfigsFilePath + "\")\n"); CMakefileContent.Append("set_source_files_properties(${PROJECT_CONFIG_FILES} PROPERTIES HEADER_FILE_ONLY TRUE)\n"); CMakefileContent.Append("source_group(\"Config Files\" REGULAR_EXPRESSION .*.ini)\n\n"); } string CMakeProjectCmdArg = ""; string UBTArguements = ""; if (bGeneratingGameProjectFiles) { UBTArguements += " -game"; } // Should the builder output progress ticks if (ProgressWriter.bWriteMarkup) { UBTArguements += " -progress"; } foreach (ProjectFile Project in GeneratedProjectFiles) { foreach (ProjectTarget TargetFile in Project.ProjectTargets) { if (TargetFile.TargetFilePath == null) { continue; } string TargetName = TargetFile.TargetFilePath.GetFileNameWithoutAnyExtensions(); // Remove both ".cs" and ". foreach (UnrealTargetConfiguration CurConfiguration in Enum.GetValues(typeof(UnrealTargetConfiguration))) { if (CurConfiguration != UnrealTargetConfiguration.Unknown && CurConfiguration != UnrealTargetConfiguration.Development) { if (InstalledPlatformInfo.IsValidConfiguration(CurConfiguration, EProjectType.Code) && !IsTargetExcluded(TargetName, BuildHostPlatform.Current.Platform, CurConfiguration)) { if (TargetName == GameProjectName || TargetName == (GameProjectName + "Editor")) { CMakeProjectCmdArg = "\"-project=" + CMakeGameProjectFile + "\""; } string ConfName = Enum.GetName(typeof(UnrealTargetConfiguration), CurConfiguration); CMakefileContent.Append(String.Format("add_custom_target({0}-{3}-{1} {5} {0} {3} {1} {2}{4} -buildscw VERBATIM)\n", TargetName, ConfName, CMakeProjectCmdArg, HostArchitecture, UBTArguements, BuildCommand)); // Add iOS and TVOS targets if valid if (bIncludeIOSTargets && !IsTargetExcluded(TargetName, UnrealTargetPlatform.IOS, CurConfiguration)) { CMakefileContent.Append(String.Format("add_custom_target({0}-{3}-{1} {5} {0} {3} {1} {2}{4} VERBATIM)\n", TargetName, ConfName, CMakeProjectCmdArg, UnrealTargetPlatform.IOS, UBTArguements, BuildCommand)); } if (bIncludeTVOSTargets && !IsTargetExcluded(TargetName, UnrealTargetPlatform.TVOS, CurConfiguration)) { CMakefileContent.Append(String.Format("add_custom_target({0}-{3}-{1} {5} {0} {3} {1} {2}{4} VERBATIM)\n", TargetName, ConfName, CMakeProjectCmdArg, UnrealTargetPlatform.TVOS, UBTArguements, BuildCommand)); } } } } if (!IsTargetExcluded(TargetName, BuildHostPlatform.Current.Platform, UnrealTargetConfiguration.Development)) { if (TargetName == GameProjectName || TargetName == (GameProjectName + "Editor")) { CMakeProjectCmdArg = "\"-project=" + CMakeGameProjectFile + "\""; } CMakefileContent.Append(String.Format("add_custom_target({0} {4} {0} {2} Development {1}{3} -buildscw VERBATIM)\n\n", TargetName, CMakeProjectCmdArg, HostArchitecture, UBTArguements, BuildCommand)); // Add iOS and TVOS targets if valid if (bIncludeIOSTargets && !IsTargetExcluded(TargetName, UnrealTargetPlatform.IOS, UnrealTargetConfiguration.Development)) { CMakefileContent.Append(String.Format("add_custom_target({0}-{3} {5} {0} {3} {1} {2}{4} VERBATIM)\n", TargetName, UnrealTargetConfiguration.Development, CMakeProjectCmdArg, UnrealTargetPlatform.IOS, UBTArguements, BuildCommand)); } if (bIncludeTVOSTargets && !IsTargetExcluded(TargetName, UnrealTargetPlatform.TVOS, UnrealTargetConfiguration.Development)) { CMakefileContent.Append(String.Format("add_custom_target({0}-{3} {5} {0} {3} {1} {2}{4} VERBATIM)\n", TargetName, UnrealTargetConfiguration.Development, CMakeProjectCmdArg, UnrealTargetPlatform.TVOS, UBTArguements, BuildCommand)); } } } } // Create Build Template if (IsProjectBuild && !bIncludeEngineSource) { CMakefileContent.AppendLine("add_executable(FakeTarget ${PROJECT_HEADER_FILES} ${PROJECT_SOURCE_FILES} ${PROJECT_CSHARP_FILES} ${PROJECT_SHADER_FILES} ${PROJECT_CONFIG_FILES})"); } else { CMakefileContent.AppendLine("add_executable(FakeTarget ${ENGINE_HEADER_FILES} ${ENGINE_SOURCE_FILES} ${ENGINE_CSHARP_FILES} ${ENGINE_SHADER_FILES} ${ENGINE_CONFIG_FILES} ${PROJECT_HEADER_FILES} ${PROJECT_SOURCE_FILES} ${PROJECT_CSHARP_FILES} ${PROJECT_SHADER_FILES} ${PROJECT_CONFIG_FILES})"); } string FullFileName = Path.Combine(MasterProjectPath.FullName, ProjectFileName); // Write out CMake files bool bWriteMakeList = WriteFileIfChanged(FullFileName, CMakefileContent.ToString()); bool bWriteEngineHeaders = WriteFileIfChanged(EngineHeadersFilePath, CMakeEngineHeaderFilesList.ToString()); bool bWriteProjectHeaders = WriteFileIfChanged(ProjectHeadersFilePath, CMakeProjectHeaderFilesList.ToString()); bool bWriteEngineSources = WriteFileIfChanged(EngineSourcesFilePath, CMakeEngineSourceFilesList.ToString()); bool bWriteProjectSources = WriteFileIfChanged(ProjectSourcesFilePath, CMakeProjectSourceFilesList.ToString()); bool bWriteIncludes = WriteFileIfChanged(IncludeFilePath, IncludeDirectoriesList.ToString()); bool bWriteDefinitions = WriteFileIfChanged(DefinitionsFilePath, PreprocessorDefinitionsList.ToString()); bool bWriteEngineConfigs = WriteFileIfChanged(EngineConfigsFilePath, CMakeEngineConfigFilesList.ToString()); bool bWriteProjectConfigs = WriteFileIfChanged(ProjectConfigsFilePath, CMakeProjectConfigFilesList.ToString()); bool bWriteEngineShaders = WriteFileIfChanged(EngineShadersFilePath, CMakeEngineShaderFilesList.ToString()); bool bWriteProjectShaders = WriteFileIfChanged(ProjectShadersFilePath, CMakeProjectShaderFilesList.ToString()); bool bWriteEngineCS = WriteFileIfChanged(EngineCSFilePath, CMakeEngineCSFilesList.ToString()); bool bWriteProjectCS = WriteFileIfChanged(ProjectCSFilePath, CMakeProjectCSFilesList.ToString()); // Return success flag if all files were written out successfully return(bWriteMakeList && bWriteEngineHeaders && bWriteProjectHeaders && bWriteEngineSources && bWriteProjectSources && bWriteEngineConfigs && bWriteProjectConfigs && bWriteEngineCS && bWriteProjectCS && bWriteEngineShaders && bWriteProjectShaders && bWriteIncludes && bWriteDefinitions); }
private bool WriteCMakeLists() { string BuildCommand; const string CMakeSectionEnd = " )\n\n"; var CMakefileContent = new StringBuilder(); StringBuilder CMakeSourceFilesList = new StringBuilder("set(SOURCE_FILES \n"); StringBuilder CMakeHeaderFilesList = new StringBuilder("set(HEADER_FILES \n"); StringBuilder CMakeConfigFilesList = new StringBuilder("set(CONFIG_FILES \n"); StringBuilder IncludeDirectoriesList = new StringBuilder("include_directories( \n"); StringBuilder PreprocessorDefinitionsList = new StringBuilder("add_definitions( \n"); string CMakeCC = "\n"; string CMakeC = "\n"; var CMakeGameRootPath = ""; var CMakeUE4RootPath = "set(UE4_ROOT_PATH " + Utils.CleanDirectorySeparators(UnrealBuildTool.RootDirectory.FullName, '/') + ")\n"; string GameProjectPath = ""; string CMakeGameProjectFile = ""; string HostArchitecture; switch (BuildHostPlatform.Current.Platform) { case UnrealTargetPlatform.Win64: { HostArchitecture = "Win64"; BuildCommand = "set(BUILD cmd /c \"${UE4_ROOT_PATH}/Engine/Build/BatchFiles/Build.bat\")\n"; break; } case UnrealTargetPlatform.Mac: { MacToolChainSettings Settings = new MacToolChainSettings(false); HostArchitecture = "Mac"; BuildCommand = "set(BUILD cd \"${UE4_ROOT_PATH}\" && bash \"${UE4_ROOT_PATH}/Engine/Build/BatchFiles/" + HostArchitecture + "/Build.sh\")\n"; CMakeCC = "set(CMAKE_CXX_COMPILER " + Settings.ToolchainDir + "clang++)\n"; CMakeC = "set(CMAKE_C_COMPILER " + Settings.ToolchainDir + "clang)\n"; break; } case UnrealTargetPlatform.Linux: { HostArchitecture = "Linux"; BuildCommand = "set(BUILD cd \"${UE4_ROOT_PATH}\" && bash \"${UE4_ROOT_PATH}/Engine/Build/BatchFiles/" + HostArchitecture + "/Build.sh\")\n"; string Compiler = LinuxCommon.WhichClang(); if (String.IsNullOrEmpty(Compiler)) { Compiler = LinuxCommon.WhichGcc(); } // Should not be possible, but... if (String.IsNullOrEmpty(Compiler)) { Compiler = "clang++"; } CMakeCC = "set(CMAKE_CXX_COMPILER \"" + Compiler + "\")\n"; string CCompiler = Compiler.Replace("++", ""); CMakeC = "set(CMAKE_C_COMPILER \"" + CCompiler + "\")\n"; break; } default: { throw new BuildException("ERROR: CMakefileGenerator does not support this platform"); } } if (!String.IsNullOrEmpty(GameProjectName)) { GameProjectPath = OnlyGameProject.Directory.FullName; CMakeGameRootPath = "set(GAME_ROOT_PATH \"" + Utils.CleanDirectorySeparators(OnlyGameProject.Directory.FullName, '/') + "\")\n"; CMakeGameProjectFile = "set(GAME_PROJECT_FILE \"" + Utils.CleanDirectorySeparators(OnlyGameProject.FullName, '/') + "\")\n"; } CMakefileContent.Append( "# Makefile generated by CMakefileGenerator.cs (v1.1)\n" + "# *DO NOT EDIT*\n\n" + "cmake_minimum_required (VERSION 2.6)\n" + "project (UE4)\n\n" + CMakeCC + CMakeC + CMakeUE4RootPath + CMakeGameProjectFile + BuildCommand + CMakeGameRootPath + "\n" ); List <string> IncludeDirectories = new List <string>(); List <string> PreprocessorDefinitions = new List <string>(); foreach (var CurProject in GeneratedProjectFiles) { foreach (var IncludeSearchPath in CurProject.IntelliSenseIncludeSearchPaths) { string IncludeDirectory = GetIncludeDirectory(IncludeSearchPath, Path.GetDirectoryName(CurProject.ProjectFilePath.FullName)); if (IncludeDirectory != null && !IncludeDirectories.Contains(IncludeDirectory)) { if (IncludeDirectory.Contains(UnrealBuildTool.RootDirectory.FullName)) { IncludeDirectories.Add(IncludeDirectory.Replace(UnrealBuildTool.RootDirectory.FullName, "${UE4_ROOT_PATH}")); } else { IncludeDirectories.Add("${GAME_ROOT_PATH}/" + IncludeDirectory); } } } foreach (var PreProcessorDefinition in CurProject.IntelliSensePreprocessorDefinitions) { string Definition = PreProcessorDefinition; string AlternateDefinition = Definition.Contains("=0") ? Definition.Replace("=0", "=1") : Definition.Replace("=1", "=0"); if (Definition.Equals("WITH_EDITORONLY_DATA=0") || Definition.Equals("WITH_DATABASE_SUPPORT=1")) { Definition = AlternateDefinition; } if (!PreprocessorDefinitions.Contains(Definition) && !PreprocessorDefinitions.Contains(AlternateDefinition) && !Definition.StartsWith("UE_ENGINE_DIRECTORY") && !Definition.StartsWith("ORIGINAL_FILE_NAME")) { PreprocessorDefinitions.Add(Definition); } } } // Create SourceFiles, HeaderFiles, and ConfigFiles sections. var AllModuleFiles = DiscoverModules(FindGameProjects()); foreach (FileReference CurModuleFile in AllModuleFiles) { var FoundFiles = SourceFileSearch.FindModuleSourceFiles(CurModuleFile); foreach (FileReference CurSourceFile in FoundFiles) { string SourceFileRelativeToRoot = CurSourceFile.MakeRelativeTo(UnrealBuildTool.EngineDirectory); // Exclude files/folders on a per-platform basis. if (!IsPathExcludedOnPlatform(SourceFileRelativeToRoot, BuildHostPlatform.Current.Platform)) { if (SourceFileRelativeToRoot.EndsWith(".cpp")) { if (!SourceFileRelativeToRoot.StartsWith("..") && !Path.IsPathRooted(SourceFileRelativeToRoot)) { CMakeSourceFilesList.Append("\t\"${UE4_ROOT_PATH}/Engine/" + Utils.CleanDirectorySeparators(SourceFileRelativeToRoot, '/') + "\"\n"); } else { if (String.IsNullOrEmpty(GameProjectName)) { CMakeSourceFilesList.Append("\t\"" + Utils.CleanDirectorySeparators(SourceFileRelativeToRoot, '/').Substring(3) + "\"\n"); } else { string RelativeGameSourcePath = Utils.MakePathRelativeTo(CurSourceFile.FullName, GameProjectPath); CMakeSourceFilesList.Append("\t\"${GAME_ROOT_PATH}/" + Utils.CleanDirectorySeparators(RelativeGameSourcePath, '/') + "\"\n"); } } } else if (SourceFileRelativeToRoot.EndsWith(".h")) { if (!SourceFileRelativeToRoot.StartsWith("..") && !Path.IsPathRooted(SourceFileRelativeToRoot)) { CMakeHeaderFilesList.Append("\t\"${UE4_ROOT_PATH}/Engine/" + Utils.CleanDirectorySeparators(SourceFileRelativeToRoot, '/') + "\"\n"); } else { if (String.IsNullOrEmpty(GameProjectName)) { CMakeHeaderFilesList.Append("\t\"" + Utils.CleanDirectorySeparators(SourceFileRelativeToRoot, '/').Substring(3) + "\"\n"); } else { string relativeGameSourcePath = Utils.MakePathRelativeTo(CurSourceFile.FullName, GameProjectPath); CMakeHeaderFilesList.Append("\t\"${GAME_ROOT_PATH}/" + Utils.CleanDirectorySeparators(relativeGameSourcePath, '/') + "\"\n"); } } } else if (SourceFileRelativeToRoot.EndsWith(".cs")) { if (!SourceFileRelativeToRoot.StartsWith("..") && !Path.IsPathRooted(SourceFileRelativeToRoot)) { CMakeConfigFilesList.Append("\t\"${UE4_ROOT_PATH}/Engine/" + Utils.CleanDirectorySeparators(SourceFileRelativeToRoot, '/') + "\"\n"); } else { if (String.IsNullOrEmpty(GameProjectName)) { CMakeConfigFilesList.Append("\t\"" + Utils.CleanDirectorySeparators(SourceFileRelativeToRoot, '/').Substring(3) + "\"\n"); } else { string relativeGameSourcePath = Utils.MakePathRelativeTo(CurSourceFile.FullName, GameProjectPath); CMakeConfigFilesList.Append("\t\"${GAME_ROOT_PATH}/" + Utils.CleanDirectorySeparators(relativeGameSourcePath, '/') + "\"\n"); } } } } } } foreach (string IncludeDirectory in IncludeDirectories) { IncludeDirectoriesList.Append("\t\"" + Utils.CleanDirectorySeparators(IncludeDirectory, '/') + "\"\n"); } foreach (string PreprocessorDefinition in PreprocessorDefinitions) { PreprocessorDefinitionsList.Append("\t-D" + PreprocessorDefinition + "\n"); } // Add section end to section strings; CMakeSourceFilesList.Append(CMakeSectionEnd); CMakeHeaderFilesList.Append(CMakeSectionEnd); CMakeConfigFilesList.Append(CMakeSectionEnd); IncludeDirectoriesList.Append(CMakeSectionEnd); PreprocessorDefinitionsList.Append(CMakeSectionEnd); // Append sections to the CMakeLists.txt file CMakefileContent.Append(CMakeSourceFilesList); CMakefileContent.Append(CMakeHeaderFilesList); CMakefileContent.Append(CMakeConfigFilesList); CMakefileContent.Append(IncludeDirectoriesList); CMakefileContent.Append(PreprocessorDefinitionsList); string CMakeProjectCmdArg = ""; foreach (var Project in GeneratedProjectFiles) { foreach (var TargetFile in Project.ProjectTargets) { if (TargetFile.TargetFilePath == null) { continue; } var TargetName = TargetFile.TargetFilePath.GetFileNameWithoutAnyExtensions(); // 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")) { CMakeProjectCmdArg = "-project=\"${GAME_PROJECT_FILE}\""; } string ConfName = Enum.GetName(typeof(UnrealTargetConfiguration), CurConfiguration); CMakefileContent.Append(String.Format("add_custom_target({0}-{3}-{1} ${{BUILD}} {0} {3} {1} {2} $(ARGS))\n", TargetName, ConfName, CMakeProjectCmdArg, HostArchitecture)); } } } if (TargetName == GameProjectName || TargetName == (GameProjectName + "Editor")) { CMakeProjectCmdArg = "-project=\"${GAME_PROJECT_FILE}\""; } CMakefileContent.Append(String.Format("add_custom_target({0} ${{BUILD}} {0} {2} Development {1} $(ARGS) SOURCES ${{SOURCE_FILES}} ${{HEADER_FILES}} ${{CONFIG_FILES}})\n\n", TargetName, CMakeProjectCmdArg, HostArchitecture)); } } // Append a dummy executable target CMakefileContent.AppendLine("add_executable(FakeTarget ${SOURCE_FILES})"); var FullFileName = Path.Combine(MasterProjectPath.FullName, ProjectFileName); bool writeSuccess = WriteFileIfChanged(FullFileName, CMakefileContent.ToString()); return(writeSuccess); }