示例#1
0
        public void TestValidHostObjectRegistration()
        {
            HostServices hostServices = new HostServices();
            TestHostObject hostObject = new TestHostObject();
            TestHostObject hostObject2 = new TestHostObject();
            TestHostObject hostObject3 = new TestHostObject();
            hostServices.RegisterHostObject("foo.proj", "target", "task", hostObject);
            hostServices.RegisterHostObject("foo.proj", "target2", "task", hostObject2);
            hostServices.RegisterHostObject("foo.proj", "target", "task2", hostObject3);

            Assert.AreSame(hostObject, hostServices.GetHostObject("foo.proj", "target", "task"));
            Assert.AreSame(hostObject2, hostServices.GetHostObject("foo.proj", "target2", "task"));
            Assert.AreSame(hostObject3, hostServices.GetHostObject("foo.proj", "target", "task2"));
        }
示例#2
0
        protected async Task <BuildInfo> BuildAsync(string taskName, MSB.Framework.ITaskHost taskHost, CancellationToken cancellationToken)
        {
            // create a project instance to be executed by build engine.
            // The executed project will hold the final model of the project after execution via msbuild.
            var executedProject = _loadedProject.CreateProjectInstance();

            if (!executedProject.Targets.ContainsKey("Compile"))
            {
                return(new BuildInfo(executedProject, null));
            }

            var hostServices = new Microsoft.Build.Execution.HostServices();

            // connect the host "callback" object with the host services, so we get called back with the exact inputs to the compiler task.
            hostServices.RegisterHostObject(_loadedProject.FullPath, "CoreCompile", taskName, taskHost);

            var buildParameters = new MSB.Execution.BuildParameters(_loadedProject.ProjectCollection);

            var buildRequestData = new MSB.Execution.BuildRequestData(executedProject, new string[] { "Compile" }, hostServices);

            BuildResult result = await this.BuildAsync(buildParameters, buildRequestData, cancellationToken).ConfigureAwait(continueOnCapturedContext: false);

            if (result.OverallResult == BuildResultCode.Failure)
            {
                return(new BuildInfo(executedProject, result.Exception?.Message ?? ""));
            }
            else
            {
                return(new BuildInfo(executedProject, null));
            }
        }
示例#3
0
        protected async Task <BuildResult> BuildAsync(string taskName, MSB.Framework.ITaskHost taskHost, CancellationToken cancellationToken)
        {
            // prepare for building
            var buildTargets = new BuildTargets(loadedProject, "Compile");

            // Don't execute this one. It will build referenced projects.
            // Even when DesignTimeBuild is defined above, it will still add the referenced project's output to the references list
            // which we don't want.
            buildTargets.Remove("ResolveProjectReferences");

            // don't execute anything after CoreCompile target, since we've
            // already done everything we need to compute compiler inputs by then.
            buildTargets.RemoveAfter("CoreCompile", includeTargetInRemoval: false);

            // create a project instance to be executed by build engine.
            // The executed project will hold the final model of the project after execution via msbuild.
            var executedProject = loadedProject.CreateProjectInstance();

            var hostServices = new Microsoft.Build.Execution.HostServices();

            // connect the host "callback" object with the host services, so we get called back with the exact inputs to the compiler task.
            hostServices.RegisterHostObject(this.loadedProject.FullPath, "CoreCompile", taskName, taskHost);

            var buildParameters = new MSB.Execution.BuildParameters(loadedProject.ProjectCollection);

            var buildRequestData = new MSB.Execution.BuildRequestData(executedProject, buildTargets.Targets, hostServices);

            var result = await this.BuildAsync(buildParameters, buildRequestData, cancellationToken).ConfigureAwait(continueOnCapturedContext: false);

            return(new BuildResult(result, executedProject));
        }
示例#4
0
 public void TestInvalidHostObjectRegistration_NullTarget()
 {
     Assert.Throws<ArgumentNullException>(() =>
     {
         HostServices hostServices = new HostServices();
         TestHostObject hostObject = new TestHostObject();
         hostServices.RegisterHostObject("project", null, "task", hostObject);
     }
    );
 }
