private static void SetupProjectConfigurations(Project project, ProjectInfo projectInfo) { project.Configurations.Clear(); // Generate a set of configurations to build all targets for all platforms/configurations/architectures var rules = GenerateRulesAssembly(); foreach (var target in project.Targets) { string targetName = target.ConfigurationName ?? target.Name; // When using custom project file try to extract configurations from there if (!string.IsNullOrEmpty(target.CustomExternalProjectFilePath)) { // TODO: implement it in a proper way by parsing the project file to extract the configurations if (target.CustomExternalProjectFilePath.EndsWith(".csproj")) { var targetPlatform = TargetPlatform.Windows; var platformName = targetPlatform.ToString(); var platform = Platform.BuildPlatform; var architecture = TargetArchitecture.AnyCPU; var architectureName = "AnyCPU"; var toolchain = platform.HasRequiredSDKsInstalled ? platform.GetToolchain(architecture) : null; var configuration = TargetConfiguration.Debug; var configurationName = "Debug"; var configurationText = configurationName; var targetBuildOptions = GetBuildOptions(target, platform, toolchain, architecture, configuration, project.WorkspaceRootPath); var modules = CollectModules(rules, platform, target, targetBuildOptions, toolchain, architecture, configuration); foreach (var module in modules) { // This merges private module build options into global target - not the best option but helps with syntax highlighting and references collecting module.Key.Setup(targetBuildOptions); module.Key.SetupEnvironment(targetBuildOptions); } project.Configurations.Add(new Project.ConfigurationData { Name = configurationText + '|' + architectureName, Text = configurationText, Platform = targetPlatform, PlatformName = platformName, Architecture = architecture, ArchitectureName = architectureName, Configuration = configuration, ConfigurationName = configurationName, Target = target, TargetBuildOptions = targetBuildOptions, Modules = modules, }); configuration = TargetConfiguration.Release; configurationName = "Release"; configurationText = configurationName; targetBuildOptions = GetBuildOptions(target, platform, toolchain, architecture, configuration, project.WorkspaceRootPath); modules = CollectModules(rules, platform, target, targetBuildOptions, toolchain, architecture, configuration); foreach (var module in modules) { // This merges private module build options into global target - not the best option but helps with syntax highlighting and references collecting module.Key.Setup(targetBuildOptions); module.Key.SetupEnvironment(targetBuildOptions); } project.Configurations.Add(new Project.ConfigurationData { Name = configurationText + '|' + architectureName, Text = configurationText, Platform = targetPlatform, PlatformName = platformName, Architecture = architecture, ArchitectureName = architectureName, Configuration = configuration, ConfigurationName = configurationName, Target = target, TargetBuildOptions = targetBuildOptions, Modules = modules, }); } else { throw new NotImplementedException(); } continue; } foreach (var targetPlatform in target.Platforms) { string platformName = targetPlatform.ToString(); foreach (var configuration in target.Configurations) { string configurationName = configuration.ToString(); foreach (var architecture in target.GetArchitectures(targetPlatform)) { if (!Platform.IsPlatformSupported(targetPlatform, architecture)) { continue; } var platform = Platform.GetPlatform(targetPlatform, true); if (platform == null) { continue; } if (!platform.HasRequiredSDKsInstalled && (!projectInfo.IsCSharpOnlyProject || platform != Platform.BuildPlatform)) { continue; } string configurationText = targetName + '.' + platformName + '.' + configurationName; string architectureName = architecture.ToString(); if (platform is IProjectCustomizer customizer) { customizer.GetProjectArchitectureName(project, platform, architecture, ref architectureName); } var toolchain = platform.HasRequiredSDKsInstalled ? platform.GetToolchain(architecture) : null; var targetBuildOptions = GetBuildOptions(target, platform, toolchain, architecture, configuration, project.WorkspaceRootPath); var modules = CollectModules(rules, platform, target, targetBuildOptions, toolchain, architecture, configuration); foreach (var module in modules) { // This merges private module build options into global target - not the best option but helps with syntax highlighting and references collecting module.Key.Setup(targetBuildOptions); module.Key.SetupEnvironment(targetBuildOptions); } project.Configurations.Add(new Project.ConfigurationData { Name = configurationText + '|' + architectureName, Text = configurationText, Platform = targetPlatform, PlatformName = platformName, Architecture = architecture, ArchitectureName = architectureName, Configuration = configuration, ConfigurationName = configurationName, Target = target, TargetBuildOptions = targetBuildOptions, Modules = modules, }); } } } } }
/// <summary> /// Builds the targets. /// </summary> /// <returns>True if failed, otherwise false.</returns> public static bool BuildTargets() { bool failed = false; var rules = GenerateRulesAssembly(); var project = Globals.Project; using (new ProfileEventScope("BuildTargets")) { // Pick targets to build var customBuildTargets = Configuration.BuildTargets; var projectTargets = GetProjectTargets(project); var targets = customBuildTargets == null ? projectTargets : projectTargets.Where(target => customBuildTargets.Contains(target.Name)).ToArray(); // Create task graph for building all targets var graph = new TaskGraph(project.ProjectFolderPath); foreach (var target in targets) { target.PreBuild(); // Pick configurations to build TargetConfiguration[] configurations = Configuration.BuildConfigurations; if (configurations != null) { foreach (var configuration in configurations) { if (!target.Configurations.Contains(configuration)) { throw new Exception(string.Format("Target {0} does not support {1} configuration.", target.Name, configuration)); } } } else { configurations = target.Configurations; } foreach (var configuration in configurations) { // Pick platforms to build TargetPlatform[] platforms = Configuration.BuildPlatforms; if (platforms != null) { foreach (var platform in platforms) { if (!target.Platforms.Contains(platform)) { throw new Exception(string.Format("Target {0} does not support {1} platform.", target.Name, platform)); } } } else { platforms = target.Platforms; } foreach (var targetPlatform in platforms) { // Pick architectures to build TargetArchitecture[] architectures = Configuration.BuildArchitectures; if (architectures != null) { foreach (var e in architectures) { if (!target.Architectures.Contains(e)) { throw new Exception(string.Format("Target {0} does not support {1} architecture.", target.Name, e)); } } } else { architectures = target.GetArchitectures(targetPlatform); } foreach (var architecture in architectures) { if (!Platform.IsPlatformSupported(targetPlatform, architecture)) { continue; } //throw new Exception(string.Format("Platform {0} {1} is not supported.", targetPlatform, architecture)); var platform = Platform.GetPlatform(targetPlatform); // Special case: building C# bindings only (eg. when building Linux game on Windows without C++ scripting or for C#-only projects) if (Configuration.BuildBindingsOnly || (project.IsCSharpOnlyProject && platform.HasModularBuildSupport)) { Log.Info("Building C# only"); using (new ProfileEventScope(target.Name)) { Log.Info(string.Format("Building target {0} in {1} for {2} {3}", target.Name, configuration, targetPlatform, architecture)); var buildContext = new Dictionary <Target, BuildData>(); switch (target.Type) { case TargetType.NativeCpp: BuildTargetNativeCppBindingsOnly(rules, graph, target, buildContext, platform, architecture, configuration); break; case TargetType.DotNet: BuildTargetDotNet(rules, graph, target, platform, configuration); break; default: throw new ArgumentOutOfRangeException(); } } continue; } var toolchain = platform.GetToolchain(architecture); using (new ProfileEventScope(target.Name)) { Log.Info(string.Format("Building target {0} in {1} for {2} {3}", target.Name, configuration, targetPlatform, architecture)); var buildContext = new Dictionary <Target, BuildData>(); switch (target.Type) { case TargetType.NativeCpp: BuildTargetNativeCpp(rules, graph, target, buildContext, toolchain, configuration); break; case TargetType.DotNet: BuildTargetDotNet(rules, graph, target, toolchain.Platform, configuration); break; default: throw new ArgumentOutOfRangeException(); } } } } } } // Prepare tasks for the execution using (new ProfileEventScope("PrepareTasks")) { using (new ProfileEventScope("Setup")) graph.Setup(); using (new ProfileEventScope("SortTasks")) graph.SortTasks(); using (new ProfileEventScope("LoadCache")) graph.LoadCache(); } // Execute tasks int executedTasksCount; using (new ProfileEventScope("ExecuteTasks")) { failed |= graph.Execute(out executedTasksCount); } if (executedTasksCount != 0) { // Save graph execution result cache using (new ProfileEventScope("SaveCache")) { graph.SaveCache(); } } foreach (var target in targets) { target.PostBuild(); } } return(failed); }
/// <summary> /// Cleans the build system cache and intermediate results. /// </summary> public static void Clean() { using (new ProfileEventScope("Clean")) { // Clear task graph cache var project = Globals.Project; TaskGraph graph; if (project == null) { graph = new TaskGraph(Globals.Root); graph.CleanCache(); return; } graph = new TaskGraph(project.ProjectFolderPath); graph.CleanCache(); // Pick targets to clean var customBuildTargets = Configuration.BuildTargets; var projectTargets = GetProjectTargets(project); var targets = customBuildTargets == null ? projectTargets : projectTargets.Where(target => customBuildTargets.Contains(target.Name)).ToArray(); foreach (var target in targets) { // Pick configurations to clean TargetConfiguration[] configurations = Configuration.BuildConfigurations; if (configurations != null) { foreach (var configuration in configurations) { if (!target.Configurations.Contains(configuration)) { throw new Exception(string.Format("Target {0} does not support {1} configuration.", target.Name, configuration)); } } } else { configurations = target.Configurations; } foreach (var configuration in configurations) { // Pick platforms to clean TargetPlatform[] platforms = Configuration.BuildPlatforms; if (platforms != null) { foreach (var platform in platforms) { if (!target.Platforms.Contains(platform)) { throw new Exception(string.Format("Target {0} does not support {1} platform.", target.Name, platform)); } } } else { platforms = target.Platforms; } foreach (var targetPlatform in platforms) { if (!Platform.BuildPlatform.CanBuildPlatform(targetPlatform)) { continue; } // Pick architectures to build TargetArchitecture[] architectures = Configuration.BuildArchitectures; if (architectures != null) { foreach (var e in architectures) { if (!target.Architectures.Contains(e)) { throw new Exception(string.Format("Target {0} does not support {1} architecture.", target.Name, e)); } } } else { architectures = target.GetArchitectures(targetPlatform); } foreach (var architecture in architectures) { if (!Platform.IsPlatformSupported(targetPlatform, architecture)) { continue; } //throw new Exception(string.Format("Platform {0} {1} is not supported.", targetPlatform, architecture)); var platform = Platform.GetPlatform(targetPlatform); var toolchain = platform.GetToolchain(architecture); var targetBuildOptions = GetBuildOptions(target, toolchain.Platform, toolchain, toolchain.Architecture, configuration, project.ProjectFolderPath, string.Empty); // Delete all intermediate files var intermediateFolder = new DirectoryInfo(targetBuildOptions.IntermediateFolder); if (intermediateFolder.Exists) { Log.Info("Removing: " + targetBuildOptions.IntermediateFolder); CleanDirectory(intermediateFolder); } } } } } } }