Пример #1
0
        /// <summary>
        /// Saves the project once the imports have been evaluated
        /// </summary>
        private void SavePostEvaluationProject(ProjectInstance projectInstance)
        {
            string postBuildProject = projectInstance.FullPath + ".postbuild.proj";

            projectInstance.ToProjectRootElement().Save(postBuildProject);
            this.TestContext.AddResultFile(postBuildProject);
        }
Пример #2
0
        //=====================================================================

        /// <summary>
        /// This is used to execute the task and perform the build
        /// </summary>
        /// <returns>True on success or false on failure.</returns>
        public override bool Execute()
        {
            Project         msBuildProject            = null;
            ProjectInstance projectInstance           = null;
            bool            removeProjectWhenDisposed = false;
            string          line;

            // If canceled already, just return
            if (buildCancelled)
            {
                return(false);
            }

            try
            {
                if (!this.AlwaysLoadProject)
                {
                    // Use the current project if possible.  This is preferable as we can make use
                    // of command line property overrides and any other user-defined properties.
                    this.ProjectFile = Path.GetFullPath(this.ProjectFile);

                    // This collection is new to the MSBuild 4.0 API.  If you load a project, it appears
                    // in the collection.  However, if you run MSBuild.exe, it doesn't put the project in
                    // this collection.  As such, we must still resort to reflection to get the executing
                    // project.  I'm leaving this here in case that ever changes as this is preferable to
                    // using Reflection to get at the current project.
                    var matchingProjects = ProjectCollection.GlobalProjectCollection.GetLoadedProjects(
                        this.ProjectFile);

                    if (matchingProjects.Count != 0)
                    {
                        if (matchingProjects.Count != 1)
                        {
                            Log.LogWarning(null, "BHT0004", "BHT0004", "SHFB", 0, 0, 0, 0, "Multiple matching " +
                                           "projects were found.  Only the first one found will be built.");
                        }

                        msBuildProject = matchingProjects.First();
                    }
                    else
                    {
                        projectInstance = this.GetCurrentProjectInstance();
                    }
                }
            }
            catch (Exception ex)
            {
                // Ignore exceptions but issue a warning and fall back to using
                // the passed project filename instead.
                Log.LogWarning(null, "BHT0001", "BHT0001", "SHFB", 0, 0, 0, 0, "Unable to get executing " +
                               "project: {0}.  The specified project will be loaded but command line property " +
                               "overrides will be ignored.", ex.Message);
            }

            try
            {
                if (msBuildProject == null)
                {
                    removeProjectWhenDisposed = true;

                    if (projectInstance != null)
                    {
                        msBuildProject = new Project(projectInstance.ToProjectRootElement());

                        // ToProjectRootElement() will not add properties in the global collection to the
                        // project.  One problem with this is that command line overrides get missed.  As such,
                        // we'll add them back to the project as long as they are not reserved names and are not
                        // there already.
                        foreach (var p in projectInstance.GlobalProperties)
                        {
                            if (!SandcastleProject.RestrictedProperties.Contains(p.Key) &&
                                !msBuildProject.AllEvaluatedProperties.Any(ep => ep.Name == p.Key))
                            {
                                msBuildProject.SetProperty(p.Key, p.Value);
                            }
                        }

                        msBuildProject.FullPath = this.ProjectFile;
                    }
                    else
                    {
                        if (!File.Exists(this.ProjectFile))
                        {
                            throw new BuilderException("BHT0003", "The specified project file does not exist: " +
                                                       this.ProjectFile);
                        }

                        Log.LogWarning(null, "BHT0001", "BHT0001", "SHFB", 0, 0, 0, 0, "Unable to get " +
                                       "executing project:  Unable to obtain matching project from the global " +
                                       "collection.  The specified project will be loaded but command line property " +
                                       "overrides will be ignored.");

                        // Create the project and set the configuration and platform options
                        msBuildProject = new Project(this.ProjectFile);
                    }

                    msBuildProject.SetGlobalProperty(BuildItemMetadata.Configuration, this.Configuration);
                    msBuildProject.SetGlobalProperty(BuildItemMetadata.Platform, this.Platform);

                    // Override the OutDir property if defined for Team Build.  Ignore ".\" as that's our default.
                    if (!String.IsNullOrEmpty(this.OutDir) && this.OutDir != @".\")
                    {
                        msBuildProject.SetGlobalProperty(BuildItemMetadata.OutDir, this.OutDir);
                    }

                    msBuildProject.ReevaluateIfNecessary();
                }

                // initialize properties that where provided in Properties
                if (!String.IsNullOrWhiteSpace(Properties))
                {
                    foreach (string propertyKeyValue in this.Properties.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries))
                    {
#if NET472_OR_GREATER
                        int length = propertyKeyValue.IndexOf('=');
#else
                        int length = propertyKeyValue.IndexOf('=', StringComparison.Ordinal);
#endif
                        if (length != -1)
                        {
                            string propertyKey   = propertyKeyValue.Substring(0, length).Trim();
                            string propertyValue = propertyKeyValue.Substring(length + 1).Trim();

                            if (!String.IsNullOrWhiteSpace(propertyKey))
                            {
                                Log.LogMessage(MessageImportance.Low, "Setting property {0}={1}", propertyKey, propertyValue);
                                msBuildProject.SetGlobalProperty(propertyKey, propertyValue);
                            }
                        }
                    }

                    msBuildProject.ReevaluateIfNecessary();
                }

                cts = new CancellationTokenSource();

                // Associate the MSBuild project with a SHFB project instance and build it
                using (sandcastleProject = new SandcastleProject(msBuildProject))
                {
                    buildProcess = new BuildProcess(sandcastleProject)
                    {
                        ProgressReportProvider = this,
                        CancellationToken      = cts.Token
                    };

                    // Since this is an MSBuild task, we'll run it directly rather than in a background thread
                    Log.LogMessage(MessageImportance.High, "Building {0}", msBuildProject.FullPath);

                    // When ran with dotnet.exe, sometimes it can't find the core dependencies.  The resolver
                    // fixes that.
                    using (var resolver = new ComponentAssemblyResolver())
                    {
                        buildProcess.Build();
                    }

                    lastBuildStep = buildProcess.CurrentBuildStep;
                }
            }
            catch (Exception ex)
            {
                Log.LogError(null, "BHT0002", "BHT0002", "SHFB", 0, 0, 0, 0,
                             "Unable to build project '{0}': {1}", msBuildProject.FullPath, ex);
            }
            finally
            {
                if (cts != null)
                {
                    cts.Dispose();
                    cts = null;
                }

                // If we loaded it, we must unload it.  If not, it is cached and may cause problems later.
                if (removeProjectWhenDisposed && msBuildProject != null)
                {
                    ProjectCollection.GlobalProjectCollection.UnloadProject(msBuildProject);
                    ProjectCollection.GlobalProjectCollection.UnloadProject(msBuildProject.Xml);
                }
            }

            if (this.DumpLogOnFailure && lastBuildStep == BuildStep.Failed)
            {
                using (StreamReader sr = new StreamReader(buildProcess.LogFilename))
                {
                    Log.LogMessage(MessageImportance.High, "Log Content:");

                    do
                    {
                        line = sr.ReadLine();

                        // Don't output the XML elements, just the text
                        if (line != null && (line.Trim().Length == 0 || line.Trim()[0] != '<'))
                        {
                            Log.LogMessage(MessageImportance.High, line);
                        }
                    } while(line != null);
                }
            }

            return(lastBuildStep == BuildStep.Completed);
        }