Exemple #1
0
        /** 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);
        }
Exemple #2
0
        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);
                }
            }
        }
Exemple #3
0
        /// <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();
        }
Exemple #5
0
 private static string ConvertPathToCygwin(string InPath)
 {
     if (InPath == null)
     {
         return(null);
     }
     return("/cygdrive/" + Utils.CleanDirectorySeparators(InPath.Replace(":", ""), '/'));
 }
Exemple #6
0
 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());
         }
     }
 }
Exemple #7
0
        /// <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));
            }
        }
Exemple #9
0
        /// <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));
                }
            }
        }
Exemple #10
0
        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));
        }
Exemple #11
0
 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");
         }
     }
 }
Exemple #12
0
        /// <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);
        }
Exemple #14
0
 public bool HasFile(string File)
 {
     return(Files.Contains(Utils.CleanDirectorySeparators(File).ToLowerInvariant()));
 }
Exemple #15
0
        /// <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);
        }
Exemple #16
0
        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();
        }
Exemple #17
0
        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);
        }