Exemplo n.º 1
0
        /// <summary>
        /// Returns true if the specified project can be built directly, without using a metaproject.
        /// </summary>
        private bool CanBuildDirectly(ProjectInstance traversalProject, ProjectInSolution projectToAdd, ProjectConfigurationInSolution projectConfiguration)
        {
            // Can we build this project directly, without a metaproject?  We can if it's MSBuild-able and has no references building in this configuration.
            bool canBuildDirectly = false;
            string unknownProjectTypeErrorMessage;
            if ((projectToAdd.ProjectType == SolutionProjectType.KnownToBeMSBuildFormat) ||
                (projectToAdd.CanBeMSBuildProjectFile(out unknownProjectTypeErrorMessage)))
            {
                canBuildDirectly = true;
                foreach (string dependencyProjectGuid in projectToAdd.Dependencies)
                {
                    ProjectInSolution dependencyProject;
                    if (!_solutionFile.ProjectsByGuid.TryGetValue(dependencyProjectGuid, out dependencyProject))
                    {
                        ProjectFileErrorUtilities.VerifyThrowInvalidProjectFile
                            (
                            false,
                            "SubCategoryForSolutionParsingErrors",
                            new BuildEventFileInfo(traversalProject.FullPath),
                            "SolutionParseProjectDepNotFoundError",
                            projectToAdd.ProjectGuid,
                            dependencyProjectGuid
                            );
                    }

                    if (WouldProjectBuild(_solutionFile, _selectedSolutionConfiguration, dependencyProject, projectConfiguration))
                    {
                        // This is a reference we would have to build, so we can't build the project directly.
                        canBuildDirectly = false;
                        break;
                    }
                }
            }

            return canBuildDirectly;
        }
Exemplo n.º 2
0
        /// <summary>
        /// Produces a set of targets which allows the MSBuild scheduler to schedule projects in the order automatically by 
        /// following their dependencies without enforcing build levels.
        /// </summary>
        /// <remarks>
        /// We want MSBuild to be able to parallelize the builds of these projects where possible and still honor references.
        /// Since the project files referenced by the solution do not (necessarily) themselves contain actual project references
        /// to the projects they depend on, we need to synthesize this relationship ourselves.  This is done by creating a target
        /// which first invokes the project's dependencies, then invokes the actual project itself.  However, invoking the 
        /// dependencies must also invoke their dependencies and so on down the line.  
        /// 
        /// Additionally, we do not wish to create a separate MSBuild project to contain this target yet we want to parallelize
        /// calls to these targets.  The way to do this is to pass in different global properties to the same project in the same
        /// MSBuild call.  MSBuild easily allows this using the AdditionalProperties metadata which can be specified on an Item.
        /// 
        /// Assuming the solution project we are generating is called "foo.proj", we can accomplish this parallelism as follows:
        /// <ItemGroup>
        ///     <ProjectReference Include="Project0"/>
        ///     <ProjectReference Include="Project1"/>
        ///     <ProjectReference Include="Project2"/>
        /// </ItemGroup>
        /// 
        /// We now have expressed the top level reference to all projects as @(SolutionReference) and each project's
        /// set of references as @(PROJECTNAMEReference).  We construct our target as:
        /// 
        /// <Target Name="Build">
        ///     <MSBuild Projects="@(ProjectReference)" Targets="Build" />
        ///     <MSBuild Projects="actualProjectName" Targets="Build" />
        /// </Target>
        /// 
        /// The first MSBuild call re-invokes the solution project instructing it to build the reference projects for the
        /// current project.  The second MSBuild call invokes the actual project itself.  Because all reference projects have
        /// the same additional properties, MSBuild will only build the first one it comes across and the rest will be
        /// satisfied from the cache.
        /// </remarks>
        private ProjectInstance CreateMetaproject(ProjectInstance traversalProject, ProjectInSolution project, ProjectConfigurationInSolution projectConfiguration)
        {
            // Create a new project instance with global properties and tools version from the existing project
            ProjectInstance metaprojectInstance = new ProjectInstance(EscapingUtilities.UnescapeAll(GetMetaprojectName(project)), traversalProject, GetMetaprojectGlobalProperties(traversalProject));

            // Add the project references which must build before this one.
            AddMetaprojectReferenceItems(traversalProject, metaprojectInstance, project);

            // This string holds the error message generated when we try to determine if a project is an MSBuild format
            // project but it is not.
            string unknownProjectTypeErrorMessage;

            if (project.ProjectType == SolutionProjectType.WebProject)
            {
                AddMetaprojectTargetForWebProject(traversalProject, metaprojectInstance, project, null);
                AddMetaprojectTargetForWebProject(traversalProject, metaprojectInstance, project, "Clean");
                AddMetaprojectTargetForWebProject(traversalProject, metaprojectInstance, project, "Rebuild");
                AddMetaprojectTargetForWebProject(traversalProject, metaprojectInstance, project, "Publish");
            }
            else if ((project.ProjectType == SolutionProjectType.KnownToBeMSBuildFormat) ||
                     (project.CanBeMSBuildProjectFile(out unknownProjectTypeErrorMessage)))
            {
                string safeItemNameFromProjectName = MakeIntoSafeItemName(project.ProjectName);
                string targetOutputItemName = string.Format(CultureInfo.InvariantCulture, "{0}BuildOutput", safeItemNameFromProjectName);

                AddMetaprojectTargetForManagedProject(traversalProject, metaprojectInstance, project, projectConfiguration, "Clean", null);
                AddMetaprojectTargetForManagedProject(traversalProject, metaprojectInstance, project, projectConfiguration, null, targetOutputItemName);
                AddMetaprojectTargetForManagedProject(traversalProject, metaprojectInstance, project, projectConfiguration, "Rebuild", targetOutputItemName);
                AddMetaprojectTargetForManagedProject(traversalProject, metaprojectInstance, project, projectConfiguration, "Publish", null);
            }
            else
            {
                AddMetaprojectTargetForUnknownProjectType(traversalProject, metaprojectInstance, project, null, unknownProjectTypeErrorMessage);
                AddMetaprojectTargetForUnknownProjectType(traversalProject, metaprojectInstance, project, "Clean", unknownProjectTypeErrorMessage);
                AddMetaprojectTargetForUnknownProjectType(traversalProject, metaprojectInstance, project, "Rebuild", unknownProjectTypeErrorMessage);
                AddMetaprojectTargetForUnknownProjectType(traversalProject, metaprojectInstance, project, "Publish", unknownProjectTypeErrorMessage);
            }

            return metaprojectInstance;
        }