public override FileItem LinkFiles(LinkEnvironment LinkEnvironment, bool bBuildImportLibraryOnly) { Debug.Assert(!bBuildImportLibraryOnly); List <string> RPaths = new List <string>(); if (LinkEnvironment.Config.bIsBuildingLibrary || bBuildImportLibraryOnly) { return(CreateArchiveAndIndex(LinkEnvironment)); } // Create an action that invokes the linker. Action LinkAction = new Action(ActionType.Link); LinkAction.WorkingDirectory = Path.GetFullPath("."); if (String.IsNullOrEmpty(ClangPath)) { LinkAction.CommandPath = GCCPath; } else { LinkAction.CommandPath = ClangPath; } // Get link arguments. LinkAction.CommandArguments = GetLinkArguments(LinkEnvironment); // Tell the action that we're building an import library here and it should conditionally be // ignored as a prerequisite for other actions LinkAction.bProducesImportLibrary = LinkEnvironment.Config.bIsBuildingDLL; // Add the output file as a production of the link action. FileItem OutputFile = FileItem.GetItemByPath(LinkEnvironment.Config.OutputFilePath); LinkAction.ProducedItems.Add(OutputFile); LinkAction.CommandDescription = "Link"; LinkAction.StatusDescription = Path.GetFileName(OutputFile.AbsolutePath); // Add the output file to the command-line. LinkAction.CommandArguments += string.Format(" -o \"{0}\"", OutputFile.AbsolutePath); // Add the input files to a response file, and pass the response file on the command-line. List <string> InputFileNames = new List <string>(); foreach (FileItem InputFile in LinkEnvironment.InputFiles) { InputFileNames.Add(string.Format("\"{0}\"", InputFile.AbsolutePath.Replace("\\", "/"))); LinkAction.PrerequisiteItems.Add(InputFile); } string ResponseFileName = GetResponseFileName(LinkEnvironment, OutputFile); LinkAction.CommandArguments += string.Format(" -Wl,@\"{0}\"", ResponseFile.Create(ResponseFileName, InputFileNames)); if (LinkEnvironment.Config.bIsBuildingDLL) { LinkAction.CommandArguments += string.Format(" -Wl,-soname={0}", OutputFile); } // Start with the configured LibraryPaths and also add paths to any libraries that // we depend on (libraries that we've build ourselves). List <string> AllLibraryPaths = LinkEnvironment.Config.LibraryPaths; foreach (string AdditionalLibrary in LinkEnvironment.Config.AdditionalLibraries) { string PathToLib = Path.GetDirectoryName(AdditionalLibrary); if (!String.IsNullOrEmpty(PathToLib)) { // make path absolute, because FixDependencies script may be executed in a different directory string AbsolutePathToLib = Path.GetFullPath(PathToLib); if (!AllLibraryPaths.Contains(AbsolutePathToLib)) { AllLibraryPaths.Add(AbsolutePathToLib); } } if ((AdditionalLibrary.Contains("Plugins") || AdditionalLibrary.Contains("Binaries/ThirdParty") || AdditionalLibrary.Contains("Binaries\\ThirdParty")) && Path.GetDirectoryName(AdditionalLibrary) != Path.GetDirectoryName(OutputFile.AbsolutePath)) { string RelativePath = Utils.MakePathRelativeTo(Path.GetDirectoryName(AdditionalLibrary), Path.GetDirectoryName(OutputFile.AbsolutePath)); if (!RPaths.Contains(RelativePath)) { RPaths.Add(RelativePath); LinkAction.CommandArguments += string.Format(" -Wl,-rpath=\"${{ORIGIN}}/{0}\"", RelativePath); } } } LinkAction.CommandArguments += string.Format(" -Wl,-rpath-link=\"{0}\"", Path.GetDirectoryName(OutputFile.AbsolutePath)); // Add the library paths to the argument list. foreach (string LibraryPath in AllLibraryPaths) { // use absolute paths because of FixDependencies script again LinkAction.CommandArguments += string.Format(" -L\"{0}\"", Path.GetFullPath(LibraryPath)); } // add libraries in a library group LinkAction.CommandArguments += string.Format(" -Wl,--start-group"); List <string> EngineAndGameLibraries = new List <string>(); foreach (string AdditionalLibrary in LinkEnvironment.Config.AdditionalLibraries) { if (String.IsNullOrEmpty(Path.GetDirectoryName(AdditionalLibrary))) { // library was passed just like "jemalloc", turn it into -ljemalloc LinkAction.CommandArguments += string.Format(" -l{0}", AdditionalLibrary); } else if (Path.GetExtension(AdditionalLibrary) == ".a") { // static library passed in, pass it along but make path absolute, because FixDependencies script may be executed in a different directory string AbsoluteAdditionalLibrary = Path.GetFullPath(AdditionalLibrary); if (AbsoluteAdditionalLibrary.Contains(" ")) { AbsoluteAdditionalLibrary = string.Format("\"{0}\"", AbsoluteAdditionalLibrary); } LinkAction.CommandArguments += (" " + AbsoluteAdditionalLibrary); LinkAction.PrerequisiteItems.Add(FileItem.GetItemByPath(AdditionalLibrary)); } else { // Skip over full-pathed library dependencies when building DLLs to avoid circular // dependencies. FileItem LibraryDependency = FileItem.GetItemByPath(AdditionalLibrary); var LibName = Path.GetFileNameWithoutExtension(AdditionalLibrary); if (LibName.StartsWith("lib")) { // Remove lib prefix LibName = LibName.Remove(0, 3); } string LibLinkFlag = string.Format(" -l{0}", LibName); if (LinkEnvironment.Config.bIsBuildingDLL && LinkEnvironment.Config.bIsCrossReferenced) { // We are building a cross referenced DLL so we can't actually include // dependencies at this point. Instead we add it to the list of // libraries to be used in the FixDependencies step. EngineAndGameLibraries.Add(LibLinkFlag); if (!LinkAction.CommandArguments.Contains("--allow-shlib-undefined")) { LinkAction.CommandArguments += string.Format(" -Wl,--allow-shlib-undefined"); } } else { LinkAction.PrerequisiteItems.Add(LibraryDependency); LinkAction.CommandArguments += LibLinkFlag; } } } LinkAction.CommandArguments += " -lrt"; // needed for clock_gettime() LinkAction.CommandArguments += " -lm"; // math LinkAction.CommandArguments += string.Format(" -Wl,--end-group"); // Add the additional arguments specified by the environment. LinkAction.CommandArguments += LinkEnvironment.Config.AdditionalArguments; LinkAction.CommandArguments = LinkAction.CommandArguments.Replace("\\\\", "/"); LinkAction.CommandArguments = LinkAction.CommandArguments.Replace("\\", "/"); // prepare a linker script string LinkerScriptPath = Path.Combine(LinkEnvironment.Config.LocalShadowDirectory, "remove-sym.ldscript"); if (!Directory.Exists(LinkEnvironment.Config.LocalShadowDirectory)) { Directory.CreateDirectory(LinkEnvironment.Config.LocalShadowDirectory); } if (File.Exists(LinkerScriptPath)) { File.Delete(LinkerScriptPath); } using (StreamWriter Writer = File.CreateText(LinkerScriptPath)) { Writer.WriteLine("UE4 {"); Writer.WriteLine(" global: *;"); Writer.WriteLine(" local: _Znwm;"); Writer.WriteLine(" _Znam;"); Writer.WriteLine(" _ZdaPv;"); Writer.WriteLine(" _ZdlPv;"); Writer.WriteLine("};"); }; LinkAction.CommandArguments += string.Format(" -Wl,--version-script=\"{0}\"", LinkerScriptPath); // Only execute linking on the local PC. LinkAction.bCanExecuteRemotely = false; // Prepare a script that will run later, once all shared libraries and the executable // are created. This script will be called by action created in FixDependencies() if (LinkEnvironment.Config.bIsCrossReferenced && LinkEnvironment.Config.bIsBuildingDLL) { bool bUseCmdExe = BuildHostPlatform.Current.Platform == UnrealTargetPlatform.Win64 || BuildHostPlatform.Current.Platform == UnrealTargetPlatform.Win32; string ScriptName = bUseCmdExe ? "FixDependencies.bat" : "FixDependencies.sh"; string FixDepsScriptPath = Path.Combine(LinkEnvironment.Config.LocalShadowDirectory, ScriptName); if (!bHasWipedFixDepsScript) { bHasWipedFixDepsScript = true; Log.TraceVerbose("Creating script: {0}", FixDepsScriptPath); StreamWriter Writer = File.CreateText(FixDepsScriptPath); if (bUseCmdExe) { Writer.Write("@echo off\n"); Writer.Write("rem Automatically generated by UnrealBuildTool\n"); Writer.Write("rem *DO NOT EDIT*\n\n"); } else { Writer.Write("#!/bin/sh\n"); Writer.Write("# Automatically generated by UnrealBuildTool\n"); Writer.Write("# *DO NOT EDIT*\n\n"); Writer.Write("set -o errexit\n"); } Writer.Close(); } StreamWriter FixDepsScript = File.AppendText(FixDepsScriptPath); string EngineAndGameLibrariesString = ""; foreach (string Library in EngineAndGameLibraries) { EngineAndGameLibrariesString += Library; } FixDepsScript.Write(string.Format("echo Fixing {0}\n", Path.GetFileName(OutputFile.AbsolutePath))); if (!bUseCmdExe) { FixDepsScript.Write(string.Format("TIMESTAMP=`stat --format %y \"{0}\"`\n", OutputFile.AbsolutePath)); } string FixDepsLine = LinkAction.CommandPath + " " + LinkAction.CommandArguments; string Replace = "-Wl,--allow-shlib-undefined"; FixDepsLine = FixDepsLine.Replace(Replace, EngineAndGameLibrariesString); string OutputFileForwardSlashes = OutputFile.AbsolutePath.Replace("\\", "/"); FixDepsLine = FixDepsLine.Replace(OutputFileForwardSlashes, OutputFileForwardSlashes + ".fixed"); FixDepsLine = FixDepsLine.Replace("$", "\\$"); FixDepsScript.Write(FixDepsLine + "\n"); if (bUseCmdExe) { FixDepsScript.Write(string.Format("move /Y \"{0}.fixed\" \"{0}\"\n", OutputFile.AbsolutePath)); } else { FixDepsScript.Write(string.Format("mv \"{0}.fixed\" \"{0}\"\n", OutputFile.AbsolutePath)); FixDepsScript.Write(string.Format("touch -d \"$TIMESTAMP\" \"{0}\"\n\n", OutputFile.AbsolutePath)); } FixDepsScript.Close(); } //LinkAction.CommandArguments += " -v"; return(OutputFile); }
/// <summary> /// Adds the include directory to the list, after converting it to an absolute path to UE4 root directory. /// </summary> /// <param name="FileContent">File content.</param> private void WriteIncludeSection(ref StringBuilder FileContent) { List <string> IncludeDirectories = new List <string>(); List <string> SystemIncludeDirectories = new List <string>(); var UnrealEngineRootPath = UnrealBuildTool.RootDirectory.FullName; int IncludeIndex = 1; // Iterate through all the include paths that // UnrealBuildTool.exe generates foreach (var CurProject in GeneratedProjectFiles) { KDevelopProjectFile KDevelopProject = CurProject as KDevelopProjectFile; if (KDevelopProject == null) { System.Console.WriteLine("KDevelopProject == null"); continue; } foreach (var CurPath in KDevelopProject.IntelliSenseIncludeSearchPaths) { string FullProjectPath = ProjectFileGenerator.MasterProjectPath.FullName; string FullPath = ""; // need to test to see if this in the project souce tree if (CurPath.StartsWith("/") && !CurPath.StartsWith(FullProjectPath)) { // Full path to a folder outside of project FullPath = CurPath; } else { FullPath = Path.GetFullPath(Path.Combine(Path.GetDirectoryName(KDevelopProject.ProjectFilePath.FullName), CurPath)); FullPath = Utils.MakePathRelativeTo(FullPath, FullProjectPath); FullPath = FullPath.TrimEnd('/'); FullPath = Path.Combine(UnrealEngineRootPath, FullPath); } if (!FullPath.Contains("FortniteGame/") && !FullPath.Contains("ThirdParty/")) { SystemIncludeDirectories.Add(String.Format("{0}", FullPath)); IncludeIndex++; } } foreach (var CurPath in KDevelopProject.IntelliSenseSystemIncludeSearchPaths) { string FullProjectPath = ProjectFileGenerator.MasterProjectPath.FullName; string FullPath = ""; if (CurPath.StartsWith("/") && !CurPath.StartsWith(FullProjectPath)) { // Full path to a folder outside of project FullPath = CurPath; } else { FullPath = Path.GetFullPath(Path.Combine(Path.GetDirectoryName(KDevelopProject.ProjectFilePath.FullName), CurPath)); FullPath = Utils.MakePathRelativeTo(FullPath, FullProjectPath); FullPath = FullPath.TrimEnd('/'); FullPath = Path.Combine(UnrealEngineRootPath, FullPath); } if (!FullPath.Contains("FortniteGame/") && !FullPath.Contains("ThirdParty/")) // @todo: skipping Fortnite header paths to shorten clang command line for building UE4XcodeHelper { SystemIncludeDirectories.Add(String.Format("{0}", FullPath)); IncludeIndex++; } } } // Remove duplicate paths from include dir and system include dir list List <string> Tmp = new List <string>(); List <string> Stmp = new List <string>(); Tmp = IncludeDirectories.Distinct().ToList(); Stmp = SystemIncludeDirectories.Distinct().ToList(); IncludeDirectories = Tmp.ToList(); SystemIncludeDirectories = Stmp.ToList(); foreach (var CurPath in IncludeDirectories) { FileContent.Append(CurPath); FileContent.Append(" \n"); } foreach (var CurPath in SystemIncludeDirectories) { FileContent.Append(CurPath); FileContent.Append(" \n"); } FileContent.Append("\n"); }
private bool WriteQMakePro() { // Some more stuff borrowed from Mac side of things. List <string> IncludeDirectories = new List <string>(); List <string> SystemIncludeDirectories = new List <string>(); List <string> DefinesAndValues = new List <string>(); // DefineList.Add (""); var QMakeIncludesFileName = MasterProjectName + "Includes.pri"; var QMakeIncludesPriFileContent = new StringBuilder(); var QMakeDefinesFileName = MasterProjectName + "Defines.pri"; var QMakeDefinesPriFileContent = new StringBuilder(); string GameProjectPath = ""; string GameProjectFile = ""; string GameProjectRootPath = ""; string BuildCommand = ""; string QMakeGameProjectFile = ""; foreach (var CurProject in GeneratedProjectFiles) { QMakefileProjectFile QMakeProject = CurProject as QMakefileProjectFile; if (QMakeProject == null) { System.Console.WriteLine("QMakeProject == null"); continue; } foreach (var CurPath in QMakeProject.IntelliSenseIncludeSearchPaths) { AddIncludeDirectory(ref IncludeDirectories, CurPath, Path.GetDirectoryName(QMakeProject.ProjectFilePath.FullName)); // System.Console.WriteLine ("Not empty now? CurPath == ", CurPath); } foreach (var CurPath in QMakeProject.IntelliSenseSystemIncludeSearchPaths) { AddIncludeDirectory(ref SystemIncludeDirectories, CurPath, Path.GetDirectoryName(QMakeProject.ProjectFilePath.FullName)); } } // Remove duplicate paths from include dir and system include dir list IncludeDirectories = IncludeDirectories.Distinct().ToList(); SystemIncludeDirectories = SystemIncludeDirectories.Distinct().ToList(); // Iterate through all the defines for the projects that are generated by // UnrealBuildTool.exe // !RAKE: move to seperate function QMakeDefinesPriFileContent.Append("DEFINES += \\\n"); foreach (var CurProject in GeneratedProjectFiles) { QMakefileProjectFile QMakeProject = CurProject as QMakefileProjectFile; if (QMakeProject == null) { System.Console.WriteLine("QMakeProject == null"); continue; } foreach (var CurDefine in QMakeProject.IntelliSensePreprocessorDefinitions) { String define = ""; String value = ""; SplitDefinitionAndValue(CurDefine, out define, out value); if (!DefinesAndValues.Contains(define)) { // System.Console.WriteLine (CurDefine); if (string.IsNullOrEmpty(value)) { DefinesAndValues.Add("\t"); DefinesAndValues.Add(String.Format("{0}=", define)); DefinesAndValues.Add(" \\\n"); } else { DefinesAndValues.Add("\t"); DefinesAndValues.Add(define); DefinesAndValues.Add("="); DefinesAndValues.Add(value); DefinesAndValues.Add(" \\\n"); } } } } foreach (var Def in DefinesAndValues) { QMakeDefinesPriFileContent.Append(Def); } // Iterate through all the include paths that // UnrealBuildTool.exe generates // !RAKE: Move to seperate function QMakeIncludesPriFileContent.Append("INCLUDEPATH += \\\n"); foreach (var CurPath in IncludeDirectories) { QMakeIncludesPriFileContent.Append("\t"); QMakeIncludesPriFileContent.Append(CurPath); QMakeIncludesPriFileContent.Append(" \\\n"); } foreach (var CurPath in SystemIncludeDirectories) { QMakeIncludesPriFileContent.Append("\t"); QMakeIncludesPriFileContent.Append(CurPath); QMakeIncludesPriFileContent.Append(" \\\n"); } QMakeIncludesPriFileContent.Append("\n"); if (!String.IsNullOrEmpty(GameProjectName)) { GameProjectPath = OnlyGameProject.Directory.FullName; GameProjectFile = OnlyGameProject.FullName; QMakeGameProjectFile = "gameProjectFile=" + GameProjectFile + "\n"; BuildCommand = "build=mono $$unrealRootPath/Engine/Binaries/DotNET/UnrealBuildTool.exe\n\n"; } else { BuildCommand = "build=bash $$unrealRootPath/Engine/Build/BatchFiles/Linux/Build.sh\n"; } var UnrealRootPath = Path.GetFullPath(ProjectFileGenerator.RootRelativePath); var FileName = MasterProjectName + ".pro"; var QMakeSourcePriFileName = MasterProjectName + "Source.pri"; var QMakeHeaderPriFileName = MasterProjectName + "Header.pri"; var QMakeConfigPriFileName = MasterProjectName + "Config.pri"; var QMakeFileContent = new StringBuilder(); var QMakeSourcePriFileContent = new StringBuilder(); var QMakeHeaderPriFileContent = new StringBuilder(); var QMakeConfigPriFileContent = new StringBuilder(); var QMakeSectionEnd = " \n\n"; var QMakeSourceFilesList = "SOURCES += \\ \n"; var QMakeHeaderFilesList = "HEADERS += \\ \n"; var QMakeConfigFilesList = "OTHER_FILES += \\ \n"; var QMakeTargetList = "QMAKE_EXTRA_TARGETS += \\ \n"; if (!String.IsNullOrEmpty(GameProjectName)) { GameProjectRootPath = GameProjectName + "RootPath=" + GameProjectPath + "\n\n"; } QMakeFileContent.Append( "# UnrealEngine.pro generated by QMakefileGenerator.cs\n" + "# *DO NOT EDIT*\n\n" + "TEMPLATE = aux\n" + "CONFIG += c++11\n" + "CONFIG -= console\n" + "CONFIG -= app_bundle\n" + "CONFIG -= qt\n\n" + "TARGET = UE4 \n\n" + "unrealRootPath=" + UnrealRootPath + "\n" + GameProjectRootPath + QMakeGameProjectFile + BuildCommand + "args=$(ARGS)\n\n" + "include(" + QMakeSourcePriFileName + ")\n" + "include(" + QMakeHeaderPriFileName + ")\n" + "include(" + QMakeConfigPriFileName + ")\n" + "include(" + QMakeIncludesFileName + ")\n" + "include(" + QMakeDefinesFileName + ")\n\n" ); // Create SourceFiles, HeaderFiles, and ConfigFiles sections. var AllModuleFiles = DiscoverModules(FindGameProjects()); foreach (FileReference CurModuleFile in AllModuleFiles) { var FoundFiles = SourceFileSearch.FindModuleSourceFiles(CurModuleFile); foreach (FileReference CurSourceFile in FoundFiles) { string SourceFileRelativeToRoot = CurSourceFile.MakeRelativeTo(UnrealBuildTool.EngineDirectory); // Exclude some directories that we don't compile (note that we still want Windows/Mac etc for code navigation) if (!SourceFileRelativeToRoot.Contains("Source/ThirdParty/")) { if (SourceFileRelativeToRoot.EndsWith(".cpp")) { if (!SourceFileRelativeToRoot.StartsWith("..") && !Path.IsPathRooted(SourceFileRelativeToRoot)) { QMakeSourceFilesList += ("\t\"" + "$$unrealRootPath/Engine/" + SourceFileRelativeToRoot + "\" \\\n"); } else { if (String.IsNullOrEmpty(GameProjectName)) { QMakeSourceFilesList += ("\t\"" + SourceFileRelativeToRoot.Substring(3) + "\" \\\n"); } else if (!String.IsNullOrEmpty(GameProjectName)) { QMakeSourceFilesList += ("\t\"$$" + GameProjectName + "RootPath/" + Utils.MakePathRelativeTo(CurSourceFile.FullName, GameProjectPath) + "\" \\\n"); } else { System.Console.WriteLine("Error!, you should not be here."); } } } if (SourceFileRelativeToRoot.EndsWith(".h")) { if (!SourceFileRelativeToRoot.StartsWith("..") && !Path.IsPathRooted(SourceFileRelativeToRoot)) { // SourceFileRelativeToRoot = "Engine/" + SourceFileRelativeToRoot; QMakeHeaderFilesList += ("\t\"" + "$$unrealRootPath/Engine/" + SourceFileRelativeToRoot + "\" \\\n"); } else { if (String.IsNullOrEmpty(GameProjectName)) { // SourceFileRelativeToRoot = SourceFileRelativeToRoot.Substring (3); QMakeHeaderFilesList += ("\t\"" + SourceFileRelativeToRoot.Substring(3) + "\" \\\n"); } else if (!String.IsNullOrEmpty(GameProjectName)) { QMakeHeaderFilesList += ("\t\"$$" + GameProjectName + "RootPath/" + Utils.MakePathRelativeTo(CurSourceFile.FullName, GameProjectPath) + "\" \\\n"); } else { System.Console.WriteLine("Error!, you should not be here."); } } } if (SourceFileRelativeToRoot.EndsWith(".cs")) { if (!SourceFileRelativeToRoot.StartsWith("..") && !Path.IsPathRooted(SourceFileRelativeToRoot)) { // SourceFileRelativeToRoot = "Engine/" + SourceFileRelativeToRoot; QMakeConfigFilesList += ("\t\"" + "$$unrealRootPath/Engine/" + SourceFileRelativeToRoot + "\" \\\n"); } else { if (String.IsNullOrEmpty(GameProjectName)) { // SourceFileRelativeToRoot = SourceFileRelativeToRoot.Substring (3); QMakeConfigFilesList += ("\t\"" + SourceFileRelativeToRoot.Substring(3) + "\" \\\n"); } else if (!String.IsNullOrEmpty(GameProjectName)) { QMakeConfigFilesList += ("\t\"$$" + GameProjectName + "RootPath/" + Utils.MakePathRelativeTo(CurSourceFile.FullName, GameProjectPath) + "\" \\\n"); } else { System.Console.WriteLine("Error!, you should not be here."); } } } } } } // Add section end to section strings; QMakeSourceFilesList += QMakeSectionEnd; QMakeHeaderFilesList += QMakeSectionEnd; QMakeConfigFilesList += QMakeSectionEnd; // Append sections to the QMakeLists.txt file QMakeSourcePriFileContent.Append(QMakeSourceFilesList); QMakeHeaderPriFileContent.Append(QMakeHeaderFilesList); QMakeConfigPriFileContent.Append(QMakeConfigFilesList); string QMakeProjectCmdArg = ""; foreach (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")) { QMakeProjectCmdArg = " -project=\"\\\"$$gameProjectFile\\\"\""; } var ConfName = Enum.GetName(typeof(UnrealTargetConfiguration), CurConfiguration); QMakeFileContent.Append(String.Format("{0}-Linux-{1}.commands = $$build {0} Linux {1} {2} $$args\n", TargetName, ConfName, QMakeProjectCmdArg)); QMakeTargetList += "\t" + TargetName + "-Linux-" + ConfName + " \\\n"; // , TargetName, ConfName); } } } if (TargetName == GameProjectName || TargetName == (GameProjectName + "Editor")) { QMakeProjectCmdArg = " -project=\"\\\"$$gameProjectFile\\\"\""; } QMakeFileContent.Append(String.Format("{0}.commands = $$build {0} Linux Development {1} $$args\n\n", TargetName, QMakeProjectCmdArg)); QMakeTargetList += "\t" + TargetName + " \\\n"; } } QMakeFileContent.Append(QMakeTargetList.TrimEnd('\\')); var FullFileName = Path.Combine(MasterProjectPath.FullName, FileName); var FullQMakeDefinesFileName = Path.Combine(MasterProjectPath.FullName, QMakeDefinesFileName); var FullQMakeIncludesFileName = Path.Combine(MasterProjectPath.FullName, QMakeIncludesFileName); var FullQMakeSourcePriFileName = Path.Combine(MasterProjectPath.FullName, QMakeSourcePriFileName); var FullQMakeHeaderPriFileName = Path.Combine(MasterProjectPath.FullName, QMakeHeaderPriFileName); var FullQMakeConfigPriFileName = Path.Combine(MasterProjectPath.FullName, QMakeConfigPriFileName); WriteFileIfChanged(FullQMakeDefinesFileName, QMakeDefinesPriFileContent.ToString()); WriteFileIfChanged(FullQMakeIncludesFileName, QMakeIncludesPriFileContent.ToString()); WriteFileIfChanged(FullQMakeSourcePriFileName, QMakeSourcePriFileContent.ToString()); WriteFileIfChanged(FullQMakeHeaderPriFileName, QMakeHeaderPriFileContent.ToString()); WriteFileIfChanged(FullQMakeConfigPriFileName, QMakeConfigPriFileContent.ToString()); return(WriteFileIfChanged(FullFileName, QMakeFileContent.ToString())); }
/** * Returns a project navigator group to which the file should belong based on its path. * Creates a group tree if it doesn't exist yet. */ public XcodeFileGroup FindGroupByFullPath(ref Dictionary <string, XcodeFileGroup> Groups, string FullPath) { string RelativePath = (FullPath == XcodeProjectFileGenerator.MasterProjectRelativePath) ? "" : Utils.MakePathRelativeTo(FullPath, XcodeProjectFileGenerator.MasterProjectRelativePath); if (RelativePath.StartsWith("..")) { string UE4Dir = Path.GetFullPath(Directory.GetCurrentDirectory() + "../../.."); RelativePath = Utils.MakePathRelativeTo(FullPath, UE4Dir); } string[] Parts = RelativePath.Split(Path.DirectorySeparatorChar); string CurrentPath = ""; Dictionary <string, XcodeFileGroup> CurrentParent = Groups; foreach (string Part in Parts) { XcodeFileGroup CurrentGroup; if (CurrentPath != "") { CurrentPath += Path.DirectorySeparatorChar; } CurrentPath += Part; if (!CurrentParent.ContainsKey(CurrentPath)) { CurrentGroup = new XcodeFileGroup(Path.GetFileName(CurrentPath), CurrentPath); CurrentParent.Add(CurrentPath, CurrentGroup); } else { CurrentGroup = CurrentParent[CurrentPath]; } if (CurrentPath == RelativePath) { return(CurrentGroup); } CurrentParent = CurrentGroup.Children; } return(null); }
private bool WriteCMakeLists() { string BuildCommand = ""; var FileName = "CMakeLists.txt"; var CMakefileContent = new StringBuilder(); var CMakeSectionEnd = " )\n\n"; var CMakeSourceFilesList = "set(SOURCE_FILES \n"; var CMakeHeaderFilesList = "set(HEADER_FILES \n"; var CMakeConfigFilesList = "set(CONFIG_FILES \n"; var CMakeGameRootPath = ""; var CMakeUE4RootPath = "set(UE4_ROOT_PATH " + Path.GetFullPath(ProjectFileGenerator.RootRelativePath) + ")\n"; string GameProjectPath = ""; string GameProjectFile = ""; string CMakeGameProjectFile = ""; if (!String.IsNullOrEmpty(GameProjectName)) { CMakeGameRootPath = "set(GAME_ROOT_PATH \"" + UnrealBuildTool.GetUProjectPath() + "\")\n"; GameProjectPath = UnrealBuildTool.GetUProjectPath(); GameProjectFile = UnrealBuildTool.GetUProjectFile(); CMakeGameProjectFile = "set(GAME_PROJECT_FILE \"" + GameProjectFile + "\")\n"; BuildCommand = "set(BUILD mono ${UE4_ROOT_PATH}/Engine/Binaries/DotNET/UnrealBuildTool.exe )\n"; // -project=\"\\\"" + UnrealBuildTool.GetUProjectPath () + "/" + GameProjectName + ".uproject\\\"\")\n"; } else { BuildCommand = "set(BUILD bash ${UE4_ROOT_PATH}/Engine/Build/BatchFiles/Linux/Build.sh)\n"; } CMakefileContent.Append( "# Makefile generated by CMakefileGenerator.cs\n" + "# *DO NOT EDIT*\n\n" + "cmake_minimum_required (VERSION 2.6)\n" + "project (UE4)\n\n" + CMakeUE4RootPath + CMakeGameProjectFile + BuildCommand + CMakeGameRootPath + "\n" ); // Create SourceFiles, HeaderFiles, and ConfigFiles sections. var AllModuleFiles = DiscoverModules(); foreach (string CurModuleFile in AllModuleFiles) { var FoundFiles = SourceFileSearch.FindModuleSourceFiles(CurModuleFile, ExcludeNoRedistFiles: bExcludeNoRedistFiles); foreach (string CurSourceFile in FoundFiles) { string SourceFileRelativeToRoot = Utils.MakePathRelativeTo(CurSourceFile, Path.Combine(EngineRelativePath)); // Exclude Windows, Mac, and iOS only files/folders. // This got ugly quick. if (!SourceFileRelativeToRoot.Contains("Source/ThirdParty/") && !SourceFileRelativeToRoot.Contains("/Windows/") && !SourceFileRelativeToRoot.Contains("/Mac/") && !SourceFileRelativeToRoot.Contains("/IOS/") && !SourceFileRelativeToRoot.Contains("/iOS/") && !SourceFileRelativeToRoot.Contains("/VisualStudioSourceCodeAccess/") && !SourceFileRelativeToRoot.Contains("/XCodeSourceCodeAccess/") && !SourceFileRelativeToRoot.Contains("/WmfMedia/") && !SourceFileRelativeToRoot.Contains("/IOSDeviceProfileSelector/") && !SourceFileRelativeToRoot.Contains("/WindowsDeviceProfileSelector/") && !SourceFileRelativeToRoot.Contains("/WindowsMoviePlayer/") && !SourceFileRelativeToRoot.Contains("/AppleMoviePlayer/") && !SourceFileRelativeToRoot.Contains("/MacGraphicsSwitching/") && !SourceFileRelativeToRoot.Contains("/Apple/") && !SourceFileRelativeToRoot.Contains("/WinRT/") ) { if (SourceFileRelativeToRoot.EndsWith(".cpp")) { if (!SourceFileRelativeToRoot.StartsWith("..") && !Path.IsPathRooted(SourceFileRelativeToRoot)) { // SourceFileRelativeToRoot = "Engine/" + SourceFileRelativeToRoot; CMakeSourceFilesList += ("\t\"${UE4_ROOT_PATH}/Engine/" + SourceFileRelativeToRoot + "\"\n"); } else { if (String.IsNullOrEmpty(GameProjectName)) { // SourceFileRelativeToRoot = SourceFileRelativeToRoot.Substring (3); CMakeSourceFilesList += ("\t\"" + SourceFileRelativeToRoot.Substring(3) + "\"\n"); } else { CMakeSourceFilesList += ("\t\"${GAME_ROOT_PATH}/" + Utils.MakePathRelativeTo(CurSourceFile, GameProjectPath) + "\"\n"); } } } if (SourceFileRelativeToRoot.EndsWith(".h")) { if (!SourceFileRelativeToRoot.StartsWith("..") && !Path.IsPathRooted(SourceFileRelativeToRoot)) { // SourceFileRelativeToRoot = "Engine/" + SourceFileRelativeToRoot; CMakeHeaderFilesList += ("\t\"${UE4_ROOT_PATH}/Engine/" + SourceFileRelativeToRoot + "\"\n"); } else { if (String.IsNullOrEmpty(GameProjectName)) { // SourceFileRelativeToRoot = SourceFileRelativeToRoot.Substring (3); CMakeHeaderFilesList += ("\t\"" + SourceFileRelativeToRoot.Substring(3) + "\"\n"); } else { CMakeHeaderFilesList += ("\t\"${GAME_ROOT_PATH}/" + Utils.MakePathRelativeTo(CurSourceFile, GameProjectPath) + "\"\n"); } } } if (SourceFileRelativeToRoot.EndsWith(".cs")) { if (!SourceFileRelativeToRoot.StartsWith("..") && !Path.IsPathRooted(SourceFileRelativeToRoot)) { // SourceFileRelativeToRoot = "Engine/" + SourceFileRelativeToRoot; CMakeConfigFilesList += ("\t\"${UE4_ROOT_PATH}/Engine/" + SourceFileRelativeToRoot + "\"\n"); } else { if (String.IsNullOrEmpty(GameProjectName)) { // SourceFileRelativeToRoot = SourceFileRelativeToRoot.Substring (3); CMakeConfigFilesList += ("\t\"" + SourceFileRelativeToRoot.Substring(3) + "\"\n"); } else { CMakeConfigFilesList += ("\t\"${GAME_ROOT_PATH}/" + Utils.MakePathRelativeTo(CurSourceFile, GameProjectPath) + "\"\n"); }; } } } } } // Add section end to section strings; CMakeSourceFilesList += CMakeSectionEnd; CMakeHeaderFilesList += CMakeSectionEnd; CMakeConfigFilesList += CMakeSectionEnd; // Append sections to the CMakeLists.txt file CMakefileContent.Append(CMakeSourceFilesList); CMakefileContent.Append(CMakeHeaderFilesList); CMakefileContent.Append(CMakeConfigFilesList); string CMakeProjectCmdArg = ""; foreach (string TargetFilePath in DiscoverTargets()) { var TargetName = Utils.GetFilenameWithoutAnyExtensions(TargetFilePath); // Remove both ".cs" and ". foreach (UnrealTargetConfiguration CurConfiguration in Enum.GetValues(typeof(UnrealTargetConfiguration))) { if (CurConfiguration != UnrealTargetConfiguration.Unknown && CurConfiguration != UnrealTargetConfiguration.Development) { if (UnrealBuildTool.IsValidConfiguration(CurConfiguration)) { if (TargetName == GameProjectName || TargetName == (GameProjectName + "Editor")) { CMakeProjectCmdArg = " -project=\"\\\"${GAME_PROJECT_FILE}\\\"\""; } var ConfName = Enum.GetName(typeof(UnrealTargetConfiguration), CurConfiguration); CMakefileContent.Append(String.Format("add_custom_target({0}-Linux-{1} ${{BUILD}} {2} {0} Linux {1} $(ARGS))\n", TargetName, ConfName, CMakeProjectCmdArg)); } } } if (TargetName == GameProjectName || TargetName == (GameProjectName + "Editor")) { CMakeProjectCmdArg = " -project=\"\\\"${GAME_PROJECT_FILE}\\\"\""; } CMakefileContent.Append(String.Format("add_custom_target({0} ${{BUILD}} {1} {0} Linux Development $(ARGS) SOURCES ${{SOURCE_FILES}} ${{HEADER_FILES}} ${{CONFIG_FILES}})\n\n", TargetName, CMakeProjectCmdArg)); } var FullFileName = Path.Combine(MasterProjectRelativePath, FileName); return(WriteFileIfChanged(FullFileName, CMakefileContent.ToString())); }
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>(); // 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(Utils.MakePathRelativeTo(Dir, "../.."), '/') + "/"); } // 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 = ConvertPathToCygwin(Path.GetFullPath("../../")); string RemotePath = ConvertPath(Path.GetFullPath("../../")).Replace(" ", "\\ "); // 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); 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(); }
/// <summary> /// Discover and fill in the project info /// </summary> public static void FillProjectInfo() { DateTime StartTime = DateTime.Now; List <string> DirectoriesToSearch = new List <string>(); // Find all the .uprojectdirs files contained in the root folder and add their entries to the search array string RootDirectory = Path.Combine(Utils.GetExecutingAssemblyDirectory(), "..", "..", ".."); string EngineSourceDirectory = Path.GetFullPath(Path.Combine(RootDirectory, "Engine", "Source")); foreach (var File in Directory.EnumerateFiles(RootDirectory, "*.uprojectdirs", SearchOption.TopDirectoryOnly)) { string FilePath = Path.GetFullPath(File); Log.TraceVerbose("\tFound uprojectdirs file {0}", FilePath); using (StreamReader Reader = new StreamReader(FilePath)) { string LineRead; while ((LineRead = Reader.ReadLine()) != null) { string ProjDirEntry = LineRead.Trim(); if (String.IsNullOrEmpty(ProjDirEntry) == false) { if (ProjDirEntry.StartsWith(";")) { // Commented out line... skip it continue; } else { string DirPath = Path.GetFullPath(Path.Combine(RootDirectory, ProjDirEntry)); DirectoriesToSearch.Add(DirPath); } } } } } Log.TraceVerbose("\tFound {0} directories to search", DirectoriesToSearch.Count); // Initialize the target finding time to 0 TimeSpan TotalTargetTime = DateTime.Now - DateTime.Now; foreach (string DirToSearch in DirectoriesToSearch) { Log.TraceVerbose("\t\tSearching {0}", DirToSearch); if (Directory.Exists(DirToSearch)) { foreach (string SubDir in Directory.EnumerateDirectories(DirToSearch, "*", SearchOption.TopDirectoryOnly)) { Log.TraceVerbose("\t\t\tFound subdir {0}", SubDir); string[] SubDirFiles = Directory.GetFiles(SubDir, "*.uproject", SearchOption.TopDirectoryOnly); foreach (string UProjFile in SubDirFiles) { string RelativePath = Utils.MakePathRelativeTo(UProjFile, EngineSourceDirectory); Log.TraceVerbose("\t\t\t\t{0}", RelativePath); if (!ProjectInfoDictionary.ContainsKey(RelativePath)) { DateTime TargetStartTime = DateTime.Now; string SourceFolder = Path.Combine(Path.GetDirectoryName(UProjFile), "Source"); bool bIsCodeProject = Directory.Exists(SourceFolder); AddProject(RelativePath, bIsCodeProject); if (bIsCodeProject) { // Find all Target.cs files bool bFoundTargetFiles = false; if (!FindTargetFiles(SourceFolder, ref bFoundTargetFiles)) { Log.TraceVerbose("No target files found under " + SourceFolder); } } DateTime TargetStopTime = DateTime.Now; TotalTargetTime += TargetStopTime - TargetStartTime; } } } } else { Log.TraceVerbose("ProjectInfo: Skipping directory {0} from .uprojectdirs file as it doesn't exist.", DirToSearch); } } DateTime StopTime = DateTime.Now; if (BuildConfiguration.bPrintPerformanceInfo) { TimeSpan TotalProjectInfoTime = StopTime - StartTime; Log.TraceInformation("FillProjectInfo took {0} milliseconds (AddTargetInfo {1} ms)", TotalProjectInfoTime.Milliseconds, TotalTargetTime.Milliseconds); } if (UnrealBuildTool.CommandLineContains("-dumpprojectinfo")) { UProjectInfo.DumpProjectInfo(); } }
public override CPPOutput CompileCPPFiles(UEBuildTarget Target, CPPEnvironment CompileEnvironment, List <FileItem> SourceFiles, string ModuleName) { var EnvVars = VCEnvironment.SetEnvironment(CompileEnvironment.Config.Target.Platform); 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 + "." + Path.GetFileName(CompileEnvironment.Config.PrecompiledHeaderIncludeFilename) + ".cpp"; string PCHCPPPath = Path.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.BuildPlatformDictionary[UnrealTargetPlatform.UWP].GetBinaryExtension(UEBuildBinaryType.PrecompiledHeader); // Add the precompiled header file to the produced items list. FileItem PrecompiledHeaderFile = FileItem.GetItemByPath( Path.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 = Path.GetFileNameWithoutExtension(CompileEnvironment.Config.PrecompiledHeaderIncludeFilename); 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.BuildPlatformDictionary[UnrealTargetPlatform.UWP].GetBinaryExtension(UEBuildBinaryType.Object); // Add the object file to the produced item list. FileItem ObjectFile = FileItem.GetItemByPath( Path.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 + "." + Path.GetFileName(CompileEnvironment.Config.PrecompiledHeaderIncludeFilename); } // Files creating a PCH use a PDB per file. else if (CompileEnvironment.Config.PrecompiledHeaderAction == PrecompiledHeaderAction.Create) { PDBFileName = "PCH." + ModuleName + "." + Path.GetFileName(CompileEnvironment.Config.PrecompiledHeaderIncludeFilename); 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.GetItemByPath( Path.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 = Path.GetFullPath("."); 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); }
private bool WriteQMakePro() { string GameProjectPath = ""; string GameProjectFile = ""; string GameProjectRootPath = ""; string BuildCommand = ""; string QMakeGameProjectFile = ""; if (!String.IsNullOrEmpty(GameProjectName)) { GameProjectPath = UnrealBuildTool.GetUProjectPath(); GameProjectFile = UnrealBuildTool.GetUProjectFile(); QMakeGameProjectFile = "gameProjectFile=" + GameProjectFile + "\n"; BuildCommand = "build=mono $$unrealRootPath/Engine/Binaries/DotNET/UnrealBuildTool.exe\n\n"; } else { BuildCommand = "build=bash $$unrealRootPath/Engine/Build/BatchFiles/Linux/Build.sh\n"; } var UnrealRootPath = Path.GetFullPath(ProjectFileGenerator.RootRelativePath); var FileName = MasterProjectName + ".pro"; var QMakeFileContent = new StringBuilder(); var QMakeSectionEnd = " \n\n"; var QMakeSourceFilesList = "SOURCES += \\ \n"; var QMakeHeaderFilesList = "HEADERS += \\ \n"; var QMakeConfigFilesList = "OTHER_FILES += \\ \n"; var QMakeTargetList = "QMAKE_EXTRA_TARGETS += \\ \n"; if (!String.IsNullOrEmpty(GameProjectName)) { GameProjectRootPath = GameProjectName + "RootPath=" + GameProjectPath + "\n\n"; } QMakeFileContent.Append( "# UnrealEngine.pro generated by QMakefileGenerator.cs\n" + "# *DO NOT EDIT*\n\n" + "TEMPLATE = aux\n" + "CONFIG -= console\n" + "CONFIG -= app_bundle\n" + "CONFIG -= qt\n\n" + "TARGET = UE4 \n\n" + "unrealRootPath=" + UnrealRootPath + "\n" + GameProjectRootPath + QMakeGameProjectFile + BuildCommand + "args=$(ARGS)\n\n" ); // Create SourceFiles, HeaderFiles, and ConfigFiles sections. var AllModuleFiles = DiscoverModules(); foreach (string CurModuleFile in AllModuleFiles) { var FoundFiles = SourceFileSearch.FindModuleSourceFiles(CurModuleFile, ExcludeNoRedistFiles: bExcludeNoRedistFiles); foreach (string CurSourceFile in FoundFiles) { string SourceFileRelativeToRoot = Utils.MakePathRelativeTo(CurSourceFile, Path.Combine(EngineRelativePath)); // Exclude Windows, Mac, and iOS only files/folders. // This got ugly quick. if (!SourceFileRelativeToRoot.Contains("Source/ThirdParty/") && !SourceFileRelativeToRoot.Contains("/Windows/") && !SourceFileRelativeToRoot.Contains("/Mac/") && !SourceFileRelativeToRoot.Contains("/IOS/") && !SourceFileRelativeToRoot.Contains("/iOS/") && !SourceFileRelativeToRoot.Contains("/VisualStudioSourceCodeAccess/") && !SourceFileRelativeToRoot.Contains("/XCodeSourceCodeAccess/") && !SourceFileRelativeToRoot.Contains("/WmfMedia/") && !SourceFileRelativeToRoot.Contains("/IOSDeviceProfileSelector/") && !SourceFileRelativeToRoot.Contains("/WindowsDeviceProfileSelector/") && !SourceFileRelativeToRoot.Contains("/WindowsMoviePlayer/") && !SourceFileRelativeToRoot.Contains("/AppleMoviePlayer/") && !SourceFileRelativeToRoot.Contains("/MacGraphicsSwitching/") && !SourceFileRelativeToRoot.Contains("/Apple/") && !SourceFileRelativeToRoot.Contains("/WinRT/") ) { if (SourceFileRelativeToRoot.EndsWith(".cpp")) { if (!SourceFileRelativeToRoot.StartsWith("..") && !Path.IsPathRooted(SourceFileRelativeToRoot)) { // SourceFileRelativeToRoot = "Engine/" + SourceFileRelativeToRoot; QMakeSourceFilesList += ("\t\"" + "$$unrealRootPath/Engine/" + SourceFileRelativeToRoot + "\" \\\n"); } else { if (String.IsNullOrEmpty(GameProjectName)) { // SourceFileRelativeToRoot = SourceFileRelativeToRoot.Substring (3); QMakeSourceFilesList += ("\t\"" + SourceFileRelativeToRoot.Substring(3) + "\" \\\n"); } else if (!String.IsNullOrEmpty(GameProjectName)) { QMakeSourceFilesList += ("\t\"$$" + GameProjectName + "RootPath/" + Utils.MakePathRelativeTo(CurSourceFile, GameProjectPath) + "\" \\\n"); } else { System.Console.WriteLine("Error!, you should not be here."); } } } if (SourceFileRelativeToRoot.EndsWith(".h")) { if (!SourceFileRelativeToRoot.StartsWith("..") && !Path.IsPathRooted(SourceFileRelativeToRoot)) { // SourceFileRelativeToRoot = "Engine/" + SourceFileRelativeToRoot; QMakeHeaderFilesList += ("\t\"" + "$$unrealRootPath/Engine/" + SourceFileRelativeToRoot + "\" \\\n"); } else { if (String.IsNullOrEmpty(GameProjectName)) { // SourceFileRelativeToRoot = SourceFileRelativeToRoot.Substring (3); QMakeHeaderFilesList += ("\t\"" + SourceFileRelativeToRoot.Substring(3) + "\" \\\n"); } else if (!String.IsNullOrEmpty(GameProjectName)) { QMakeHeaderFilesList += ("\t\"$$" + GameProjectName + "RootPath/" + Utils.MakePathRelativeTo(CurSourceFile, GameProjectPath) + "\" \\\n"); } else { System.Console.WriteLine("Error!, you should not be here."); } } } if (SourceFileRelativeToRoot.EndsWith(".cs")) { if (!SourceFileRelativeToRoot.StartsWith("..") && !Path.IsPathRooted(SourceFileRelativeToRoot)) { // SourceFileRelativeToRoot = "Engine/" + SourceFileRelativeToRoot; QMakeConfigFilesList += ("\t\"" + "$$unrealRootPath/Engine/" + SourceFileRelativeToRoot + "\" \\\n"); } else { if (String.IsNullOrEmpty(GameProjectName)) { // SourceFileRelativeToRoot = SourceFileRelativeToRoot.Substring (3); QMakeConfigFilesList += ("\t\"" + SourceFileRelativeToRoot.Substring(3) + "\" \\\n"); } else if (!String.IsNullOrEmpty(GameProjectName)) { QMakeConfigFilesList += ("\t\"$$" + GameProjectName + "RootPath/" + Utils.MakePathRelativeTo(CurSourceFile, GameProjectPath) + "\" \\\n"); } else { System.Console.WriteLine("Error!, you should not be here."); } } } } } } // Add section end to section strings; QMakeSourceFilesList += QMakeSectionEnd; QMakeHeaderFilesList += QMakeSectionEnd; QMakeConfigFilesList += QMakeSectionEnd; // Append sections to the QMakeLists.txt file QMakeFileContent.Append(QMakeSourceFilesList); QMakeFileContent.Append(QMakeHeaderFilesList); QMakeFileContent.Append(QMakeConfigFilesList); string QMakeProjectCmdArg = ""; foreach (string TargetFilePath in DiscoverTargets()) { var TargetName = Utils.GetFilenameWithoutAnyExtensions(TargetFilePath); // Remove both ".cs" and ". foreach (UnrealTargetConfiguration CurConfiguration in Enum.GetValues(typeof(UnrealTargetConfiguration))) { if (CurConfiguration != UnrealTargetConfiguration.Unknown && CurConfiguration != UnrealTargetConfiguration.Development) { if (UnrealBuildTool.IsValidConfiguration(CurConfiguration)) { if (TargetName == GameProjectName || TargetName == (GameProjectName + "Editor")) { QMakeProjectCmdArg = " -project=\"\\\"$$gameProjectFile\\\"\""; } var ConfName = Enum.GetName(typeof(UnrealTargetConfiguration), CurConfiguration); QMakeFileContent.Append(String.Format("{0}-Linux-{1}.commands = $$build {2} {0} Linux {1} $$args\n", TargetName, ConfName, QMakeProjectCmdArg)); QMakeTargetList += "\t" + TargetName + "-Linux-" + ConfName + " \\\n"; // , TargetName, ConfName); } } } if (TargetName == GameProjectName || TargetName == (GameProjectName + "Editor")) { QMakeProjectCmdArg = " -project=\"\\\"$$gameProjectFile\\\"\""; } QMakeFileContent.Append(String.Format("{0}.commands = $$build {1} {0} Linux Development $$args\n\n", TargetName, QMakeProjectCmdArg)); QMakeTargetList += "\t" + TargetName + " \\\n"; } QMakeFileContent.Append(QMakeTargetList.TrimEnd('\\')); var FullFileName = Path.Combine(MasterProjectRelativePath, FileName); return(WriteFileIfChanged(FullFileName, QMakeFileContent.ToString())); }
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"); var CMakeGameRootPath = ""; var CMakeUE4RootPath = "set(UE4_ROOT_PATH " + Utils.CleanDirectorySeparators(Path.GetFullPath(ProjectFileGenerator.RootRelativePath), '/') + ")\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: { HostArchitecture = "Mac"; BuildCommand = "set(BUILD cd \"${UE4_ROOT_PATH}\" && bash \"${UE4_ROOT_PATH}/Engine/Build/BatchFiles/" + HostArchitecture + "/Build.sh\")\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"; 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" + 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(Path.GetFullPath(RootRelativePath))) { IncludeDirectories.Add(IncludeDirectory.Replace(Path.GetFullPath(RootRelativePath), "${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}\""; } if (!String.IsNullOrEmpty(HostArchitecture)) { 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); }
/// <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", GetElfName(NMakeOutputPath)); string DebuggerFlavor = "MLDebugger"; string SymFile = Utils.MakePathRelativeTo(NMakeOutputPath.Directory.FullName, ProjectFilePath.Directory.FullName); SymFile = Path.Combine(SymFile, "..\\..\\Intermediate\\Lumin\\Mabu\\Binaries", Path.ChangeExtension(GetElfName(NMakeOutputPath), ".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)); } }
private bool WriteCMakeLists() { string BuildCommand = ""; var FileName = "CMakeLists.txt"; var CMakefileContent = new StringBuilder(); var CMakeSectionEnd = " )\n\n"; var CMakeSourceFilesList = "set(SOURCE_FILES \n"; var CMakeHeaderFilesList = "set(HEADER_FILES \n"; var CMakeConfigFilesList = "set(CONFIG_FILES \n"; var IncludeDirectoriesList = "include_directories( \n"; var PreprocessorDefinitionsList = "add_definitions( \n"; var CMakeGameRootPath = ""; var CMakeUE4RootPath = "set(UE4_ROOT_PATH " + Path.GetFullPath(ProjectFileGenerator.RootRelativePath) + ")\n"; string GameProjectPath = ""; string GameProjectFile = ""; string CMakeGameProjectFile = ""; bool bIsMac = BuildHostPlatform.Current.Platform == UnrealTargetPlatform.Mac; bool bIsLinux = BuildHostPlatform.Current.Platform == UnrealTargetPlatform.Linux; bool bIsWin64 = BuildHostPlatform.Current.Platform == UnrealTargetPlatform.Win64; String HostArchitecture = null; if (bIsLinux) { HostArchitecture = "Linux"; } else if (bIsMac) { HostArchitecture = "Mac"; } else if (bIsWin64) { HostArchitecture = "Win64"; } else { throw new BuildException("ERROR: CMakefileGenerator does not support this platform"); } if (!String.IsNullOrEmpty(GameProjectName)) { CMakeGameRootPath = "set(GAME_ROOT_PATH \"" + UnrealBuildTool.GetUProjectPath() + "\")\n"; GameProjectPath = UnrealBuildTool.GetUProjectPath(); GameProjectFile = UnrealBuildTool.GetUProjectFile(); CMakeGameProjectFile = "set(GAME_PROJECT_FILE \"" + GameProjectFile + "\")\n"; BuildCommand = "set(BUILD mono ${UE4_ROOT_PATH}/Engine/Binaries/DotNET/UnrealBuildTool.exe )\n"; } else if (bIsLinux || bIsMac) { BuildCommand = String.Format("set(BUILD cd ${{UE4_ROOT_PATH}} && bash ${{UE4_ROOT_PATH}}/Engine/Build/BatchFiles/{0}/Build.sh)\n", HostArchitecture); } else if (bIsWin64) { BuildCommand = "set(BUILD bash ${{UE4_ROOT_PATH}}/Engine/Build/BatchFiles/Build.bat)\n"; } CMakefileContent.Append( "# Makefile generated by CMakefileGenerator.cs\n" + "# *DO NOT EDIT*\n\n" + "cmake_minimum_required (VERSION 2.6)\n" + "project (UE4)\n\n" + CMakeUE4RootPath + CMakeGameProjectFile + BuildCommand + CMakeGameRootPath + "\n" ); List <String> IncludeDirectories = new List <String>(); List <String> PreprocessorDefinitions = new List <String>(); foreach (var CurProject in GeneratedProjectFiles) { foreach (var CurPath in CurProject.IntelliSenseIncludeSearchPaths) { string IncludeDirectory = GetIncludeDirectory(CurPath, Path.GetDirectoryName(CurProject.ProjectFilePath)); if (IncludeDirectory != null && !IncludeDirectories.Contains(IncludeDirectory)) { IncludeDirectories.Add(IncludeDirectory); } } foreach (var CurDefinition in CurProject.IntelliSensePreprocessorDefinitions) { string Definition = CurDefinition; 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(); foreach (string CurModuleFile in AllModuleFiles) { var FoundFiles = SourceFileSearch.FindModuleSourceFiles(CurModuleFile, ExcludeNoRedistFiles: bExcludeNoRedistFiles); foreach (string CurSourceFile in FoundFiles) { string SourceFileRelativeToRoot = Utils.MakePathRelativeTo(CurSourceFile, Path.Combine(EngineRelativePath)); // Exclude files/folders on a per-platform basis. if ((bIsLinux && IsLinuxFiltered(SourceFileRelativeToRoot)) || (bIsMac && IsMacFiltered(SourceFileRelativeToRoot)) || (bIsWin64 && IsWinFiltered(SourceFileRelativeToRoot)) ) { if (SourceFileRelativeToRoot.EndsWith(".cpp")) { if (!SourceFileRelativeToRoot.StartsWith("..") && !Path.IsPathRooted(SourceFileRelativeToRoot)) { // SourceFileRelativeToRoot = "Engine/" + SourceFileRelativeToRoot; CMakeSourceFilesList += ("\t\"${UE4_ROOT_PATH}/Engine/" + SourceFileRelativeToRoot + "\"\n"); } else { if (String.IsNullOrEmpty(GameProjectName)) { // SourceFileRelativeToRoot = SourceFileRelativeToRoot.Substring (3); CMakeSourceFilesList += ("\t\"" + SourceFileRelativeToRoot.Substring(3) + "\"\n"); } else { CMakeSourceFilesList += ("\t\"${GAME_ROOT_PATH}/" + Utils.MakePathRelativeTo(CurSourceFile, GameProjectPath) + "\"\n"); } } } if (SourceFileRelativeToRoot.EndsWith(".h")) { if (!SourceFileRelativeToRoot.StartsWith("..") && !Path.IsPathRooted(SourceFileRelativeToRoot)) { // SourceFileRelativeToRoot = "Engine/" + SourceFileRelativeToRoot; CMakeHeaderFilesList += ("\t\"${UE4_ROOT_PATH}/Engine/" + SourceFileRelativeToRoot + "\"\n"); } else { if (String.IsNullOrEmpty(GameProjectName)) { // SourceFileRelativeToRoot = SourceFileRelativeToRoot.Substring (3); CMakeHeaderFilesList += ("\t\"" + SourceFileRelativeToRoot.Substring(3) + "\"\n"); } else { CMakeHeaderFilesList += ("\t\"${GAME_ROOT_PATH}/" + Utils.MakePathRelativeTo(CurSourceFile, GameProjectPath) + "\"\n"); } } } if (SourceFileRelativeToRoot.EndsWith(".cs")) { if (!SourceFileRelativeToRoot.StartsWith("..") && !Path.IsPathRooted(SourceFileRelativeToRoot)) { // SourceFileRelativeToRoot = "Engine/" + SourceFileRelativeToRoot; CMakeConfigFilesList += ("\t\"${UE4_ROOT_PATH}/Engine/" + SourceFileRelativeToRoot + "\"\n"); } else { if (String.IsNullOrEmpty(GameProjectName)) { // SourceFileRelativeToRoot = SourceFileRelativeToRoot.Substring (3); CMakeConfigFilesList += ("\t\"" + SourceFileRelativeToRoot.Substring(3) + "\"\n"); } else { CMakeConfigFilesList += ("\t\"${GAME_ROOT_PATH}/" + Utils.MakePathRelativeTo(CurSourceFile, GameProjectPath) + "\"\n"); }; } } } } } foreach (string IncludeDirectory in IncludeDirectories) { IncludeDirectoriesList += ("\t\"" + IncludeDirectory + "\"\n"); } foreach (string PreprocessorDefinition in PreprocessorDefinitions) { PreprocessorDefinitionsList += ("\t-D" + PreprocessorDefinition + "\n"); } // Add section end to section strings; CMakeSourceFilesList += CMakeSectionEnd; CMakeHeaderFilesList += CMakeSectionEnd; CMakeConfigFilesList += CMakeSectionEnd; IncludeDirectoriesList += CMakeSectionEnd; PreprocessorDefinitionsList += 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 = Utils.GetFilenameWithoutAnyExtensions(TargetFile.TargetFilePath); // Remove both ".cs" and ". foreach (UnrealTargetConfiguration CurConfiguration in Enum.GetValues(typeof(UnrealTargetConfiguration))) { if (CurConfiguration != UnrealTargetConfiguration.Unknown && CurConfiguration != UnrealTargetConfiguration.Development) { if (UnrealBuildTool.IsValidConfiguration(CurConfiguration)) { if (TargetName == GameProjectName || TargetName == (GameProjectName + "Editor")) { CMakeProjectCmdArg = " -project=\"\\\"${GAME_PROJECT_FILE}\\\"\""; } var ConfName = Enum.GetName(typeof(UnrealTargetConfiguration), CurConfiguration); CMakefileContent.Append(String.Format("add_custom_target({0}-{3}-{1} ${{BUILD}} {2} {0} {3} {1} $(ARGS))\n", TargetName, ConfName, CMakeProjectCmdArg, HostArchitecture)); } } } if (TargetName == GameProjectName || TargetName == (GameProjectName + "Editor")) { CMakeProjectCmdArg = " -project=\"\\\"${GAME_PROJECT_FILE}\\\"\""; } if (HostArchitecture != null) { CMakefileContent.Append(String.Format("add_custom_target({0} ${{BUILD}} {1} {0} {2} Development $(ARGS) SOURCES ${{SOURCE_FILES}} ${{HEADER_FILES}} ${{CONFIG_FILES}})\n\n", TargetName, CMakeProjectCmdArg, HostArchitecture)); } } } var FullFileName = Path.Combine(MasterProjectRelativePath, FileName); return(WriteFileIfChanged(FullFileName, CMakefileContent.ToString())); }