/// <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> /// 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 .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 ); } } }