示例#5
0
        private async Task <Compilation> BuildAsync(string inputProjectFile, ICompilationHost compilationHost, CancellationToken cancellationToken = default(CancellationToken))
        {
            var hostServices = new HostServices();

            hostServices.RegisterHostObject(inputProjectFile, "CoreCompile", compilationHost.TaskName, compilationHost);

            var properties = new Dictionary <string, string>(_properties ?? ImmutableDictionary <string, string> .Empty)
            {
                ["DesignTimeBuild"]            = "true", // this will tell msbuild to not build the dependent projects
                ["BuildingInsideVisualStudio"] = "true"  // this will force CoreCompile task to execute even if all inputs and outputs are up to date
            };

            var errorLogger = new Logger()
            {
                Verbosity = LoggerVerbosity.Normal
            };

            var buildParameters = new BuildParameters
            {
                GlobalProperties = properties,
                Loggers          = new ILogger[] { errorLogger }
            };

            var buildRequestData = new BuildRequestData(inputProjectFile, properties, null, new string[] { "Compile" }, hostServices);
            var sw = new Stopwatch();

            sw.Start();
            Log.Trace("Begin MSBuild");
            var result = await BuildAsync(buildParameters, buildRequestData, cancellationToken).ConfigureAwait(continueOnCapturedContext: false);

            sw.Stop();
            Log.Trace($"Finish MSBuild {sw.Elapsed.TotalMilliseconds}ms");
            if (result.OverallResult == BuildResultCode.Failure)
            {
                throw result.Exception ?? new InvalidOperationException("Error during project compilation");
            }

            return(compilationHost.Compile(cancellationToken));
        }
示例#6
0
        protected async Task <ProjectInstance> BuildAsync(string taskName, MSB.Framework.ITaskHost taskHost, CancellationToken cancellationToken)
        {
            // prepare for building
            var buildTargets = new BuildTargets(_loadedProject, "Compile");

            // don't execute anything after CoreCompile target, since we've
            // already done everything we need to compute compiler inputs by then.
            buildTargets.RemoveAfter("CoreCompile", includeTargetInRemoval: false);

            // create a project instance to be executed by build engine.
            // The executed project will hold the final model of the project after execution via msbuild.
            var executedProject = _loadedProject.CreateProjectInstance();

            if (!executedProject.Targets.ContainsKey("Compile"))
            {
                return(executedProject);
            }

            var hostServices = new Microsoft.Build.Execution.HostServices();

            // connect the host "callback" object with the host services, so we get called back with the exact inputs to the compiler task.
            hostServices.RegisterHostObject(_loadedProject.FullPath, "CoreCompile", taskName, taskHost);

            var buildParameters = new MSB.Execution.BuildParameters(_loadedProject.ProjectCollection);

            var buildRequestData = new MSB.Execution.BuildRequestData(executedProject, buildTargets.Targets, hostServices);

            var result = await this.BuildAsync(buildParameters, buildRequestData, cancellationToken).ConfigureAwait(continueOnCapturedContext: false);

            if (result.Exception != null)
            {
                throw result.Exception;
            }

            return(executedProject);
        }
示例#7
0
        public void TestUnregisteringNonConflictingHostObjectRestoresOriginalAffinity()
        {
            HostServices hostServices = new HostServices();
            TestHostObject hostObject = new TestHostObject();
            hostServices.SetNodeAffinity(String.Empty, NodeAffinity.OutOfProc);
            hostServices.SetNodeAffinity("project", NodeAffinity.Any);
            Assert.AreEqual(NodeAffinity.OutOfProc, hostServices.GetNodeAffinity("project2"));
            Assert.AreEqual(NodeAffinity.Any, hostServices.GetNodeAffinity("project"));

            hostServices.RegisterHostObject("project", "target", "task", hostObject);
            Assert.AreEqual(NodeAffinity.InProc, hostServices.GetNodeAffinity("project"));
            hostServices.RegisterHostObject("project", "target", "task", null);
            Assert.AreEqual(NodeAffinity.Any, hostServices.GetNodeAffinity("project"));
            Assert.AreEqual(NodeAffinity.OutOfProc, hostServices.GetNodeAffinity("project2"));
        }
示例#8
0
 public void TestAffinityChangeAfterClearingHostObject()
 {
     HostServices hostServices = new HostServices();
     TestHostObject hostObject = new TestHostObject();
     hostServices.RegisterHostObject("project", "target", "task", hostObject);
     Assert.AreEqual(NodeAffinity.InProc, hostServices.GetNodeAffinity("project"));
     hostServices.RegisterHostObject("project", "target", "task", null);
     Assert.AreEqual(NodeAffinity.Any, hostServices.GetNodeAffinity("project"));
     hostServices.SetNodeAffinity("project", NodeAffinity.OutOfProc);
     Assert.AreEqual(NodeAffinity.OutOfProc, hostServices.GetNodeAffinity("project"));
 }
示例#9
0
 public void TestNonContraditcoryHostObjectAllowed_InProc()
 {
     HostServices hostServices = new HostServices();
     TestHostObject hostObject = new TestHostObject();
     hostServices.SetNodeAffinity("project", NodeAffinity.InProc);
     hostServices.RegisterHostObject("project", "target", "task", hostObject);
 }
