private IPipGraphBuilder CreatePipGraphBuilder( LoggingContext loggingContext, MountsTable mountsTable, [CanBeNull] GraphReuseResult reuseResult) { var builder = new PipGraph.Builder( EngineSchedule.CreateEmptyPipTable(Context), Context, Scheduler.Tracing.Logger.Log, loggingContext, Configuration, mountsTable.MountPathExpander, fingerprintSalt: Configuration.Cache.CacheSalt, directoryMembershipFingerprinterRules: new Scheduler.DirectoryMembershipFingerprinterRuleSet(Configuration, Context.StringTable)); PatchablePipGraph patchableGraph = null; if (Configuration.FrontEnd.UseGraphPatching() && reuseResult?.IsPartialReuse == true) { Logger.Log.UsingPatchableGraphBuilder(loggingContext); patchableGraph = new PatchablePipGraph( oldPipGraph: reuseResult.PipGraph.DataflowGraph, oldPipTable: reuseResult.PipGraph.PipTable, graphBuilder: builder, maxDegreeOfParallelism: Configuration.FrontEnd.MaxFrontEndConcurrency()); } return((IPipGraphBuilder)patchableGraph ?? builder); }
public RequiredDependencyAnalyzer(AnalysisInput input) : base(input) { m_pool = new ObjectPool <WorkerAnalyzer>(() => CreateAnalyzer(), w => { }); m_pipTable = EngineSchedule.CreateEmptyPipTable(input.CachedGraph.Context); }
public static bool TryBuildWorkspace( ICommandLineConfiguration commandLineConfig, FrontEndContext frontEndContext, EngineContext engineContext, EvaluationFilter evaluationFilter, EventHandler <WorkspaceProgressEventArgs> progressHandler, out Workspace workspace, out FrontEndHostController frontEndHostController, out IPipGraph pipGraph, WorkspaceBuilderConfiguration configuration, FrontEndEngineAbstraction frontEndEngineAbstraction = null, bool collectMemoryAsSoonAsPossible = true) { Contract.Requires((commandLineConfig.Engine.Phase & (EnginePhases.ParseWorkspace | EnginePhases.AnalyzeWorkspace)) != EnginePhases.None); Contract.Requires(frontEndContext != null); Contract.Requires(engineContext != null); Contract.Requires(commandLineConfig.Startup.ConfigFile.IsValid); Contract.Requires(evaluationFilter != null); workspace = null; frontEndHostController = null; pipGraph = null; var pathTable = engineContext.PathTable; var loggingContext = frontEndContext.LoggingContext; var mutableCommandlineConfig = GetCommandLineConfiguration( commandLineConfig, configuration); BuildXLEngine.ModifyConfigurationForCloudbuild(mutableCommandlineConfig, false, pathTable, loggingContext); BuildXLEngine.PopulateLoggingAndLayoutConfiguration(mutableCommandlineConfig, pathTable, bxlExeLocation: null); var statistics = new FrontEndStatistics(progressHandler); var frontEndControllerFactory = FrontEndControllerFactory.Create( mode: FrontEndMode.NormalMode, loggingContext: loggingContext, configuration: mutableCommandlineConfig, collector: null, statistics: statistics, collectMemoryAsSoonAsPossible: collectMemoryAsSoonAsPossible); var controller = frontEndControllerFactory.Create(engineContext.PathTable, engineContext.SymbolTable); controller.InitializeHost(frontEndContext, mutableCommandlineConfig); frontEndHostController = (FrontEndHostController)controller; // If there is an explicit engine abstraction, we set it. This is used by IDE test. if (frontEndEngineAbstraction != null) { frontEndHostController.SetState(frontEndEngineAbstraction, pipGraph: null, configuration: mutableCommandlineConfig); } var config = controller.ParseConfig(mutableCommandlineConfig); if (config == null) { return(false); } IPipGraph pipGraphBuilder = null; using (var cache = Task.FromResult <Possible <EngineCache> >( new EngineCache( new InMemoryArtifactContentCache(), // Note that we have an 'empty' store (no hits ever) rather than a normal in memory one. new EmptyTwoPhaseFingerprintStore()))) { if (frontEndEngineAbstraction == null) { if (mutableCommandlineConfig.Engine.Phase.HasFlag(EnginePhases.Schedule)) { var mountsTable = MountsTable.CreateAndRegister(loggingContext, engineContext, config, mutableCommandlineConfig.Startup.Properties); frontEndEngineAbstraction = new FrontEndEngineImplementation( loggingContext, frontEndContext.PathTable, config, mutableCommandlineConfig.Startup, mountsTable, InputTracker.CreateDisabledTracker(loggingContext), null, null, () => FileContentTable.CreateStub(), 5000, false); pipGraphBuilder = new PipGraph.Builder( EngineSchedule.CreateEmptyPipTable(engineContext), engineContext, Scheduler.Tracing.Logger.Log, loggingContext, config, mountsTable.MountPathExpander, fingerprintSalt: config.Cache.CacheSalt, directoryMembershipFingerprinterRules: new DirectoryMembershipFingerprinterRuleSet(config, engineContext.StringTable)); if (!AddConfigurationMountsAndCompleteInitialization(config, loggingContext, mountsTable)) { return(false); } IDictionary <ModuleId, MountsTable> moduleMountsTableMap; if (!mountsTable.PopulateModuleMounts(config.ModulePolicies.Values, out moduleMountsTableMap)) { Contract.Assume(loggingContext.ErrorWasLogged, "An error should have been logged after MountTable.PopulateModuleMounts()"); return(false); } } else { frontEndEngineAbstraction = new BasicFrontEndEngineAbstraction(frontEndContext.PathTable, frontEndContext.FileSystem, config); } } using (frontEndEngineAbstraction is IDisposable ? (IDisposable)frontEndEngineAbstraction : null) { // Attempt to build and/or analyze the workspace if (!controller.PopulateGraph( cache: cache, graph: pipGraphBuilder, engineAbstraction: frontEndEngineAbstraction, evaluationFilter: evaluationFilter, configuration: config, startupConfiguration: mutableCommandlineConfig.Startup)) { workspace = frontEndHostController.GetWorkspace(); // Error has been reported already return(false); } pipGraph = pipGraphBuilder; } } Contract.Assert(frontEndHostController != null); workspace = frontEndHostController.GetWorkspace(); if (mutableCommandlineConfig.Engine.Phase == EnginePhases.AnalyzeWorkspace) { // If workspace construction is successful, we run the linter on all specs. // This makes sure the workspace will carry all the errors that will occur when running the same specs in the regular engine path workspace = CreateLintedWorkspace( workspace, frontEndContext.LoggingContext, config.FrontEnd, pathTable); } return(true); }
private static bool TryBuildWorkspaceInternal( ICommandLineConfiguration commandLineConfig, FrontEndContext frontEndContext, EngineContext engineContext, EvaluationFilter evaluationFilter, EventHandler <WorkspaceProgressEventArgs> progressHandler, out Workspace workspace, out FrontEndHostController frontEndHostController, out IMutablePipGraph pipGraph, WorkspaceBuilderConfiguration configuration, bool forIDE, FrontEndEngineAbstraction frontEndEngineAbstraction = null, bool collectMemoryAsSoonAsPossible = true) { Contract.Requires((commandLineConfig.Engine.Phase & (EnginePhases.ParseWorkspace | EnginePhases.AnalyzeWorkspace)) != EnginePhases.None); Contract.Requires(frontEndContext != null); Contract.Requires(engineContext != null); Contract.Requires(commandLineConfig.Startup.ConfigFile.IsValid); Contract.Requires(evaluationFilter != null); workspace = null; frontEndHostController = null; pipGraph = null; var pathTable = engineContext.PathTable; var loggingContext = frontEndContext.LoggingContext; var mutableCommandlineConfig = GetCommandLineConfiguration( commandLineConfig, configuration); BuildXLEngine.ModifyConfigurationForCloudbuild(mutableCommandlineConfig, false, pathTable, loggingContext); BuildXLEngine.PopulateLoggingAndLayoutConfiguration(mutableCommandlineConfig, pathTable, bxlExeLocation: null); var statistics = new FrontEndStatistics(progressHandler); var frontEndControllerFactory = FrontEndControllerFactory.Create( mode: FrontEndMode.NormalMode, loggingContext: loggingContext, configuration: mutableCommandlineConfig, collector: null, statistics: statistics, collectMemoryAsSoonAsPossible: collectMemoryAsSoonAsPossible); var controller = frontEndControllerFactory.Create(engineContext.PathTable, engineContext.SymbolTable); controller.InitializeHost(frontEndContext, mutableCommandlineConfig); frontEndHostController = (FrontEndHostController)controller; // If there is an explicit engine abstraction, we set it. This is used by the IDE. if (frontEndEngineAbstraction != null) { // The IDE engine typically doesn't have mounts configured. We do it here if they haven't been configured yet. // Observe these are just the default mounts used for config evaluation. if (frontEndEngineAbstraction is BasicFrontEndEngineAbstraction basicEngine && !frontEndEngineAbstraction.GetMountNames("Script", BuildXL.Utilities.ModuleId.Invalid).Any()) { // If this fails we just ignore the failure. Mounts not being properly configured doesn't prevent the IDE plugin from working. basicEngine.TryPopulateWithDefaultMountsTable(loggingContext, engineContext, mutableCommandlineConfig, mutableCommandlineConfig.Startup.Properties); } frontEndHostController.SetState(frontEndEngineAbstraction, pipGraph: null, configuration: mutableCommandlineConfig); } else { // Otherwise we construct one with all mounts populated for config evaluation var configurationEngine = new BasicFrontEndEngineAbstraction(engineContext.PathTable, engineContext.FileSystem, mutableCommandlineConfig); if (!configurationEngine.TryPopulateWithDefaultMountsTable(loggingContext, engineContext, mutableCommandlineConfig, mutableCommandlineConfig.Startup.Properties)) { // Errors are logged already return(false); } frontEndEngineAbstraction = configurationEngine; } var config = controller.ParseConfig(frontEndEngineAbstraction, mutableCommandlineConfig); if (config == null) { return(false); } IMutablePipGraph pipGraphBuilder = null; using (var cache = Task.FromResult <Possible <EngineCache> >( new EngineCache( new InMemoryArtifactContentCache(), // Note that we have an 'empty' store (no hits ever) rather than a normal in memory one. new EmptyTwoPhaseFingerprintStore()))) { var mountsTable = MountsTable.CreateAndRegister(loggingContext, engineContext, config, mutableCommandlineConfig.Startup.Properties); // For the IDE case, we want to make sure all config-specific mounts are properly populated if (forIDE && frontEndEngineAbstraction is BasicFrontEndEngineAbstraction languageServiceEngine) { Contract.AssertNotNull(frontEndEngineAbstraction); AddConfigurationMounts(config, mountsTable); languageServiceEngine.SetMountsTable(mountsTable); } if (frontEndEngineAbstraction == null) { if (mutableCommandlineConfig.Engine.Phase.HasFlag(EnginePhases.Schedule)) { frontEndEngineAbstraction = new FrontEndEngineImplementation( loggingContext, frontEndContext.PathTable, config, mutableCommandlineConfig.Startup, mountsTable, InputTracker.CreateDisabledTracker(loggingContext), null, null, () => FileContentTable.CreateStub(loggingContext), 5000, false, controller.RegisteredFrontEnds); var searchPathToolsHash = new DirectoryMembershipFingerprinterRuleSet(config, engineContext.StringTable).ComputeSearchPathToolsHash(); pipGraphBuilder = new PipGraph.Builder( EngineSchedule.CreateEmptyPipTable(engineContext), engineContext, Pips.Tracing.Logger.Log, loggingContext, config, mountsTable.MountPathExpander, fingerprintSalt: config.Cache.CacheSalt, searchPathToolsHash: searchPathToolsHash); // Observe mount table is completed during workspace construction AddConfigurationMounts(config, mountsTable); IDictionary <ModuleId, MountsTable> moduleMountsTableMap; if (!mountsTable.PopulateModuleMounts(config.ModulePolicies.Values, out moduleMountsTableMap)) { Contract.Assume(loggingContext.ErrorWasLogged, "An error should have been logged after MountTable.PopulateModuleMounts()"); return(false); } } else { frontEndEngineAbstraction = new BasicFrontEndEngineAbstraction(frontEndContext.PathTable, frontEndContext.FileSystem, config); } } using (frontEndEngineAbstraction is IDisposable ? (IDisposable)frontEndEngineAbstraction : null) { // Attempt to build and/or analyze the workspace if (!controller.PopulateGraph( cache: cache, graph: pipGraphBuilder, engineAbstraction: frontEndEngineAbstraction, evaluationFilter: evaluationFilter, configuration: config, startupConfiguration: mutableCommandlineConfig.Startup)) { workspace = frontEndHostController.GetWorkspace(); // Error has been reported already return(false); } pipGraph = pipGraphBuilder; } } Contract.Assert(frontEndHostController != null); workspace = frontEndHostController.GetWorkspace(); if (mutableCommandlineConfig.Engine.Phase == EnginePhases.AnalyzeWorkspace) { // If workspace construction is successful, we run the linter on all specs. // This makes sure the workspace will carry all the errors that will occur when running the same specs in the regular engine path workspace = CreateLintedWorkspace( workspace, frontEndContext.LoggingContext, config.FrontEnd, pathTable); } return(true); }