/// <summary> /// Adds all of the PS4 C# projects to the master project /// </summary> private void AddPS4Projects(MasterProjectFolder Folder) { string ProjectFolderName = Path.Combine(EngineRelativePath, "Source", "Programs", "PS4"); DirectoryInfo ProjectFolderInfo = new DirectoryInfo(ProjectFolderName); if (ProjectFolderInfo.Exists) { Folder.ChildProjects.Add(AddSimpleCSharpProject("PS4/PS4DevKitUtil")); } }
/// <summary> /// Adds UnrealBuildTool to the master project /// </summary> private void AddUnrealBuildToolProject( MasterProjectFolder ProgramsFolder, IEnumerable<ProjectFile> Dependencies ) { var ProjectFileName = Utils.MakePathRelativeTo( Path.Combine( Path.Combine( EngineRelativePath, "Source" ), "Programs", "UnrealBuildTool", "UnrealBuildTool.csproj" ), MasterProjectRelativePath ); var UnrealBuildToolProject = new VCSharpProjectFile( ProjectFileName ); UnrealBuildToolProject.ShouldBuildForAllSolutionTargets = true; foreach (var Dependent in Dependencies) { UnrealBuildToolProject.AddDependsOnProject( Dependent ); } // Store it off as we need it when generating target projects. UBTProject = UnrealBuildToolProject; // Add the project AddExistingProjectFile(UnrealBuildToolProject, bNeedsAllPlatformAndConfigurations:true, bForceDevelopmentConfiguration:true); // Put this in a solution folder ProgramsFolder.ChildProjects.Add( UnrealBuildToolProject ); }
/// <summary> /// Adds all of the HTML5 C# projects to the master project /// </summary> private void AddHTML5Projects(MasterProjectFolder Folder) { string ProjectFolderName = Path.Combine(EngineRelativePath, "Source", "Programs", "HTML5"); DirectoryInfo ProjectFolderInfo = new DirectoryInfo(ProjectFolderName); if (ProjectFolderInfo.Exists) { Folder.ChildProjects.Add(AddSimpleCSharpProject("HTML5/HTML5LaunchHelper", true)); // Build by default; needed for UAT. } }
/// <summary> /// Adds all of the IOS C# projects to the master project /// </summary> private void AddIOSProjects(MasterProjectFolder Folder) { string ProjectFolderName = Path.Combine( EngineRelativePath, "Source", "Programs", "IOS" ); DirectoryInfo ProjectFolderInfo = new DirectoryInfo( ProjectFolderName ); if( ProjectFolderInfo.Exists ) { Folder.ChildProjects.Add( AddSimpleCSharpProject( "IOS/iPhonePackager" ) ); Folder.ChildProjects.Add( AddSimpleCSharpProject( "IOS/DeploymentInterface", true ) ); // Build by default; needed for UAT. Folder.ChildProjects.Add( AddSimpleCSharpProject( "IOS/DeploymentServer" ) ); Folder.ChildProjects.Add( AddSimpleCSharpProject( "IOS/MobileDeviceInterface" ) ); } }
/// <summary> /// Adds all of the Android C# projects to the master project /// </summary> private void AddAndroidProjects(MasterProjectFolder Folder) { }
/// <summary> /// Adds all .automation.csproj files to the solution. /// </summary> void AddAutomationModules(MasterProjectFolder ProgramsFolder) { var Folder = ProgramsFolder.AddSubFolder("Automation"); var AllGameFolders = UEBuildTarget.DiscoverAllGameFolders(); var BuildFolders = new List<string>(AllGameFolders.Count); foreach (var GameFolder in AllGameFolders) { var GameBuildFolder = Path.Combine(GameFolder, "Build"); if (Directory.Exists(GameBuildFolder)) { BuildFolders.Add(GameBuildFolder); } } // Find all the automation modules .csproj files to add var ModuleFiles = RulesCompiler.FindAllRulesSourceFiles(RulesCompiler.RulesFileType.AutomationModule, BuildFolders); foreach (var ProjectFile in ModuleFiles) { FileInfo Info = new FileInfo(Path.Combine(ProjectFile)); if (Info.Exists) { var RelativeFileName = Utils.MakePathRelativeTo(ProjectFile, MasterProjectRelativePath); var Project = new VCSharpProjectFile(RelativeFileName); Project.ShouldBuildForAllSolutionTargets = true; AddExistingProjectFile(Project, bForceDevelopmentConfiguration: true); Folder.ChildProjects.Add( Project ); } } }
/// <summary> /// Validate the specified Folder. Default implementation requires /// for project file names to be unique! /// </summary> /// <param name="Folder">Folder.</param> /// <param name="MasterProjectFolderPath">Parent master project folder path.</param> protected virtual void Validate(MasterProjectFolder Folder, string MasterProjectFolderPath) { foreach (var CurChildProject in Folder.ChildProjects) { foreach (var OtherChildProject in Folder.ChildProjects) { if (CurChildProject != OtherChildProject) { if (Utils.GetFilenameWithoutAnyExtensions(CurChildProject.ProjectFilePath).Equals(Utils.GetFilenameWithoutAnyExtensions(OtherChildProject.ProjectFilePath), StringComparison.InvariantCultureIgnoreCase)) { throw new BuildException("Detected collision between two project files with the same path in the same master project folder, " + OtherChildProject.ProjectFilePath + " and " + CurChildProject.ProjectFilePath + " (master project folder: " + MasterProjectFolderPath + ")"); } } } } foreach (var SubFolder in Folder.SubFolders) { // If the parent folder already has a child project or file item with the same name as this sub-folder, then // that's considered an error (it should never have been allowed to have a folder name that collided // with project file names or file items, as that's not supported in Visual Studio.) foreach (var CurChildProject in Folder.ChildProjects) { if (Utils.GetFilenameWithoutAnyExtensions(CurChildProject.ProjectFilePath).Equals(SubFolder.FolderName, StringComparison.InvariantCultureIgnoreCase)) { throw new BuildException("Detected collision between a master project sub-folder " + SubFolder.FolderName + " and a project within the outer folder " + CurChildProject.ProjectFilePath + " (master project folder: " + MasterProjectFolderPath + ")"); } } foreach (var CurFile in Folder.Files) { if (Path.GetFileName(CurFile).Equals(SubFolder.FolderName, StringComparison.InvariantCultureIgnoreCase)) { throw new BuildException("Detected collision between a master project sub-folder " + SubFolder.FolderName + " and a file within the outer folder " + CurFile + " (master project folder: " + MasterProjectFolderPath + ")"); } } foreach (var CurFolder in Folder.SubFolders) { if (CurFolder != SubFolder) { if (CurFolder.FolderName.Equals(SubFolder.FolderName, StringComparison.InvariantCultureIgnoreCase)) { throw new BuildException("Detected collision between a master project sub-folder " + SubFolder.FolderName + " and a sibling folder " + CurFolder.FolderName + " (master project folder: " + MasterProjectFolderPath + ")"); } } } } }
/// <summary> /// Adds UnrealBuildTool to the master project /// </summary> private void AddUnrealBuildToolProject( MasterProjectFolder ProgramsFolder, IEnumerable<ProjectFile> Dependencies ) { FileReference ProjectFileName = FileReference.Combine(UnrealBuildTool.EngineSourceDirectory, "Programs", "UnrealBuildTool", "UnrealBuildTool.csproj" ); VCSharpProjectFile UnrealBuildToolProject = new VCSharpProjectFile( ProjectFileName ); UnrealBuildToolProject.ShouldBuildForAllSolutionTargets = true; foreach (ProjectFile Dependent in Dependencies) { UnrealBuildToolProject.AddDependsOnProject( Dependent ); } // Store it off as we need it when generating target projects. UBTProject = UnrealBuildToolProject; // Add the project AddExistingProjectFile(UnrealBuildToolProject, bNeedsAllPlatformAndConfigurations:true, bForceDevelopmentConfiguration:true); // Put this in a solution folder ProgramsFolder.ChildProjects.Add( UnrealBuildToolProject ); }
/// <summary> /// Adds UnrealBuildTool to the master project /// </summary> private void AddUnrealBuildToolProject( MasterProjectFolder ProgramsFolder ) { var ProjectFileName = Utils.MakePathRelativeTo( Path.Combine( Path.Combine( EngineRelativePath, "Source" ), "Programs", "UnrealBuildTool", "UnrealBuildTool.csproj" ), MasterProjectRelativePath ); var UnrealBuildToolProject = new VCSharpProjectFile( ProjectFileName ); // Store it off as we need it when generating target projects. UBTProject = UnrealBuildToolProject; // Add the project AddExistingProjectFile(UnrealBuildToolProject, bNeedsAllPlatformAndConfigurations:true, bForceDevelopmentConfiguration:true); // Put this in a solution folder ProgramsFolder.ChildProjects.Add( UnrealBuildToolProject ); }
/// <summary> /// Recursively collapses all sub-folders that are redundant. Should only be called after we're done adding /// files and projects to the master project. /// </summary> /// <param name="Folder">The folder whose sub-folders we should potentially collapse into</param> void EliminateRedundantMasterProjectSubFolders( MasterProjectFolder Folder, string ParentMasterProjectFolderPath ) { // NOTE: This is for diagnostics output only var MasterProjectFolderPath = String.IsNullOrEmpty( ParentMasterProjectFolderPath ) ? Folder.FolderName : ( ParentMasterProjectFolderPath + "/" + Folder.FolderName ); // We can eliminate folders that meet all of these requirements: // 1) Have only a single project file in them // 2) Have no files in the folder except project files, and no sub-folders // 3) The project file matches the folder name // // Additionally, if KeepSourceSubDirectories==false, we can eliminate directories called "Source". // // Also, we can kill folders that are completely empty. foreach( var SubFolder in Folder.SubFolders ) { // Recurse EliminateRedundantMasterProjectSubFolders( SubFolder, MasterProjectFolderPath ); } var SubFoldersToAdd = new List<MasterProjectFolder>(); var SubFoldersToRemove = new List<MasterProjectFolder>(); foreach( var SubFolder in Folder.SubFolders ) { bool CanCollapseFolder = false; // 1) if( SubFolder.ChildProjects.Count == 1 ) { // 2) if( SubFolder.Files.Count == 0 && SubFolder.SubFolders.Count == 0 ) { // 3) if (SubFolder.FolderName.Equals(Utils.GetFilenameWithoutAnyExtensions(SubFolder.ChildProjects[0].ProjectFilePath), StringComparison.InvariantCultureIgnoreCase)) { CanCollapseFolder = true; } } } if( !KeepSourceSubDirectories ) { if( SubFolder.FolderName.Equals( "Source", StringComparison.InvariantCultureIgnoreCase ) ) { // Avoid collapsing the Engine's Source directory, since there are so many other solution folders in // the parent directory. if( !Folder.FolderName.Equals( "Engine", StringComparison.InvariantCultureIgnoreCase ) ) { CanCollapseFolder = true; } } } if( SubFolder.ChildProjects.Count == 0 && SubFolder.Files.Count == 0 & SubFolder.SubFolders.Count == 0 ) { // Folder is totally empty CanCollapseFolder = true; } if( CanCollapseFolder ) { // OK, this folder is redundant and can be collapsed away. SubFoldersToAdd.AddRange( SubFolder.SubFolders ); SubFolder.SubFolders.Clear(); Folder.ChildProjects.AddRange( SubFolder.ChildProjects ); SubFolder.ChildProjects.Clear(); Folder.Files.AddRange( SubFolder.Files ); SubFolder.Files.Clear(); SubFoldersToRemove.Add( SubFolder ); } } foreach( var SubFolderToRemove in SubFoldersToRemove ) { Folder.SubFolders.Remove( SubFolderToRemove ); } Folder.SubFolders.AddRange( SubFoldersToAdd ); // After everything has been collapsed, do a bit of data validation { foreach( var CurChildProject in Folder.ChildProjects ) { foreach( var OtherChildProject in Folder.ChildProjects ) { if( CurChildProject != OtherChildProject ) { if (Utils.GetFilenameWithoutAnyExtensions(CurChildProject.ProjectFilePath).Equals(Utils.GetFilenameWithoutAnyExtensions(OtherChildProject.ProjectFilePath), StringComparison.InvariantCultureIgnoreCase)) { throw new BuildException( "Detected collision between two project files with the same path in the same master project folder, " + OtherChildProject.ProjectFilePath + " and " + CurChildProject.ProjectFilePath + " (master project folder: " + MasterProjectFolderPath + ")" ); } } } } foreach( var SubFolder in Folder.SubFolders ) { // If the parent folder already has a child project or file item with the same name as this sub-folder, then // that's considered an error (it should never have been allowed to have a folder name that collided // with project file names or file items, as that's not supported in Visual Studio.) foreach( var CurChildProject in Folder.ChildProjects ) { if (Utils.GetFilenameWithoutAnyExtensions(CurChildProject.ProjectFilePath).Equals(SubFolder.FolderName, StringComparison.InvariantCultureIgnoreCase)) { throw new BuildException( "Detected collision between a master project sub-folder " + SubFolder.FolderName + " and a project within the outer folder " + CurChildProject.ProjectFilePath + " (master project folder: " + MasterProjectFolderPath + ")" ); } } foreach( var CurFile in Folder.Files ) { if( Path.GetFileName( CurFile ).Equals( SubFolder.FolderName, StringComparison.InvariantCultureIgnoreCase ) ) { throw new BuildException( "Detected collision between a master project sub-folder " + SubFolder.FolderName + " and a file within the outer folder " + CurFile + " (master project folder: " + MasterProjectFolderPath + ")" ); } } foreach( var CurFolder in Folder.SubFolders ) { if( CurFolder != SubFolder ) { if( CurFolder.FolderName.Equals( SubFolder.FolderName, StringComparison.InvariantCultureIgnoreCase ) ) { throw new BuildException( "Detected collision between a master project sub-folder " + SubFolder.FolderName + " and a sibling folder " + CurFolder.FolderName + " (master project folder: " + MasterProjectFolderPath + ")" ); } } } } } }
/// <summary> /// Adds all game project files, including target projects and config files /// </summary> private void AddAllGameProjects(Dictionary<DirectoryReference, ProjectFile> GameProjects, string SupportedPlatformNames, MasterProjectFolder ProjectsFolder) { foreach( KeyValuePair<DirectoryReference, ProjectFile> GameFolderAndProjectFile in GameProjects ) { DirectoryReference GameProjectDirectory = GameFolderAndProjectFile.Key; // @todo projectfiles: We have engine localization files, but should we also add GAME localization files? // Game config files if( IncludeConfigFiles ) { DirectoryReference GameConfigDirectory = DirectoryReference.Combine(GameProjectDirectory, "Config"); if( GameConfigDirectory.Exists( ) ) { ProjectFile GameProjectFile = GameFolderAndProjectFile.Value; GameProjectFile.AddFilesToProject( SourceFileSearch.FindFiles( GameConfigDirectory ), GameProjectDirectory ); } } // Game build files if( IncludeBuildSystemFiles ) { var GameBuildDirectory = DirectoryReference.Combine(GameProjectDirectory, "Build"); if( GameBuildDirectory.Exists() ) { var SubdirectoryNamesToExclude = new List<string>(); SubdirectoryNamesToExclude.Add("Receipts"); SubdirectoryNamesToExclude.Add("Scripts"); var GameProjectFile = GameFolderAndProjectFile.Value; GameProjectFile.AddFilesToProject( SourceFileSearch.FindFiles( GameBuildDirectory, SubdirectoryNamesToExclude ), GameProjectDirectory ); } } } }
/// <summary> /// Finds all csproj within Engine/Source/Programs, and add them if their UE4CSharp.prog file exists. /// </summary> void DiscoverCSharpProgramProjects(MasterProjectFolder ProgramsFolder) { List<FileReference> FoundProjects = new List<FileReference>(); DirectoryReference EngineProgramsSource = DirectoryReference.Combine(UnrealBuildTool.EngineDirectory, "Source", "Programs"); DiscoverCSharpProgramProjectsRecursively(EngineProgramsSource, FoundProjects); foreach (FileReference FoundProject in FoundProjects) { VCSharpProjectFile Project = new VCSharpProjectFile(FoundProject); Project.ShouldBuildForAllSolutionTargets = false; Project.ShouldBuildByDefaultForSolutionTargets = true; AddExistingProjectFile(Project, bForceDevelopmentConfiguration: false); ProgramsFolder.ChildProjects.Add(Project); } }
/// <summary> /// Adds all .automation.csproj files to the solution. /// </summary> void AddAutomationModules(MasterProjectFolder ProgramsFolder) { MasterProjectFolder Folder = ProgramsFolder.AddSubFolder("Automation"); List<DirectoryReference> AllGameFolders = UEBuildTarget.DiscoverAllGameFolders(); List<DirectoryReference> BuildFolders = new List<DirectoryReference>(AllGameFolders.Count); foreach (DirectoryReference GameFolder in AllGameFolders) { DirectoryReference GameBuildFolder = DirectoryReference.Combine(GameFolder, "Build"); if (GameBuildFolder.Exists()) { BuildFolders.Add(GameBuildFolder); } } // Find all the automation modules .csproj files to add List<FileReference> ModuleFiles = RulesCompiler.FindAllRulesSourceFiles(RulesCompiler.RulesFileType.AutomationModule, null, ForeignPlugins:null, AdditionalSearchPaths: BuildFolders ); foreach (FileReference ProjectFile in ModuleFiles) { if (ProjectFile.Exists()) { VCSharpProjectFile Project = new VCSharpProjectFile(ProjectFile); Project.ShouldBuildForAllSolutionTargets = true; AddExistingProjectFile(Project, bForceDevelopmentConfiguration: true); AutomationProjectFiles.Add( Project ); Folder.ChildProjects.Add( Project ); } } }
/// <summary> /// Recursively collapses all sub-folders that are redundant. Should only be called after we're done adding /// files and projects to the master project. /// </summary> /// <param name="Folder">The folder whose sub-folders we should potentially collapse into</param> void EliminateRedundantMasterProjectSubFolders( MasterProjectFolder Folder, string ParentMasterProjectFolderPath ) { // NOTE: This is for diagnostics output only var MasterProjectFolderPath = String.IsNullOrEmpty( ParentMasterProjectFolderPath ) ? Folder.FolderName : ( ParentMasterProjectFolderPath + "/" + Folder.FolderName ); // We can eliminate folders that meet all of these requirements: // 1) Have only a single project file in them // 2) Have no files in the folder except project files, and no sub-folders // 3) The project file matches the folder name // // Additionally, if KeepSourceSubDirectories==false, we can eliminate directories called "Source". // // Also, we can kill folders that are completely empty. foreach( var SubFolder in Folder.SubFolders ) { // Recurse EliminateRedundantMasterProjectSubFolders( SubFolder, MasterProjectFolderPath ); } var SubFoldersToAdd = new List<MasterProjectFolder>(); var SubFoldersToRemove = new List<MasterProjectFolder>(); foreach( var SubFolder in Folder.SubFolders ) { bool CanCollapseFolder = false; // 1) if( SubFolder.ChildProjects.Count == 1 ) { // 2) if( SubFolder.Files.Count == 0 && SubFolder.SubFolders.Count == 0 ) { // 3) if (SubFolder.FolderName.Equals(Utils.GetFilenameWithoutAnyExtensions(SubFolder.ChildProjects[0].ProjectFilePath), StringComparison.InvariantCultureIgnoreCase)) { CanCollapseFolder = true; } } } if( !KeepSourceSubDirectories ) { if( SubFolder.FolderName.Equals( "Source", StringComparison.InvariantCultureIgnoreCase ) ) { // Avoid collapsing the Engine's Source directory, since there are so many other solution folders in // the parent directory. if( !Folder.FolderName.Equals( "Engine", StringComparison.InvariantCultureIgnoreCase ) ) { CanCollapseFolder = true; } } } if( SubFolder.ChildProjects.Count == 0 && SubFolder.Files.Count == 0 & SubFolder.SubFolders.Count == 0 ) { // Folder is totally empty CanCollapseFolder = true; } if( CanCollapseFolder ) { // OK, this folder is redundant and can be collapsed away. SubFoldersToAdd.AddRange( SubFolder.SubFolders ); SubFolder.SubFolders.Clear(); Folder.ChildProjects.AddRange( SubFolder.ChildProjects ); SubFolder.ChildProjects.Clear(); Folder.Files.AddRange( SubFolder.Files ); SubFolder.Files.Clear(); SubFoldersToRemove.Add( SubFolder ); } } foreach( var SubFolderToRemove in SubFoldersToRemove ) { Folder.SubFolders.Remove( SubFolderToRemove ); } Folder.SubFolders.AddRange( SubFoldersToAdd ); // After everything has been collapsed, do a bit of data validation Validate(Folder, ParentMasterProjectFolderPath); }
/// <summary> /// Adds all game project files, including target projects and config files /// </summary> private void AddAllGameProjects(Dictionary<string, ProjectFile> GameProjects, string SupportedPlatformNames, MasterProjectFolder ProjectsFolder) { foreach( var GameFolderAndProjectFile in GameProjects ) { var GameFolderName = GameFolderAndProjectFile.Key; // @todo projectfiles: We have engine localization files, but should we also add GAME localization files? string GameProjectDirectory = GameFolderName; GameProjectDirectory = GameProjectDirectory.Replace("/", "\\"); // Game config files if( IncludeConfigFiles ) { var GameConfigDirectory = Path.Combine(GameProjectDirectory, "Config"); if( Directory.Exists( GameConfigDirectory ) ) { var GameProjectFile = GameFolderAndProjectFile.Value; var DirectoriesToSearch = new List<string>(); DirectoriesToSearch.Add( GameConfigDirectory ); GameProjectFile.AddFilesToProject( SourceFileSearch.FindFiles( DirectoriesToSearch, ExcludeNoRedistFiles:bExcludeNoRedistFiles ), GameFolderName ); } } } }
/// <summary> /// Generates a Visual Studio solution file and Visual C++ project files for all known engine and game targets. /// Does not actually build anything. /// </summary> /// <param name="Arguments">Command-line arguments</param> /// <param name="bSuccess">True if everything went OK</param> public virtual void GenerateProjectFiles( String[] Arguments, out bool bSuccess ) { bSuccess = true; // Parse project generator options bool IncludeAllPlatforms = true; ConfigureProjectFileGeneration( Arguments, ref IncludeAllPlatforms); if( bGeneratingGameProjectFiles ) { Log.TraceInformation("Discovering modules, targets and source code for game..."); MasterProjectRelativePath = UnrealBuildTool.GetUProjectPath(); // Set the project file name MasterProjectName = Path.GetFileNameWithoutExtension(UnrealBuildTool.GetUProjectFile()); if (!Directory.Exists(MasterProjectRelativePath + "/Source")) { if (!Directory.Exists(MasterProjectRelativePath + "/Intermediate/Source")) { if (BuildHostPlatform.Current.Platform == UnrealTargetPlatform.Mac) { MasterProjectRelativePath = Path.GetFullPath(Path.Combine(Utils.GetExecutingAssemblyDirectory(), "..", "..", "..", "Engine")); GameProjectName = "UE4Game"; } if (!Directory.Exists(MasterProjectRelativePath + "/Source")) { throw new BuildException("Directory '{0}' is missing 'Source' folder.", MasterProjectRelativePath); } } } IntermediateProjectFilesPath = Path.Combine(MasterProjectRelativePath, "Intermediate", "ProjectFiles"); } else if( bGeneratingRocketProjectFiles ) { Log.TraceInformation("Discovering modules, targets and source code for project..."); // NOTE: Realistically, the distro that the Rocket user is generating projects FROM won't have NoRedist files in it. But when // testing from a developer branch, this is useful to get authentic projects. This only really matters when // bIncludeEngineModulesInRocketProjects=true (defaults to false.) bExcludeNoRedistFiles = true; MasterProjectRelativePath = UnrealBuildTool.GetUProjectPath(); IntermediateProjectFilesPath = Path.Combine( MasterProjectRelativePath, "Intermediate", "ProjectFiles" ); // Set the project file name MasterProjectName = Path.GetFileNameWithoutExtension(UnrealBuildTool.GetUProjectFile()); if (!Directory.Exists(MasterProjectRelativePath + "/Source")) { if (!Directory.Exists(MasterProjectRelativePath + "/Intermediate/Source")) { throw new BuildException("Directory '{0}' is missing 'Source' folder.", MasterProjectRelativePath); } } } // Modify the name if specific platforms were given if (ProjectPlatforms.Count > 0) { // Sort the platforms names so we get consistent names List<string> SortedPlatformNames = new List<string>(); foreach (UnrealTargetPlatform SpecificPlatform in ProjectPlatforms) { SortedPlatformNames.Add(SpecificPlatform.ToString()); } SortedPlatformNames.Sort(); MasterProjectName += "_"; foreach (string SortedPlatform in SortedPlatformNames) { MasterProjectName += SortedPlatform; IntermediateProjectFilesPath += SortedPlatform; } } bool bCleanProjectFiles = UnrealBuildTool.CommandLineContains( "-CleanProjects" ); if (bCleanProjectFiles) { CleanProjectFiles(MasterProjectRelativePath, MasterProjectName, IntermediateProjectFilesPath); } // Figure out which platforms we should generate project files for. string SupportedPlatformNames; SetupSupportedPlatformsAndConfigurations( IncludeAllPlatforms:IncludeAllPlatforms, SupportedPlatformNames:out SupportedPlatformNames ); Log.TraceVerbose( "Detected supported platforms: " + SupportedPlatformNames ); RootFolder = AllocateMasterProjectFolder( this, "<Root>" ); // Build the list of games to generate projects for var AllGameProjects = UProjectInfo.FilterGameProjects(true, bGeneratingGameProjectFiles ? GameProjectName : null); var AssemblyName = "ProjectFileGenerator"; if( bGeneratingGameProjectFiles ) { AssemblyName = GameProjectName + "ProjectFileGenerator"; } else if( bGeneratingRocketProjectFiles ) { AssemblyName = "RocketProjectFileGenerator"; } List<string> AssemblyGameFolders = new List<string>(); foreach (UProjectInfo Project in AllGameProjects) { AssemblyGameFolders.Add(Project.Folder); } RulesCompiler.SetAssemblyNameAndGameFolders( AssemblyName, AssemblyGameFolders ); ProjectFile EngineProject = null; Dictionary<string, ProjectFile> GameProjects = null; Dictionary<string, ProjectFile> ProgramProjects = null; HashSet<ProjectFile> TemplateGameProjects = null; { // Setup buildable projects for all targets AddProjectsForAllTargets( AllGameProjects, out EngineProject, out GameProjects, out ProgramProjects, out TemplateGameProjects ); // Add all game projects and game config files AddAllGameProjects(GameProjects, SupportedPlatformNames, RootFolder); // Set the game to be the default project if(bGeneratingGameProjectFiles && GameProjects.Count > 0) { DefaultProject = GameProjects.Values.First(); } // Place projects into root level solution folders if( IncludeEngineSource ) { // If we're still missing an engine project because we don't have any targets for it, make one up. if( EngineProject == null ) { string ProjectFilePath = Path.Combine(IntermediateProjectFilesPath, "UE4" + ProjectFileExtension); bool bAlreadyExisted; EngineProject = FindOrAddProject(Utils.MakePathRelativeTo(ProjectFilePath, MasterProjectRelativePath), true, out bAlreadyExisted); EngineProject.IsForeignProject = false; EngineProject.IsGeneratedProject = true; EngineProject.IsStubProject = true; } if( EngineProject != null ) { RootFolder.AddSubFolder( "Engine" ).ChildProjects.Add( EngineProject ); // Engine config files if( IncludeConfigFiles ) { AddEngineConfigFiles( EngineProject ); if( IncludeEnginePrograms ) { AddUnrealHeaderToolConfigFiles(EngineProject); AddUBTConfigFilesToEngineProject(EngineProject); } } // Engine localization files if( IncludeLocalizationFiles ) { AddEngineLocalizationFiles( EngineProject ); } // Engine template files if (IncludeTemplateFiles) { AddEngineTemplateFiles( EngineProject ); } if( IncludeShaderSource ) { Log.TraceVerbose( "Adding shader source code..." ); // Find shader source files and generate stub project AddEngineShaderSource( EngineProject ); } if( IncludeBuildSystemFiles ) { Log.TraceVerbose( "Adding build system files..." ); AddEngineBuildFiles( EngineProject ); } if( IncludeDocumentation ) { AddEngineDocumentation( EngineProject ); } } foreach( var CurGameProject in GameProjects.Values ) { // Templates go under a different solution folder than games if( TemplateGameProjects.Contains( CurGameProject ) ) { RootFolder.AddSubFolder( "Templates" ).ChildProjects.Add( CurGameProject ); } else { RootFolder.AddSubFolder( "Games" ).ChildProjects.Add( CurGameProject ); } } foreach( var CurProgramProject in ProgramProjects.Values ) { ProjectTarget Target = CurProgramProject.ProjectTargets.FirstOrDefault(t => !String.IsNullOrEmpty(t.TargetRules.SolutionDirectory)); if (Target != null) { RootFolder.AddSubFolder(Target.TargetRules.SolutionDirectory).ChildProjects.Add(CurProgramProject); } else { RootFolder.AddSubFolder( "Programs" ).ChildProjects.Add( CurProgramProject ); } } // Add all of the config files for generated program targets AddEngineProgramConfigFiles( ProgramProjects ); } } // Find all of the module files. This will filter out any modules or targets that don't belong to platforms // we're generating project files for. var AllModuleFiles = DiscoverModules(); // Setup "stub" projects for all modules AddProjectsForAllModules(AllGameProjects, ProgramProjects, AllModuleFiles, bGatherThirdPartySource); { if( IncludeEnginePrograms ) { MasterProjectFolder ProgramsFolder = RootFolder.AddSubFolder( "Programs" ); // Add EnvVarsToXML to the master project var EnvVarsToXMLProjectFile = AddSimpleCSharpProject("EnvVarsToXML/EnvVarsToXML", bShouldBuildForAllSolutionTargets: true, bForceDevelopmentConfiguration: true); ProgramsFolder.ChildProjects.Add(EnvVarsToXMLProjectFile); // Add UnrealBuildTool to the master project AddUnrealBuildToolProject( ProgramsFolder, new ProjectFile[] { EnvVarsToXMLProjectFile } ); // Add AutomationTool to the master project ProgramsFolder.ChildProjects.Add(AddSimpleCSharpProject("AutomationTool", bShouldBuildForAllSolutionTargets: true, bForceDevelopmentConfiguration: true)); // Add UnrealAutomationTool (launcher) to the master project ProgramsFolder.ChildProjects.Add(AddSimpleCSharpProject("AutomationToolLauncher", bShouldBuildForAllSolutionTargets: true, bForceDevelopmentConfiguration: true)); // Add automation.csproj files to the master project AddAutomationModules(ProgramsFolder); // Add DotNETUtilities to the master project ProgramsFolder.ChildProjects.Add(AddSimpleCSharpProject("DotNETCommon/DotNETUtilities", bShouldBuildForAllSolutionTargets: true, bForceDevelopmentConfiguration: true)); // Add the Git dependencies project ProgramsFolder.ChildProjects.Add(AddSimpleCSharpProject("GitDependencies", bForceDevelopmentConfiguration: true, bShouldBuildByDefaultForSolutionTargets: false)); // Add all of the IOS C# projects AddIOSProjects( ProgramsFolder ); // Add all of the Android C# projects AddAndroidProjects( ProgramsFolder ); // Add all of the PS4 C# projects AddPS4Projects( ProgramsFolder ); AddHTML5Projects( ProgramsFolder ); } // Eliminate all redundant master project folders. E.g., folders which contain only one project and that project // has the same name as the folder itself. To the user, projects "feel like" folders already in the IDE, so we // want to collapse them down where possible. EliminateRedundantMasterProjectSubFolders( RootFolder, "" ); bool bWriteFileManifest = UnrealBuildTool.CommandLineContains("-filemanifest"); if (bWriteFileManifest == false) { // Figure out which targets we need about IntelliSense for. We only need to worry about targets for projects // that we're actually generating in this session. var IntelliSenseTargetFiles = new List<Tuple<ProjectFile, string>>(); { // Engine targets if( EngineProject != null && !bGeneratingRocketProjectFiles ) { foreach( var ProjectTarget in EngineProject.ProjectTargets ) { if( !String.IsNullOrEmpty( ProjectTarget.TargetFilePath ) ) { // Only bother with the editor target. We want to make sure that definitions are setup to be as inclusive as possible // for good quality IntelliSense. For example, we want WITH_EDITORONLY_DATA=1, so using the editor targets works well. if( ProjectTarget.TargetRules.Type == TargetRules.TargetType.Editor ) { IntelliSenseTargetFiles.Add( Tuple.Create(EngineProject, ProjectTarget.TargetFilePath) ); } } } } // Program targets foreach( var ProgramProject in ProgramProjects.Values ) { foreach( var ProjectTarget in ProgramProject.ProjectTargets ) { if( !String.IsNullOrEmpty( ProjectTarget.TargetFilePath ) ) { IntelliSenseTargetFiles.Add( Tuple.Create( ProgramProject, ProjectTarget.TargetFilePath ) ); } } } // Game/template targets foreach( var GameProject in GameProjects.Values ) { foreach( var ProjectTarget in GameProject.ProjectTargets ) { if( !String.IsNullOrEmpty( ProjectTarget.TargetFilePath ) ) { // Only bother with the editor target. We want to make sure that definitions are setup to be as inclusive as possible // for good quality IntelliSense. For example, we want WITH_EDITORONLY_DATA=1, so using the editor targets works well. if( ProjectTarget.TargetRules.Type == TargetRules.TargetType.Editor ) { IntelliSenseTargetFiles.Add( Tuple.Create( GameProject, ProjectTarget.TargetFilePath ) ); } } } } } // Generate IntelliSense data if we need to. This involves having UBT simulate the action compilation of // the targets so that we can extra the compiler defines, include paths, etc. bSuccess = GenerateIntelliSenseData(Arguments, IntelliSenseTargetFiles ); } // If everything went OK, we'll now save out all of the new project files if( bSuccess ) { if (bWriteFileManifest == false) { // Save new project files WriteProjectFiles(); Log.TraceVerbose( "Project generation complete ({0} generated, {1} imported)", GeneratedProjectFiles.Count, OtherProjectFiles.Count ); } else { WriteProjectFileManifest(); } } } }
/// <summary> /// Adds all of the PS4 C# projects to the master project /// </summary> private void AddPS4Projects(MasterProjectFolder Folder) { if (UEBuildPlatform.BuildPlatformDictionary.ContainsKey(UnrealTargetPlatform.PS4)) { string ProjectFolderName = Path.Combine(EngineRelativePath, "Source", "Programs", "PS4"); DirectoryInfo ProjectFolderInfo = new DirectoryInfo(ProjectFolderName); if (ProjectFolderInfo.Exists) { Folder.ChildProjects.Add(AddSimpleCSharpProject("PS4/PS4DevKitUtil")); } } }