private void MakeFastBuildAllProjectIfNeeded(Builder builder, Dictionary <Solution.Configuration, List <Project.Configuration> > unlinkedConfigurations) { if (!GenerateFastBuildAllProject) { return; } foreach (var solutionFile in SolutionFilesMapping) { var solutionConfigurations = solutionFile.Value; bool generateFastBuildAll = false; var projectsToBuildPerSolutionConfig = new List <Tuple <Solution.Configuration, List <Solution.Configuration.IncludedProjectInfo> > >(); foreach (var solutionConfiguration in solutionConfigurations) { var configProjects = solutionConfiguration.IncludedProjectInfos; var fastBuildProjectConfsToBuild = configProjects.Where( configProject => ( configProject.Configuration.IsFastBuild && configProject.ToBuild == Solution.Configuration.IncludedProjectInfo.Build.Yes ) ).ToList(); if (fastBuildProjectConfsToBuild.Count == 0) { continue; } // if there's only one project to build, no need for the FastBuildAll generateFastBuildAll |= fastBuildProjectConfsToBuild.Count > 1; projectsToBuildPerSolutionConfig.Add(Tuple.Create(solutionConfiguration, fastBuildProjectConfsToBuild)); } if (!generateFastBuildAll) { continue; } builder.LogWriteLine(" extra FastBuildAll project added to solution " + Path.GetFileName(solutionFile.Key)); // Use the target type from the first solution configuration, as they all should have the same anyway var firstSolutionConf = projectsToBuildPerSolutionConfig.First().Item1; Project fastBuildAllProject = null; foreach (var projectsToBuildInSolutionConfig in projectsToBuildPerSolutionConfig) { var solutionConf = projectsToBuildInSolutionConfig.Item1; var projectConfigsToBuild = projectsToBuildInSolutionConfig.Item2; if (GenerateFastBuildAllOnlyForConfThatNeedIt && projectConfigsToBuild.Count == 1) { continue; } var solutionTarget = solutionConf.Target; if (fastBuildAllProject == null) { var firstProject = projectConfigsToBuild.First(); // Use the target type from the current solution configuration, as they all should have the same anyway fastBuildAllProject = new FastBuildAllProject(solutionConf.Target.GetType()) { Name = FastBuildAllProjectName, RootPath = firstProject.Project.RootPath, SourceRootPath = firstProject.Project.RootPath, IsFileNameToLower = firstProject.Project.IsFileNameToLower, SharpmakeProjectType = Project.ProjectTypeAttribute.Generate }; } else { // validate the assumption made above if (fastBuildAllProject.Targets.TargetType != firstSolutionConf.Target.GetType()) { throw new Error("Target type must match between all solution configurations"); } } fastBuildAllProject.AddTargets(solutionTarget); } fastBuildAllProject.Targets.BuildTargets(); fastBuildAllProject.InvokeConfiguration(builder.Context); // we need to iterate again after invoking the configure of all the projects so we can tweak their conf foreach (var projectsToBuildInSolutionConfig in projectsToBuildPerSolutionConfig) { var solutionConf = projectsToBuildInSolutionConfig.Item1; var projectConfigsToBuild = projectsToBuildInSolutionConfig.Item2; if (GenerateFastBuildAllOnlyForConfThatNeedIt && projectConfigsToBuild.Count == 1) { continue; } var solutionTarget = solutionConf.Target; var projectConf = fastBuildAllProject.GetConfiguration(solutionTarget); // Re-link projects to the new All project // TODO: We should do something to detect and avoid any circular references that this project can now theoretically create. List <Project.Configuration> projectConfigsToRelink; if (unlinkedConfigurations.TryGetValue(solutionConf, out projectConfigsToRelink)) { foreach (Project.Configuration config in projectConfigsToRelink.Distinct()) { ProjectsDependingOnFastBuildAllForThisSolution.Add(config.Project); } } projectConf.IsFastBuild = true; projectConf.AddMasterBff(solutionConf.MasterBffFilePath); // output the project in the same folder as the solution, and the same name projectConf.ProjectPath = solutionConf.SolutionPath; if (string.IsNullOrWhiteSpace(FastBuildAllProjectFileSuffix)) { throw new Error("FastBuildAllProjectFileSuffix cannot be left empty in solution " + solutionFile); } projectConf.ProjectFileName = solutionFile.Key + FastBuildAllProjectFileSuffix; projectConf.SolutionFolder = FastBuildAllSolutionFolder; // the project doesn't output anything projectConf.Output = Project.Configuration.OutputType.None; // get some settings that are usually global from the first project // we could expose those, if we need to set them specifically for FastBuildAllProject var firstProject = projectConfigsToBuild.First(); projectConf.FastBuildCustomArgs = firstProject.Configuration.FastBuildCustomArgs; projectConf.FastBuildCustomActionsBeforeBuildCommand = firstProject.Configuration.FastBuildCustomActionsBeforeBuildCommand; // add all the projects to build as private dependencies, and OnlyBuildOrder foreach (Configuration.IncludedProjectInfo projectConfigToBuild in projectConfigsToBuild) { // update the ToBuild, as now it is built through the "FastBuildAll" dependency projectConfigToBuild.ToBuild = Configuration.IncludedProjectInfo.Build.YesThroughDependency; // Relink any build-order dependencies projectConf.GenericBuildDependencies.AddRange(projectConfigToBuild.Configuration.GenericBuildDependencies); projectConf.GenericBuildDependencies.AddRange(projectConfigToBuild.Configuration.DotNetPublicDependencies.Select(d => d.Configuration).Where(c => !c.IsFastBuild)); projectConf.GenericBuildDependencies.AddRange(projectConfigToBuild.Configuration.DotNetPrivateDependencies.Select(d => d.Configuration).Where(c => !c.IsFastBuild)); projectConf.AddPrivateDependency(projectConfigToBuild.Target, projectConfigToBuild.Project.GetType(), DependencySetting.OnlyBuildOrder); } // add the newly generated project to the solution config solutionConf.IncludedProjectInfos.Add( new Configuration.IncludedProjectInfo { Project = fastBuildAllProject, Configuration = projectConf, Target = solutionTarget, Type = fastBuildAllProject.GetType(), ToBuild = Configuration.IncludedProjectInfo.Build.Yes } ); } fastBuildAllProject.Resolve(builder, false); fastBuildAllProject.Link(builder); builder.RegisterGeneratedProject(fastBuildAllProject); } }
private void MakeFastBuildAllProjectIfNeeded(Builder builder) { foreach (var solutionFile in SolutionFilesMapping) { var solutionConfigurations = solutionFile.Value; bool generateFastBuildAll = false; var projectsToBuildPerSolutionConfig = new List <Tuple <Solution.Configuration, List <Solution.Configuration.IncludedProjectInfo> > >(); foreach (var solutionConfiguration in solutionConfigurations) { var configProjects = solutionConfiguration.IncludedProjectInfos; var fastBuildProjectConfsToBuild = configProjects.Where( configProject => ( configProject.Configuration.IsFastBuild && configProject.ToBuild == Solution.Configuration.IncludedProjectInfo.Build.Yes ) ).ToList(); if (fastBuildProjectConfsToBuild.Count == 0) { continue; } // if there's only one project to build, no need for the FastBuildAll generateFastBuildAll |= fastBuildProjectConfsToBuild.Count > 1; projectsToBuildPerSolutionConfig.Add(Tuple.Create(solutionConfiguration, fastBuildProjectConfsToBuild)); } if (!generateFastBuildAll) { continue; } builder.LogWriteLine(" extra FastBuildAll project added to solution " + Path.GetFileName(solutionFile.Key)); // Use the target type from the first solution configuration, as they all should have the same anyway var firstSolutionConf = projectsToBuildPerSolutionConfig.First().Item1; Project fastBuildAllProject = null; foreach (var projectsToBuildInSolutionConfig in projectsToBuildPerSolutionConfig) { var solutionConf = projectsToBuildInSolutionConfig.Item1; var projectConfigsToBuild = projectsToBuildInSolutionConfig.Item2; var solutionTarget = solutionConf.Target; if (fastBuildAllProject == null) { var firstProject = projectConfigsToBuild.First(); // Use the target type from the current solution configuration, as they all should have the same anyway fastBuildAllProject = new FastBuildAllProject(solutionConf.Target.GetType()) { Name = FastBuildAllProjectName, RootPath = firstProject.Project.RootPath, SourceRootPath = firstProject.Project.RootPath, IsFileNameToLower = firstProject.Project.IsFileNameToLower }; } else { // validate the asumption made above if (fastBuildAllProject.Targets.TargetType != firstSolutionConf.Target.GetType()) { throw new Error("Target type must match between all solution configurations"); } } fastBuildAllProject.AddTargets(solutionTarget); } fastBuildAllProject.Targets.BuildTargets(); fastBuildAllProject.InvokeConfiguration(builder.Context); foreach (var projectsToBuildInSolutionConfig in projectsToBuildPerSolutionConfig) { var solutionConf = projectsToBuildInSolutionConfig.Item1; var projectConfigsToBuild = projectsToBuildInSolutionConfig.Item2; var solutionTarget = solutionConf.Target; var projectConf = fastBuildAllProject.GetConfiguration(solutionTarget); projectConf.IsFastBuild = true; // output the project in the same folder as the solution, and the same name projectConf.ProjectPath = solutionConf.SolutionPath; if (string.IsNullOrWhiteSpace(FastBuildAllProjectFileSuffix)) { throw new Error("FastBuildAllProjectFileSuffix cannot be left emtpy in solution " + solutionFile); } projectConf.ProjectFileName = solutionFile.Key + FastBuildAllProjectFileSuffix; projectConf.SolutionFolder = FastBuildAllSolutionFolder; // the project doesn't output anything projectConf.Output = Project.Configuration.OutputType.None; // get some settings that are usually global from the first project // we could expose those, if we need to set them specifically for FastBuildAllProject var firstProject = projectConfigsToBuild.First(); projectConf.FastBuildCustomArgs = firstProject.Configuration.FastBuildCustomArgs; projectConf.FastBuildCustomActionsBeforeBuildCommand = firstProject.Configuration.FastBuildCustomActionsBeforeBuildCommand; // add all the projects to build as private dependencies, and OnlyBuildOrder foreach (Configuration.IncludedProjectInfo projectConfigToBuild in projectConfigsToBuild) { // update the ToBuild, as now it is built through the "FastBuildAll" dependency projectConfigToBuild.ToBuild = Configuration.IncludedProjectInfo.Build.YesThroughDependency; projectConf.AddPrivateDependency(projectConfigToBuild.Target, projectConfigToBuild.Project.GetType(), DependencySetting.OnlyBuildOrder); } // add the newly generated project to the solution config solutionConf.IncludedProjectInfos.Add( new Configuration.IncludedProjectInfo { Project = fastBuildAllProject, Configuration = projectConf, Target = solutionTarget, Type = fastBuildAllProject.GetType(), ToBuild = Configuration.IncludedProjectInfo.Build.Yes } ); } fastBuildAllProject.Resolve(builder, false); fastBuildAllProject.Link(builder); builder.RegisterGeneratedProject(fastBuildAllProject); } }