private bool CreateFactories( FrontEndContext frontEndContext, TestEngineAbstraction engineAbstraction, FrontEndStatistics frontEndStatistics, ICommandLineConfiguration configuration, out AmbientTesting ambientTesting, out ModuleRegistry moduleRegistry, out FrontEndFactory frontEndFactory) { moduleRegistry = new ModuleRegistry(frontEndContext.SymbolTable); ambientTesting = new AmbientTesting(engineAbstraction, GetAllDiagnostics, moduleRegistry.PrimitiveTypes); ambientTesting.Initialize(moduleRegistry.GlobalLiteral); var ambientAssert = new AmbientAssert(moduleRegistry.PrimitiveTypes); ambientAssert.Initialize(moduleRegistry.GlobalLiteral); // Create the controller frontEndFactory = new FrontEndFactory(); frontEndFactory.SetConfigurationProcessor(new TestConfigProcessor(configuration)); frontEndFactory.AddFrontEnd( new DScriptFrontEnd( frontEndStatistics, logger: m_astLogger)); if (!frontEndFactory.TrySeal(frontEndContext.LoggingContext)) { HandleDiagnostics(); return(false); } return(true); }
private BuildXLEngine CreateEngine(bool rememberAllChangedTrackedInputs) { IFrontEndController Create(PathTable pathTable, SymbolTable symbolTable) { var frontEndStatistics = new FrontEndStatistics(); var moduleRegistry = new ModuleRegistry(symbolTable); var frontEndFactory = FrontEndFactory.CreateInstanceForTesting( () => new ConfigurationProcessor(new FrontEndStatistics(), ParseAndEvaluateLogger), new DScriptFrontEnd(frontEndStatistics, ParseAndEvaluateLogger)); var evaluationScheduler = new EvaluationScheduler(degreeOfParallelism: 1); return(new FrontEndHostController( frontEndFactory, evaluationScheduler, moduleRegistry, new FrontEndStatistics(), logger: InitializationLogger, collector: null, collectMemoryAsSoonAsPossible: false)); } BuildXLEngine.PopulateLoggingAndLayoutConfiguration(Configuration, Context.PathTable, bxlExeLocation: null, inTestMode: true); var successfulValidation = BuildXLEngine.PopulateAndValidateConfiguration(Configuration, Configuration, Context.PathTable, LoggingContext); Assert.True(successfulValidation); var engine = BuildXLEngine.Create(LoggingContext, Context, Configuration, new LambdaBasedFrontEndControllerFactory(Create), new BuildViewModel(), rememberAllChangedTrackedInputs: rememberAllChangedTrackedInputs); engine.TestHooks = TestHooks; return(engine); }
private async Task <Workspace> TypeCheckWorkspaceAsync(Workspace workspace) { var frontEndStatistics = new FrontEndStatistics(); // don't pollute global statistics with this var semanticWorkspaceProvider = new SemanticWorkspaceProvider(frontEndStatistics, WorkspaceConfiguration); workspace = await semanticWorkspaceProvider.ComputeSemanticWorkspaceAsync(Context.PathTable, workspace); if (workspace.GetSemanticModel().GetAllSemanticDiagnostics().Any()) { return(workspace.WithExtraFailures(new[] { new Failure <string>("Failed to type check configuration") })); } return(workspace); }
private bool CreateFactories( FrontEndContext frontEndContext, TestEngineAbstraction engineAbstraction, FrontEndStatistics frontEndStatistics, ICommandLineConfiguration configuration, out AmbientTesting ambientTesting, out DScriptWorkspaceResolverFactory workspaceFactory, out FrontEndFactory frontEndFactory) { var globalConstants = new GlobalConstants(frontEndContext.SymbolTable); ambientTesting = new AmbientTesting(engineAbstraction, GetAllDiagnostics, globalConstants.KnownTypes); ambientTesting.Initialize(globalConstants.Global); var ambientAssert = new AmbientAssert(globalConstants.KnownTypes); ambientAssert.Initialize(globalConstants.Global); var sharedModuleRegistry = new ModuleRegistry(); workspaceFactory = new DScriptWorkspaceResolverFactory(); workspaceFactory.RegisterResolver( KnownResolverKind.DScriptResolverKind, () => new WorkspaceSourceModuleResolver(globalConstants, sharedModuleRegistry, frontEndStatistics)); workspaceFactory.RegisterResolver( KnownResolverKind.SourceResolverKind, () => new WorkspaceSourceModuleResolver(globalConstants, sharedModuleRegistry, frontEndStatistics)); workspaceFactory.RegisterResolver( KnownResolverKind.DefaultSourceResolverKind, () => new WorkspaceDefaultSourceModuleResolver(globalConstants, sharedModuleRegistry, frontEndStatistics)); // Create the controller frontEndFactory = new FrontEndFactory(); frontEndFactory.SetConfigurationProcessor(new TestConfigProcessor(configuration)); frontEndFactory.AddFrontEnd( new DScriptFrontEnd( globalConstants, sharedModuleRegistry, frontEndStatistics, logger: m_astLogger)); if (!frontEndFactory.TrySeal(frontEndContext.LoggingContext)) { HandleDiagnostics(); return(false); } return(true); }
/// <nodoc/> public DownloadResolver( FrontEndStatistics frontEndStatistics, EvaluationStatistics evaluationStatistics, FrontEndHost frontEndHost, FrontEndContext context, Script.Tracing.Logger logger, string frontEndName) { Contract.Requires(!string.IsNullOrEmpty(frontEndName)); Name = frontEndName; m_frontEndStatistics = frontEndStatistics; m_evaluationStatistics = evaluationStatistics; m_frontEndHost = frontEndHost; m_context = context; m_logger = logger; }
public WorkspaceEvaluationHelper(string testOutputDirectory, FrontEndContext context = null, bool forTesting = false) { AstLogger = global::BuildXL.FrontEnd.Script.Tracing.Logger.CreateLogger(preserveLogEvents: true); FrontEndLogger = global::BuildXL.FrontEnd.Core.Tracing.Logger.CreateLogger(preserveLogEvents: true); var pathTable = new PathTable(); var pathBasedFileSystem = new InMemoryFileSystem(pathTable); FrontEndContext = context ?? FrontEndContext.CreateInstanceForTesting(pathTable: pathTable, fileSystem: pathBasedFileSystem); FrontEndStatistics = new FrontEndStatistics(); Engine = new BasicFrontEndEngineAbstraction( FrontEndContext.PathTable, FrontEndContext.FileSystem ); WorkspaceHelper = new WorkspaceTestBase( PathTable, FrontEndHost.PreludeModuleName, NameResolutionSemantics.ImplicitProjectReferences, cancellationToken: FrontEndContext.CancellationToken); SrcRoot = AbsolutePath.Create(PathTable, Path.Combine(testOutputDirectory, "src")); ObjRoot = AbsolutePath.Create(PathTable, Path.Combine(testOutputDirectory, "obj")); }
/// <summary> /// Run the test /// </summary> public bool Run(string testFolder, string specFile, string fullIdentifier, string shortName, string lkgFile, params string[] sdksToResolve) { Contract.Requires(!string.IsNullOrEmpty(testFolder)); Contract.Requires(!string.IsNullOrEmpty(specFile)); Contract.Requires(sdksToResolve != null); // Sadly the frontend doesn't use the engine abstractions file api's so we have to materialize stuff on disk for now... // TODO: Fix this code once the frontend supports a proper virtual FileSystem. // TODO: Change the package semantics to implicit when we expose a way to evaluate a single value var testFileName = Path.GetFileName(specFile); var mainFileName = "testMain.bp"; var testMainFile = Path.Combine(testFolder, mainFileName); Directory.CreateDirectory(testFolder); File.WriteAllText(Path.Combine(testFolder, Names.ModuleConfigBm), I($@"module( {{ name: 'TestPackage', nameResolutionSemantics: NameResolutionSemantics.implicitProjectReferences, projects: [ f`{mainFileName}`, f`{testFileName}`, ], }});")); File.WriteAllText(testMainFile, I($@" export const testFolder = d`{Path.GetDirectoryName(specFile).Replace('\\', '/')}`; @@public export const main = {fullIdentifier}();")); File.Copy(specFile, Path.Combine(testFolder, testFileName)); // Create a fake package for Sdk.TestRunner so that you can safely test packages that have the tests embedded in them. var testRunnerFolder = Path.Combine(testFolder, "Sdk.TestRunner"); Directory.CreateDirectory(testRunnerFolder); File.WriteAllText(Path.Combine(testRunnerFolder, Names.ModuleConfigBm), I($"module({{\n\tname: 'Sdk.TestRunner',\n}});")); File.WriteAllText(Path.Combine(testRunnerFolder, "package" + Names.DotDscExtension), I($@" export interface TestArguments {{ testFiles: File[]; sdkFolders?: (Directory|StaticDirectory)[]; autoFixLkgs?: boolean; }} export interface TestResult {{ xmlResults: File; }} export function test(args: TestArguments): TestResult {{ Contract.fail(""Can't run a DScript UnitTest inside of a DScript UnitTest""); }}")); // Setup Context and configuration var frontEndContext = FrontEndContext.CreateInstanceForTesting(); var pipContext = new SchedulerContext(CancellationToken.None, frontEndContext.StringTable, frontEndContext.PathTable, frontEndContext.SymbolTable, frontEndContext.QualifierTable); var pathTable = frontEndContext.PathTable; var testFolderPath = AbsolutePath.Create(pathTable, testFolder); var configuration = CreateConfiguration(sdksToResolve.Union(new[] { testRunnerFolder }), pathTable, testFolderPath); var engineAbstraction = new TestEngineAbstraction(pathTable, frontEndContext.StringTable, testFolderPath, new PassThroughFileSystem(pathTable)); var frontEndStatistics = new FrontEndStatistics(); if (!CreateFactories( frontEndContext, engineAbstraction, frontEndStatistics, configuration, out var ambientTesting, out var moduleRegistry, out var frontEndFactory)) { return(false); } // Set the timeout to a large number to avoid useless performance collections in tests. using (var performanceCollector = new PerformanceCollector(TimeSpan.FromHours(1))) using (var frontEndHostController = new FrontEndHostController( frontEndFactory, new EvaluationScheduler(1), moduleRegistry, frontEndStatistics, m_tracingLogger, performanceCollector, collectMemoryAsSoonAsPossible: true)) { var frontEndController = (IFrontEndController)frontEndHostController; frontEndController.InitializeHost(frontEndContext, configuration); frontEndController.ParseConfig(configuration); // Populate the graph using (var pipTable = new PipTable( pipContext.PathTable, pipContext.SymbolTable, initialBufferSize: 16384, maxDegreeOfParallelism: 1, debug: true)) { var mountPathExpander = new MountPathExpander(pathTable); mountPathExpander.Add(pathTable, new SemanticPathInfo(PathAtom.Create(frontEndContext.StringTable, "testFolder"), testFolderPath, allowHashing: true, readable: true, writable: false)); mountPathExpander.Add(pathTable, new SemanticPathInfo(PathAtom.Create(frontEndContext.StringTable, "src"), testFolderPath.Combine(pathTable, "src"), allowHashing: true, readable: true, writable: true)); mountPathExpander.Add(pathTable, new SemanticPathInfo(PathAtom.Create(frontEndContext.StringTable, "out"), testFolderPath.Combine(pathTable, "out"), allowHashing: true, readable: true, writable: true)); mountPathExpander.Add(pathTable, new SemanticPathInfo(PathAtom.Create(frontEndContext.StringTable, "noRead"), testFolderPath.Combine(pathTable, "noRead"), allowHashing: true, readable: false, writable: true)); mountPathExpander.Add(pathTable, new SemanticPathInfo(PathAtom.Create(frontEndContext.StringTable, "temp"), engineAbstraction.Layout.TempDirectory, allowHashing: true, readable: true, writable: true)); mountPathExpander.Add(pathTable, new SemanticPathInfo(PathAtom.Create(frontEndContext.StringTable, "obj"), engineAbstraction.Layout.ObjectDirectory, allowHashing: true, readable: true, writable: true)); var graph = new PipGraph.Builder( pipTable, pipContext, m_pipLogger, frontEndContext.LoggingContext, configuration, mountPathExpander); using (var cacheLayer = new EngineCache( new InMemoryArtifactContentCache(), new InMemoryTwoPhaseFingerprintStore())) { var cache = Task.FromResult(Possible.Create(cacheLayer)); try { var evaluationFilter = new EvaluationFilter( pipContext.SymbolTable, pipContext.PathTable, new FullSymbol[0], new[] { AbsolutePath.Create(frontEndContext.PathTable, testMainFile), }, CollectionUtilities.EmptyArray <StringId>()); if (!frontEndController.PopulateGraph(cache, graph, engineAbstraction, evaluationFilter, configuration, configuration.Startup)) { HandleDiagnostics(); return(false); } } catch (AggregateException e) { var baseException = e.GetBaseException(); if (baseException is XunitException) { // If it is an XUnit assert, then unwrap the exception and throw that because XUnit other doesn't display the error nicely. ExceptionDispatchInfo.Capture(baseException).Throw(); } throw; } } if (!ValidatePips(frontEndContext, graph, testFolderPath, specFile, shortName, lkgFile, ambientTesting.DontValidatePipsEnabled)) { return(false); } } } HandleDiagnostics(); return(true); }
public PublicSurfaceTests() : base(pathTable: new PathTable(), preludeName: "Sdk.Prelude", nameResolutionSemantics: NameResolutionSemantics.ImplicitProjectReferences) { m_frontEndStatistics = new FrontEndStatistics(); }
/// <nodoc/> public DownloadFrontEnd() { m_logger = Script.Tracing.Logger.CreateLogger(preserveLogEvents: true); m_frontEndStatistics = new FrontEndStatistics(); m_evaluationStatistics = new EvaluationStatistics(); }
private static bool TryBuildPipGraphFragment( ICommandLineConfiguration commandLineConfig, PipGraphFragmentGeneratorConfiguration pipGraphFragmentGeneratorConfig, FrontEndContext frontEndContext, EngineContext engineContext, EvaluationFilter evaluationFilter) { Contract.Requires(frontEndContext != null); Contract.Requires(engineContext != null); Contract.Requires(commandLineConfig.Startup.ConfigFile.IsValid); Contract.Requires(evaluationFilter != null); var pathTable = engineContext.PathTable; var loggingContext = frontEndContext.LoggingContext; var mutableCommandlineConfig = CompleteCommandLineConfiguration(commandLineConfig); BuildXLEngine.ModifyConfigurationForCloudbuild(mutableCommandlineConfig, false, pathTable, loggingContext); BuildXLEngine.PopulateLoggingAndLayoutConfiguration(mutableCommandlineConfig, pathTable, bxlExeLocation: null); var statistics = new FrontEndStatistics(); var frontEndControllerFactory = FrontEndControllerFactory.Create( mode: FrontEndMode.NormalMode, loggingContext: loggingContext, configuration: mutableCommandlineConfig, collector: null, statistics: statistics); var controller = frontEndControllerFactory.Create(engineContext.PathTable, engineContext.SymbolTable); controller.InitializeHost(frontEndContext, mutableCommandlineConfig); FrontEndHostController frontEndHostController = (FrontEndHostController)controller; var config = controller.ParseConfig(mutableCommandlineConfig); if (config == null) { return(false); } using (var cache = Task.FromResult <Possible <EngineCache> >( new EngineCache( new InMemoryArtifactContentCache(), new EmptyTwoPhaseFingerprintStore()))) { var mountsTable = MountsTable.CreateAndRegister(loggingContext, engineContext, config, mutableCommandlineConfig.Startup.Properties); FrontEndEngineAbstraction frontEndEngineAbstraction = new FrontEndEngineImplementation( loggingContext, frontEndContext.PathTable, config, mutableCommandlineConfig.Startup, mountsTable, InputTracker.CreateDisabledTracker(loggingContext), null, null, () => FileContentTable.CreateStub(loggingContext), 5000, false, controller.RegisteredFrontEnds); var pipGraphBuilder = pipGraphFragmentGeneratorConfig.TopSort ? new PipGraphFragmentBuilderTopSort(engineContext, config, mountsTable.MountPathExpander) : new PipGraphFragmentBuilder(engineContext, config, mountsTable.MountPathExpander); if (!AddConfigurationMountsAndCompleteInitialization(config, loggingContext, mountsTable)) { return(false); } if (!mountsTable.PopulateModuleMounts(config.ModulePolicies.Values, out var moduleMountsTableMap)) { Contract.Assume(loggingContext.ErrorWasLogged, "An error should have been logged after MountTable.PopulateModuleMounts()"); return(false); } using (frontEndEngineAbstraction is IDisposable ? (IDisposable)frontEndEngineAbstraction : null) { if (!controller.PopulateGraph( cache: cache, graph: pipGraphBuilder, engineAbstraction: frontEndEngineAbstraction, evaluationFilter: evaluationFilter, configuration: config, startupConfiguration: mutableCommandlineConfig.Startup)) { // Error should have been reported already return(false); } if (!SerializeFragmentIfRequested(pipGraphFragmentGeneratorConfig, frontEndContext, pipGraphBuilder)) { // Error should have been reported already return(false); } } } return(true); }
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); }
public static bool TryBuildWorkspace( EnginePhases phase, FrontEndContext frontEndContext, PipExecutionContext engineContext, AbsolutePath configFile, EvaluationFilter evaluationFilter, EventHandler <WorkspaceProgressEventArgs> progressHandler, out Workspace workspace, out FrontEndHostController frontEndHostController, WorkspaceBuilderConfiguration configuration, FrontEndEngineAbstraction frontEndEngineAbstraction = null, bool collectMemoryAsSoonAsPossible = true) { Contract.Requires((phase & (EnginePhases.ParseWorkspace | EnginePhases.AnalyzeWorkspace)) != EnginePhases.None); Contract.Requires(frontEndContext != null); Contract.Requires(engineContext != null); Contract.Requires(configFile.IsValid); Contract.Requires(evaluationFilter != null); workspace = null; var pathTable = engineContext.PathTable; var loggingContext = frontEndContext.LoggingContext; var commandlineConfig = GetCommandLineConfiguration(configuration, phase, configFile); BuildXLEngine.PopulateLoggingAndLayoutConfiguration(commandlineConfig, pathTable, bxlExeLocation: null); var statistics = new FrontEndStatistics(progressHandler); var frontEndControllerFactory = FrontEndControllerFactory.Create( mode: FrontEndMode.NormalMode, loggingContext: loggingContext, configuration: commandlineConfig, collector: null, statistics: statistics, collectMemoryAsSoonAsPossible: collectMemoryAsSoonAsPossible); var controller = frontEndControllerFactory.Create(engineContext.PathTable, engineContext.SymbolTable); controller.InitializeHost(frontEndContext, commandlineConfig); frontEndHostController = controller as FrontEndHostController; // If there is an explicit engine abstraction, we set it if (frontEndEngineAbstraction != null) { frontEndHostController.SetState(frontEndEngineAbstraction, pipGraph: null, configuration: commandlineConfig); } var config = controller.ParseConfig(commandlineConfig); if (config == null) { frontEndHostController = null; return(false); } using (var cache = Task.FromResult <Possible <EngineCache> >( new EngineCache( new InMemoryArtifactContentCache( new SchedulerContext( CancellationToken.None, frontEndContext.StringTable, frontEndContext.PathTable, frontEndContext.SymbolTable, frontEndContext.QualifierTable)), // Note that we have an 'empty' store (no hits ever) rather than a normal in memory one. new EmptyTwoPhaseFingerprintStore()))) { // Attempt to build and/or analyze the workspace if (!controller.PopulateGraph( cache: cache, graph: null /* No need to create pips */, engineAbstraction: frontEndEngineAbstraction ?? new BasicFrontEndEngineAbstraction(frontEndContext.PathTable, frontEndContext.FileSystem, config), evaluationFilter: evaluationFilter, configuration: config, startupConfiguration: commandlineConfig.Startup)) { Contract.Assert(frontEndHostController != null); workspace = frontEndHostController.GetWorkspace(); // Error has been reported already return(false); } } Contract.Assert(frontEndHostController != null); // If workspace construction is successfull, 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( frontEndHostController.GetWorkspace(), 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); }