示例#10
0
 public void TestNonContraditcoryHostObjectAllowed_Any()
 {
     HostServices hostServices = new HostServices();
     TestHostObject hostObject = new TestHostObject();
     hostServices.SetNodeAffinity("project", NodeAffinity.Any);
     hostServices.RegisterHostObject("project", "target", "task", hostObject);
     Assert.AreEqual(NodeAffinity.InProc, hostServices.GetNodeAffinity("project"));
 }
示例#11
0
 public void TestContraditcoryHostObjectCausesException_OutOfProc()
 {
     HostServices hostServices = new HostServices();
     TestHostObject hostObject = new TestHostObject();
     hostServices.SetNodeAffinity("project", NodeAffinity.OutOfProc);
     hostServices.RegisterHostObject("project", "target", "task", hostObject);
 }
示例#12
0
 public void TestInvalidHostObjectRegistration_NullTask()
 {
     HostServices hostServices = new HostServices();
     TestHostObject hostObject = new TestHostObject();
     hostServices.RegisterHostObject("project", "target", null, hostObject);
 }
示例#13
0
        public static ProjectDetails LoadProjectDetails(BuildEnvironment environment)
        {
            var            key = Tuple.Create(environment.ProjectFile, environment.Configuration);
            ProjectDetails details;

            if (_allProjects.TryGetValue(key, out details))
            {
                if (!details.HasChanged())
                {
                    if (_log.IsEnabled(Microsoft.Extensions.Logging.LogLevel.Debug))
                    {
                        _log.LogDebug($"Using cached project file details for [{environment.ProjectFile}]");
                    }

                    return(details);
                }
                else
                {
                    if (_log.IsEnabled(Microsoft.Extensions.Logging.LogLevel.Debug))
                    {
                        _log.LogDebug($"Reloading project file details [{environment.ProjectFile}] as one of its imports has been modified.");
                    }
                }
            }

            if (_log.IsEnabled(Microsoft.Extensions.Logging.LogLevel.Debug))
            {
                _log.LogDebug($"Loading project file [{environment.ProjectFile}]");
            }

            details = new ProjectDetails();

            var properties = new Dictionary <string, string>(ImmutableDictionary <string, string> .Empty)
            {
                ["DesignTimeBuild"]                  = "true", // this will tell msbuild to not build the dependent projects
                ["BuildingInsideVisualStudio"]       = "true", // this will force CoreCompile task to execute even if all inputs and outputs are up to date
                ["BuildingInsideUnoSourceGenerator"] = "true", // this will force prevent the task to run recursively
                ["Configuration"] = environment.Configuration,
                ["UseHostCompilerIfAvailable"] = "true",
                ["UseSharedCompilation"]       = "true",
                ["VisualStudioVersion"]        = environment.VisualStudioVersion,

                // Force the intermediate path to be different from the VS default path
                // so that the generated files don't mess up the file count for incremental builds.
                ["IntermediateOutputPath"] = Path.Combine(environment.OutputPath, "obj") + Path.DirectorySeparatorChar
            };

            // Target framework is required for the MSBuild 15.0 Cross Compilation.
            // Loading a project without the target framework results in an empty project, which interatively
            // sets the TargetFramework property.
            if (environment.TargetFramework.HasValue())
            {
                properties["TargetFramework"] = environment.TargetFramework;
            }

            // TargetFrameworkRootPath is used by VS4Mac to determine the
            // location of frameworks like Xamarin.iOS.
            if (environment.TargetFrameworkRootPath.HasValue())
            {
                properties["TargetFrameworkRootPath"] = environment.TargetFrameworkRootPath;
            }

            // Platform is intentionally kept as not defined, to avoid having
            // dependent projects being loaded with a platform they don't support.
            // properties["Platform"] = _platform;

            var xmlReader  = XmlReader.Create(environment.ProjectFile);
            var collection = new Microsoft.Build.Evaluation.ProjectCollection();

            // Change this logger details to troubleshoot project loading details.
            collection.RegisterLogger(new Microsoft.Build.Logging.ConsoleLogger()
            {
                Verbosity = LoggerVerbosity.Minimal
            });

            // Uncomment this to enable file logging for debugging purposes.
            // collection.RegisterLogger(new Microsoft.Build.BuildEngine.FileLogger() { Verbosity = LoggerVerbosity.Diagnostic, Parameters = $@"logfile=c:\temp\build\MSBuild.{Guid.NewGuid()}.log" });

            collection.OnlyLogCriticalEvents = false;
            var xml = Microsoft.Build.Construction.ProjectRootElement.Create(xmlReader, collection);

            // When constructing a project from an XmlReader, MSBuild cannot determine the project file path.  Setting the
            // path explicitly is necessary so that the reserved properties like $(MSBuildProjectDirectory) will work.
            xml.FullPath = Path.GetFullPath(environment.ProjectFile);

            var loadedProject = new Microsoft.Build.Evaluation.Project(
                xml,
                properties,
                toolsVersion: null,
                projectCollection: collection
                );

            var buildTargets = new BuildTargets(loadedProject, "Compile");

            // don't execute anything after CoreCompile target, since we've
            // already done everything we need to compute compiler inputs by then.
            buildTargets.RemoveAfter("CoreCompile", includeTargetInRemoval: true);

            details.Configuration = environment.Configuration;
            details.LoadedProject = loadedProject;

            // create a project instance to be executed by build engine.
            // The executed project will hold the final model of the project after execution via msbuild.
            details.ExecutedProject = loadedProject.CreateProjectInstance();

            var hostServices = new Microsoft.Build.Execution.HostServices();

            // connect the host "callback" object with the host services, so we get called back with the exact inputs to the compiler task.
            hostServices.RegisterHostObject(loadedProject.FullPath, "CoreCompile", "Csc", null);

            var buildParameters = new Microsoft.Build.Execution.BuildParameters(loadedProject.ProjectCollection);

            // This allows for the loggers to
            buildParameters.Loggers = collection.Loggers;

            var buildRequestData = new Microsoft.Build.Execution.BuildRequestData(details.ExecutedProject, buildTargets.Targets, hostServices);

            var result = BuildAsync(buildParameters, buildRequestData);

            if (result.Exception == null)
            {
                ValidateOutputPath(details.ExecutedProject);

                var projectFilePath = Path.GetFullPath(Path.GetDirectoryName(environment.ProjectFile));

                details.References = details.ExecutedProject.GetItems("ReferencePath").Select(r => r.EvaluatedInclude).ToArray();

                if (!details.References.Any())
                {
                    if (_log.IsEnabled(Microsoft.Extensions.Logging.LogLevel.Error))
                    {
                        _log.LogError($"Project has no references.");
                    }

                    LogFailedTargets(environment.ProjectFile, result);
                    details.Generators = new (Type, Func <SourceGenerator>)[0];
示例#14
0
        public static ProjectDetails LoadProjectDetails(string projectFile, string configuration)
        {
            var            key = Tuple.Create(projectFile, configuration);
            ProjectDetails details;

            if (_allProjects.TryGetValue(key, out details))
            {
                if (!details.HasChanged())
                {
                    if (_log.IsEnabled(Microsoft.Extensions.Logging.LogLevel.Debug))
                    {
                        _log.Debug($"Using cached project file details for [{projectFile}]");
                    }

                    return(details);
                }
                else
                {
                    if (_log.IsEnabled(Microsoft.Extensions.Logging.LogLevel.Debug))
                    {
                        _log.Debug($"Reloading project file details [{projectFile}] as one of its imports has been modified.");
                    }
                }
            }

            if (_log.IsEnabled(Microsoft.Extensions.Logging.LogLevel.Debug))
            {
                _log.Debug($"Loading project file [{projectFile}]");
            }

            details = new ProjectDetails();

            var properties = new Dictionary <string, string>(ImmutableDictionary <string, string> .Empty);

            properties["DesignTimeBuild"]                  = "true"; // this will tell msbuild to not build the dependent projects
            properties["BuildingInsideVisualStudio"]       = "true"; // this will force CoreCompile task to execute even if all inputs and outputs are up to date
            properties["BuildingInsideUnoSourceGenerator"] = "true"; // this will force prevent the task to run recursively
            properties["Configuration"] = configuration;
            properties["UseHostCompilerIfAvailable"] = "true";
            properties["UseSharedCompilation"]       = "true";

            // Platform is intentionally kept as not defined, to avoid having
            // dependent projects being loaded with a platform they don't support.
            // properties["Platform"] = _platform;

            var xmlReader  = XmlReader.Create(projectFile);
            var collection = new Microsoft.Build.Evaluation.ProjectCollection();

            collection.RegisterLogger(new Microsoft.Build.Logging.ConsoleLogger()
            {
                Verbosity = LoggerVerbosity.Normal
            });

            collection.OnlyLogCriticalEvents = false;
            var xml = Microsoft.Build.Construction.ProjectRootElement.Create(xmlReader, collection);

            // When constructing a project from an XmlReader, MSBuild cannot determine the project file path.  Setting the
            // path explicitly is necessary so that the reserved properties like $(MSBuildProjectDirectory) will work.
            xml.FullPath = Path.GetFullPath(projectFile);

            var loadedProject = new Microsoft.Build.Evaluation.Project(
                xml,
                properties,
                toolsVersion: null,
                projectCollection: collection
                );

            var buildTargets = new BuildTargets(loadedProject, "Compile");

            // don't execute anything after CoreCompile target, since we've
            // already done everything we need to compute compiler inputs by then.
            buildTargets.RemoveAfter("CoreCompile", includeTargetInRemoval: false);

            details.Configuration = configuration;
            details.LoadedProject = loadedProject;

            // create a project instance to be executed by build engine.
            // The executed project will hold the final model of the project after execution via msbuild.
            details.ExecutedProject = loadedProject.CreateProjectInstance();

            var hostServices = new Microsoft.Build.Execution.HostServices();

            // connect the host "callback" object with the host services, so we get called back with the exact inputs to the compiler task.
            hostServices.RegisterHostObject(loadedProject.FullPath, "CoreCompile", "Csc", null);

            var buildParameters = new Microsoft.Build.Execution.BuildParameters(loadedProject.ProjectCollection);

            // This allows for the loggers to
            buildParameters.Loggers = collection.Loggers;

            var buildRequestData = new Microsoft.Build.Execution.BuildRequestData(details.ExecutedProject, buildTargets.Targets, hostServices);

            var result = BuildAsync(buildParameters, buildRequestData);

            if (result.Exception == null)
            {
                ValidateOutputPath(details.ExecutedProject);

                var projectFilePath = Path.GetFullPath(Path.GetDirectoryName(projectFile));

                details.References = details.ExecutedProject.GetItems("ReferencePath").Select(r => r.EvaluatedInclude).ToArray();

                if (details.References.None())
                {
                    LogFailedTargets(projectFile, result);
                    return(details);
                }
            }
            else
            {
                LogFailedTargets(projectFile, result);
            }

            _allProjects.TryAdd(key, details);

            details.BuildImportsMap();

            return(details);
        }
示例#15
0
 public void TestContraditcoryHostObjectCausesException_OutOfProc()
 {
     Assert.Throws<InvalidOperationException>(() =>
     {
         HostServices hostServices = new HostServices();
         TestHostObject hostObject = new TestHostObject();
         hostServices.SetNodeAffinity("project", NodeAffinity.OutOfProc);
         hostServices.RegisterHostObject("project", "target", "task", hostObject);
     }
    );
 }
示例#16
0
        public void UnloadedProjectDiscardsHostServices()
        {
            HostServices hostServices = new HostServices();
            TestHostObject th = new TestHostObject();
            ProjectCollection.GlobalProjectCollection.HostServices = hostServices;
            Project project1 = LoadDummyProject("foo.proj");
            Project project2 = LoadDummyProject("foo.proj");

            hostServices.RegisterHostObject(project1.FullPath, "test", "Message", th);

            ProjectCollection.GlobalProjectCollection.UnloadProject(project1);

            Assert.IsTrue(hostServices.HasHostObject(project2.FullPath));

            ProjectCollection.GlobalProjectCollection.UnloadProject(project2);

            Assert.IsFalse(hostServices.HasHostObject(project2.FullPath));
        }
示例#17
0
 public void TestHostObjectCausesInProcAffinity()
 {
     HostServices hostServices = new HostServices();
     TestHostObject hostObject = new TestHostObject();
     hostServices.RegisterHostObject("project", "target", "task", hostObject);
     Assert.AreEqual(NodeAffinity.InProc, hostServices.GetNodeAffinity("project"));
 }
示例#18
0
        public void TestUnregisterHostObject()
        {
            HostServices hostServices = new HostServices();
            TestHostObject hostObject = new TestHostObject();
            hostServices.RegisterHostObject("project", "target", "task", hostObject);
            Assert.AreSame(hostObject, hostServices.GetHostObject("project", "target", "task"));

            hostServices.RegisterHostObject("project", "target", "task", null);
            Assert.IsNull(hostServices.GetHostObject("project", "target", "task"));
        }
示例#19
0
 public void TestContradictoryAffinityCausesException_Any()
 {
     HostServices hostServices = new HostServices();
     TestHostObject hostObject = new TestHostObject();
     hostServices.RegisterHostObject("project", "target", "task", hostObject);
     Assert.AreEqual(NodeAffinity.InProc, hostServices.GetNodeAffinity("project"));
     hostServices.SetNodeAffinity("project", NodeAffinity.Any);
 }