public ProjectConfigAndTargetCombination(STTargetPlatform InPlatform, STTargetConfiguration InConfiguration, string InProjectPlatformName, string InProjectConfigurationName, ProjectTarget InProjectTarget) { Platform = InPlatform; Configuration = InConfiguration; ProjectPlatformName = InProjectPlatformName; ProjectConfigurationName = InProjectConfigurationName; ProjectTarget = InProjectTarget; }
/// <summary> /// Adds the given project to the OtherProjects list /// </summary> /// <param name="InProject">The project to add</param> /// <returns>True if successful</returns> public void AddExistingProjectFile(ProjectFile InProject, bool bNeedsAllPlatformAndConfigurations = false, bool bForceDevelopmentConfiguration = false, bool bProjectDeploys = false, List<STTargetPlatform> InSupportedPlatforms = null, List<STTargetConfiguration> InSupportedConfigurations = null) { if (InProject.ProjectTargets.Count != 0) { throw new BuildException("Expecting existing project to not have any ProjectTargets defined yet."); } var ProjectTarget = new ProjectTarget(); if (bForceDevelopmentConfiguration) { ProjectTarget.ForceDevelopmentConfiguration = true; } ProjectTarget.ProjectDeploys = bProjectDeploys; if (bNeedsAllPlatformAndConfigurations) { // Add all platforms var AllPlatforms = Enum.GetValues(typeof(STTargetPlatform)); foreach (STTargetPlatform CurPlatfrom in AllPlatforms) { ProjectTarget.ExtraSupportedPlatforms.Add(CurPlatfrom); } // Add all configurations var AllConfigurations = Enum.GetValues(typeof(STTargetConfiguration)); foreach (STTargetConfiguration CurConfiguration in AllConfigurations) { ProjectTarget.ExtraSupportedConfigurations.Add(CurConfiguration); } } else if (InSupportedPlatforms != null || InSupportedConfigurations != null) { if (InSupportedPlatforms != null) { // Add all explicitly specified platforms foreach (STTargetPlatform CurPlatfrom in InSupportedPlatforms) { ProjectTarget.ExtraSupportedPlatforms.Add(CurPlatfrom); } } else { // Otherwise, add all platforms var AllPlatforms = Enum.GetValues(typeof(STTargetPlatform)); foreach (STTargetPlatform CurPlatfrom in AllPlatforms) { ProjectTarget.ExtraSupportedPlatforms.Add(CurPlatfrom); } } if (InSupportedConfigurations != null) { // Add all explicitly specified configurations foreach (STTargetConfiguration CurConfiguration in InSupportedConfigurations) { ProjectTarget.ExtraSupportedConfigurations.Add(CurConfiguration); } } else { // Otherwise, add all configurations var AllConfigurations = Enum.GetValues(typeof(STTargetConfiguration)); foreach (STTargetConfiguration CurConfiguration in AllConfigurations) { ProjectTarget.ExtraSupportedConfigurations.Add(CurConfiguration); } } } else { // For existing project files, just support the default desktop platforms and configurations STBuildTool.GetAllDesktopPlatforms(ref ProjectTarget.ExtraSupportedPlatforms, false); // Debug and Development only ProjectTarget.ExtraSupportedConfigurations.Add(STTargetConfiguration.Debug); ProjectTarget.ExtraSupportedConfigurations.Add(STTargetConfiguration.Development); } InProject.ProjectTargets.Add(ProjectTarget); // Existing projects must always have a GUID. This will throw an exception if one isn't found. InProject.LoadGUIDFromExistingProject(); OtherProjectFiles.Add(InProject); }
/// <summary> /// Checks to see if the specified solution platform and configuration is able to map to this project /// </summary> /// <param name="ProjectTarget">The target that we're checking for a valid platform/config combination</param> /// <param name="Platform">Platform</param> /// <param name="Configuration">Configuration</param> /// <returns>True if this is a valid combination for this project, otherwise false</returns> public static bool IsValidProjectPlatformAndConfiguration(ProjectTarget ProjectTarget, STTargetPlatform Platform, STTargetConfiguration Configuration) { var PlatformProjectGenerator = STPlatformProjectGenerator.GetPlatformProjectGenerator(Platform, true); if (PlatformProjectGenerator == null) { return false; } var BuildPlatform = STBuildPlatform.GetBuildPlatform(Platform, true); if (BuildPlatform == null) { return false; } if (BuildPlatform.HasRequiredSDKsInstalled() != SDKStatus.Valid) { return false; } var SupportedConfigurations = new List<STTargetConfiguration>(); var SupportedPlatforms = new List<STTargetPlatform>(); if (!ProjectFileGenerator.bCreateDummyConfigsForUnsupportedPlatforms || ProjectFileGenerator.bGeneratingRocketProjectFiles) { if (ProjectTarget.TargetRules != null) { ProjectTarget.TargetRules.GetSupportedPlatforms(ref SupportedPlatforms); } } else { STBuildTool.GetAllPlatforms(ref SupportedPlatforms); } bool bIncludeTestAndShippingConfigs = ProjectFileGenerator.bIncludeTestAndShippingConfigs || ProjectFileGenerator.bGeneratingRocketProjectFiles; if (ProjectTarget.TargetRules != null) { // Rocket projects always get shipping configs ProjectTarget.TargetRules.GetSupportedConfigurations(ref SupportedConfigurations, bIncludeTestAndShippingConfigs: bIncludeTestAndShippingConfigs); } // Add all of the extra platforms/configurations for this target { foreach (var ExtraPlatform in ProjectTarget.ExtraSupportedPlatforms) { if (!SupportedPlatforms.Contains(ExtraPlatform)) { SupportedPlatforms.Add(ExtraPlatform); } } foreach (var ExtraConfig in ProjectTarget.ExtraSupportedConfigurations) { if (bIncludeTestAndShippingConfigs || (ExtraConfig != STTargetConfiguration.Shipping && ExtraConfig != STTargetConfiguration.Test)) { if (!SupportedConfigurations.Contains(ExtraConfig)) { SupportedConfigurations.Add(ExtraConfig); } } } } // Only build for supported platforms if (SupportedPlatforms.Contains(Platform) == false) { return false; } // Only build for supported configurations if (SupportedConfigurations.Contains(Configuration) == false) { return false; } // For Rocket projects, we currently only allow 64-bit versions of Debug and Development binaries to be compiled // and only 32-bit versions of Shipping binaries to be compiled. This has to do with our choice of which build // configurations we want to ship with that product. So to simplify things, we're merging Win32 and Win64 // configurations together in the IDE under "Windows". In order for this to work properly, we need to make // sure that Rocket projects only report the respective Windows platform that is valid for each configuration if (STBuildTool.RunningRocket() && ProjectTarget.TargetRules != null) { if (Platform == STTargetPlatform.Win32 || Platform == STTargetPlatform.Win64) { // In Rocket, shipping game targets are always 32-bit if (Configuration == STTargetConfiguration.Shipping && ProjectTarget.TargetRules.Type == TargetRules.TargetType.Game) { if (Platform != STTargetPlatform.Win32) { return false; } } else { // Everything else is expecting to be 64-bit if (Platform != STTargetPlatform.Win64) { return false; } } } } return true; }
/// <summary> /// Creates project entries for all known targets (*.Target.cs files) /// </summary> /// <param name="AllGameFolders">All game folders</param> /// <param name="EngineProject">The engine project we created</param> /// <param name="GameProjects">Map of game folder name to all of the game projects we created</param> /// <param name="ProgramProjects">Map of program names to all of the program projects we created</param> /// <param name="TemplateGameProjects">Set of template game projects we found. These will also be in the GameProjects map</param> private void AddProjectsForAllTargets(List<UProjectInfo> AllGames, out ProjectFile EngineProject, out Dictionary<string, ProjectFile> GameProjects, out Dictionary<string, ProjectFile> ProgramProjects, out HashSet<ProjectFile> TemplateGameProjects) { // As we're creating project files, we'll also keep track of whether we created an "engine" project and return that if we have one EngineProject = null; GameProjects = new Dictionary<string, ProjectFile>(StringComparer.InvariantCultureIgnoreCase); ProgramProjects = new Dictionary<string, ProjectFile>(StringComparer.InvariantCultureIgnoreCase); TemplateGameProjects = new HashSet<ProjectFile>(); // Find all of the target files. This will filter out any modules or targets that don't // belong to platforms we're generating project files for. var AllTargetFiles = DiscoverTargets(); foreach (var TargetFilePath in AllTargetFiles) { var TargetName = Utils.GetFilenameWithoutAnyExtensions(TargetFilePath); // Remove both ".cs" and ".Target" // Check to see if this is an Engine target. That is, the target is located under the "Engine" folder bool IsEngineTarget = false; string TargetFileRelativeToEngineDirectory = Utils.MakePathRelativeTo(TargetFilePath, Path.Combine(EngineRelativePath), AlwaysTreatSourceAsDirectory: false); if (!TargetFileRelativeToEngineDirectory.StartsWith("..") && !Path.IsPathRooted(TargetFileRelativeToEngineDirectory)) { // This is an engine target IsEngineTarget = true; } bool WantProjectFileForTarget = true; if (TargetFileRelativeToEngineDirectory.StartsWith(Path.Combine("Source", "Programs"), StringComparison.InvariantCultureIgnoreCase)) { WantProjectFileForTarget = IncludeEnginePrograms; } else if (TargetFileRelativeToEngineDirectory.StartsWith(Path.Combine("Source"), StringComparison.InvariantCultureIgnoreCase)) { WantProjectFileForTarget = IncludeEngineSource; } if (WantProjectFileForTarget) { // Create target rules for all of the platforms and configuration combinations that we want to enable support for. // Just use the current platform as we only need to recover the target type and both should be supported for all targets... string UnusedTargetFilePath; var TargetRulesObject = RulesCompiler.CreateTargetRules(TargetName, new TargetInfo(BuildHostPlatform.Current.Platform, STTargetConfiguration.Development), false, out UnusedTargetFilePath); // Exclude client and server targets under binary Rocket; it's impossible to build without precompiled engine binaries if (!STBuildTool.RunningRocket() || (TargetRulesObject.Type != TargetRules.TargetType.Client && TargetRulesObject.Type != TargetRules.TargetType.Server)) { bool IsProgramTarget = false; string GameFolder = null; string ProjectFileNameBase = null; if (TargetRulesObject.Type == TargetRules.TargetType.Program) { IsProgramTarget = true; ProjectFileNameBase = TargetName; } else if (IsEngineTarget) { ProjectFileNameBase = EngineProjectFileNameBase; } else { // Figure out which game project this target belongs to UProjectInfo ProjectInfo = FindGameContainingFile(AllGames, TargetFilePath); if (ProjectInfo == null) { throw new BuildException("Found a non-engine target file (" + TargetFilePath + ") that did not exist within any of the known game folders"); } GameFolder = ProjectInfo.Folder; ProjectFileNameBase = ProjectInfo.GameName; } // @todo projectfiles: We should move all of the Target.cs files out of sub-folders to clean up the project directories a bit (e.g. GameUncooked folder) var ProjectFilePath = Path.Combine(IntermediateProjectFilesPath, ProjectFileNameBase + ProjectFileExtension); if (TargetRules.IsGameType(TargetRulesObject.Type) && (TargetRules.IsEditorType(TargetRulesObject.Type) == false)) { // Allow platforms to generate stub projects here... STPlatformProjectGenerator.GenerateGameProjectStubs( InGenerator: this, InTargetName: TargetName, InTargetFilepath: TargetFilePath, InTargetRules: TargetRulesObject, InPlatforms: SupportedPlatforms, InConfigurations: SupportedConfigurations); } ProjectFilePath = Utils.MakePathRelativeTo(ProjectFilePath, MasterProjectRelativePath); bool bProjectAlreadyExisted; var ProjectFile = FindOrAddProject(ProjectFilePath, IncludeInGeneratedProjects: true, bAlreadyExisted: out bProjectAlreadyExisted); ProjectFile.IsForeignProject = bGeneratingGameProjectFiles && STBuildTool.HasUProjectFile() && Utils.IsFileUnderDirectory(TargetFilePath, STBuildTool.GetUProjectPath()); ProjectFile.IsGeneratedProject = true; ProjectFile.IsStubProject = false; bool IsTemplateTarget = false; { // Check to see if this is a template target. That is, the target is located under the "Templates" folder string TargetFileRelativeToTemplatesDirectory = Utils.MakePathRelativeTo(TargetFilePath, Path.Combine(RootRelativePath, "Templates")); if (!TargetFileRelativeToTemplatesDirectory.StartsWith("..") && !Path.IsPathRooted(TargetFileRelativeToTemplatesDirectory)) { IsTemplateTarget = true; } } string BaseFolder = null; if (IsProgramTarget) { ProgramProjects[TargetName] = ProjectFile; BaseFolder = Path.GetDirectoryName(TargetFilePath); } else if (IsEngineTarget) { EngineProject = ProjectFile; BaseFolder = EngineRelativePath; } else { GameProjects[GameFolder] = ProjectFile; if (IsTemplateTarget) { TemplateGameProjects.Add(ProjectFile); } BaseFolder = GameFolder; if (!bProjectAlreadyExisted) { // Add the .uproject file for this game/template var UProjectFilePath = Path.Combine(BaseFolder, ProjectFileNameBase + ".uproject"); if (File.Exists(UProjectFilePath)) { ProjectFile.AddFileToProject(UProjectFilePath, BaseFolder); } else { throw new BuildException("Not expecting to find a game with no .uproject file. File '{0}' doesn't exist", UProjectFilePath); } } } foreach (var ExistingProjectTarget in ProjectFile.ProjectTargets) { if (ExistingProjectTarget.TargetRules.ConfigurationName.Equals(TargetRulesObject.ConfigurationName, StringComparison.InvariantCultureIgnoreCase)) { throw new BuildException("Not expecting project {0} to already have a target rules of with configuration name {1} ({2}) while trying to add: {3}", ProjectFilePath, TargetRulesObject.ConfigurationName, ExistingProjectTarget.TargetRules.ToString(), TargetRulesObject.ToString()); } // Not expecting to have both a game and a program in the same project. These would alias because we share the project and solution configuration names (just because it makes sense to) if (ExistingProjectTarget.TargetRules.Type == TargetRules.TargetType.Game && ExistingProjectTarget.TargetRules.Type == TargetRules.TargetType.Program || ExistingProjectTarget.TargetRules.Type == TargetRules.TargetType.Program && ExistingProjectTarget.TargetRules.Type == TargetRules.TargetType.Game) { throw new BuildException("Not expecting project {0} to already have a Game/Program target ({1}) associated with it while trying to add: {2}", ProjectFilePath, ExistingProjectTarget.TargetRules.ToString(), TargetRulesObject.ToString()); } } var ProjectTarget = new ProjectTarget() { TargetRules = TargetRulesObject, TargetFilePath = TargetFilePath }; if (TargetName == "ShaderCompileWorker") // @todo projectfiles: Ideally, the target rules file should set this { ProjectTarget.ForceDevelopmentConfiguration = true; } ProjectFile.ProjectTargets.Add(ProjectTarget); // Make sure the *.Target.cs file is in the project. ProjectFile.AddFileToProject(TargetFilePath, BaseFolder); // We special case ShaderCompileWorker. It needs to always be compiled in Development mode. Log.TraceVerbose("Generating target {0} for {1}", TargetRulesObject.Type.ToString(), ProjectFilePath); } } } }