예제 #1
0
        private GraphReuseResult(PipGraph pipGraph, EngineSchedule engineSchedule, InputTracker.InputChanges inputChanges)
        {
            m_pipGraph       = pipGraph;
            m_engineSchedule = engineSchedule;
            InputChanges     = inputChanges;

            // Calling invariant method explicitely because this is the only way to check it at least once.
            Invariant();
        }
예제 #2
0
        /// <nodoc />
        public XlgDebuggerState(DebugLogsAnalyzer analyzer)
            : base(XlgThreadId)
        {
            Analyzer = analyzer;

            var logFile = Path.Combine(Path.GetDirectoryName(Analyzer.Input.ExecutionLogPath), "BuildXL.status.csv");

            StackTrace = new[]
            {
                new DisplayStackTraceEntry(file: logFile, line: 1, position: 1, functionName: "<main>", entry: null)
            };

            PipsByType = Enum
                         .GetValues(typeof(PipType))
                         .Cast <PipType>()
                         .Except(new[] { PipType.Max })
                         .Aggregate(new ObjectInfoBuilder(), (obi, pipType) => obi.Prop(pipType.ToString(), () => PipGraph.RetrievePipReferencesOfType(pipType).ToArray()))
                         .Build();

            PipsByStatus = Enum
                           .GetValues(typeof(PipExecutionLevel))
                           .Cast <PipExecutionLevel>()
                           .Select(level => level.ToString())
                           .Concat(new[] { ExeLevelNotCompleted })
                           .Aggregate(new ObjectInfoBuilder(), (obi, levelStr) => obi.Prop(levelStr, () => GetPipsForExecutionLevel(levelStr)))
                           .Build();

            RootObject = new ObjectInfoBuilder()
                         .Preview("Root")
                         .Prop("Pips", () => PipGraph.RetrieveAllPips())
                         .Prop("ProcessPips", () => PipGraph.RetrievePipReferencesOfType(PipType.Process))
                         .Prop("Files", () => PipGraph.AllFiles)
                         .Prop("Directories", () => PipGraph.AllSealDirectories)
                         .Prop("DirMembership", () => Analyzer.GetDirMembershipData())
                         //.Prop("CriticalPath",  () => new AnalyzeCriticalPath())
                         .Prop("GroupedBy", new ObjectInfoBuilder()
                               .Prop("Pips", new PipsScope())
                               .Prop("Files", () => GroupFiles(PipGraph.AllFiles))
                               .Prop("Directories", () => GroupDirs(PipGraph.AllSealDirectories))
                               .Build())
                         .Build();

            RootEnv = new Env(
                parent: null,
                resolver: (obj) =>
            {
                return(Renderer.GetObjectInfo(context: this, obj).SetValidator(obj => !Renderer.IsInvalid(obj)));
            },
                vars: LibraryFunctions.All.ToDictionary(f => '$' + f.Name, f => Result.Scalar(f)),
                current: RootObject);

            Evaluator = new Evaluator(
                new Env(parent: RootEnv, resolver: RootEnv.Resolver, current: RootEnv.Current),
                Analyzer.EnableEvalCaching,
                Analyzer.EnsureOrdering);
        }
예제 #3
0
        // Check whether a pip (which produced secondPipOutput) is reachable from another pip (which has to produce firstPipOutput)
        private void AssertReachability(List <Pip> processPips, PipGraph pipGraph, string firstPipOutput, string secondPipOutput)
        {
            var firstPip  = processPips.Find(p => p.PipId == FindPipIdThatProducedFile(pipGraph, firstPipOutput));
            var secondPip = processPips.Find(p => p.PipId == FindPipIdThatProducedFile(pipGraph, secondPipOutput));

            Assert.NotNull(firstPip);
            Assert.NotNull(secondPip);

            Assert.True(pipGraph.DataflowGraph.IsReachableFrom(firstPip.PipId.ToNodeId(), secondPip.PipId.ToNodeId(), true));
        }
예제 #4
0
        protected override void AssertPipGraphContent(PipGraph pipGraph, SimpleGraph file2file, StringTable stringTable)
        {
            AssertPipGraphCounts(pipGraph, new Dictionary <PipType, int>
            {
                [PipType.Process] = file2file.NodeCount,
            });
            var processPips = pipGraph.RetrievePipsOfType(PipType.Process).ToList();

            AssertEdges(pipGraph, file2file, processPips, stringTable);
        }
예제 #5
0
 /// <summary>
 /// Same behavior as <see cref="LoadOrReuse"/>, but the file envelopeId is ignored
 /// </summary>
 /// <remarks>
 /// Only available when the factory is constructed with analysis mode on
 /// </remarks>
 public IIncrementalSchedulingState LoadOrReuseIgnoringFileEnvelope(
     PipGraph pipGraph,
     IConfiguration configuration,
     ContentHash preserveOutputSalt,
     string incrementalSchedulingStatePath,
     SchedulerState schedulerState)
 {
     Contract.Assert(m_analysisMode);
     return(LoadOrReuseInternal(FileEnvelopeId.Invalid, pipGraph, configuration, preserveOutputSalt, incrementalSchedulingStatePath, schedulerState));
 }
예제 #6
0
        /// <nodoc />
        public XlgDebuggerState(DebugLogsAnalyzer analyzer)
            : base(XlgThreadId)
        {
            Analyzer = analyzer;

            var logFile = Path.Combine(Path.GetDirectoryName(Analyzer.Input.ExecutionLogPath), "BuildXL.log");

            StackTrace = new[]
            {
                new DisplayStackTraceEntry(file: logFile, line: 1, position: 1, functionName: "<main>", entry: null)
            };

            PipsByType = new ObjectInfo(Enum
                                        .GetValues(typeof(PipType))
                                        .Cast <PipType>()
                                        .Except(new[] { PipType.Max })
                                        .Select(pipType => new Property(pipType.ToString(), () => PipGraph.RetrievePipReferencesOfType(pipType).ToArray())));

            PipsByStatus = new ObjectInfo(Enum
                                          .GetValues(typeof(PipExecutionLevel))
                                          .Cast <PipExecutionLevel>()
                                          .Select(level => level.ToString())
                                          .Concat(new[] { ExeLevelNotCompleted })
                                          .Select(levelStr => new Property(levelStr, () => GetPipsForExecutionLevel(levelStr))));

            RootObject = new ObjectInfo(preview: "Root", properties: new[]
            {
                new Property("Pips", () => PipGraph.RetrieveAllPips()),
                new Property("Files", () => PipGraph.AllFiles),
                new Property("Directories", () => PipGraph.AllSealDirectories),
                //new Property("CriticalPath",  new AnalyzeCricialPath()),
                new Property("GroupedBy", new ObjectInfo(new[]
                {
                    new Property("Pips", new PipsScope()),
                    new Property("Files", () => GroupFiles(PipGraph.AllFiles)),
                    new Property("Directories", () => GroupDirs(PipGraph.AllSealDirectories))
                }))
            });

            RootEnv = new Env(
                parent: null,
                resolver: (obj) =>
            {
                var result = Renderer.GetObjectInfo(context: this, obj);
                return(new ObjectInfo(
                           result.Preview,
                           properties: result.Properties
                           .Select(p => new Property(p.Name, value: Renderer.IsInvalid(p.Value) ? new object[0] : p.Value))
                           .ToArray()));
            },
                vars: LibraryFunctions.All.ToDictionary(f => '$' + f.Name, f => Result.Scalar(f)),
                current: RootObject);

            Evaluator = new Evaluator(new Env(parent: RootEnv, resolver: RootEnv.Resolver, current: RootEnv.Current));
        }
예제 #7
0
        public Context(
            PipExecutionContext pipContext,
            PipGraph pipGraph,
            IReadonlyDirectedGraph scheduledGraph,
            AbsolutePath configFilePath,
            IIdeConfiguration ideConfig)
        {
            Contract.Requires(pipGraph != null);
            Contract.Requires(scheduledGraph != null);
            Contract.Requires(configFilePath.IsValid);
            Contract.Requires(ideConfig.SolutionRoot.IsValid);
            Contract.Requires(ideConfig.SolutionName.IsValid);
            Contract.Requires(ideConfig.IsEnabled);
            Contract.Requires(ideConfig.IsNewEnabled);

            PipGraph       = pipGraph;
            ScheduledGraph = scheduledGraph;
            StringTable    = pipContext.StringTable;
            PathTable      = pipContext.PathTable;
            SymbolTable    = pipContext.SymbolTable;
            QualifierTable = pipContext.QualifierTable;
            IdeConfig      = ideConfig;

            DotSettingsPathStr = ideConfig.DotSettingsFile.IsValid ? ideConfig.DotSettingsFile.ToString(PathTable) : null;
            ConfigFilePathStr  = configFilePath.ToString(PathTable);

            EnlistmentRoot    = configFilePath.GetParent(PathTable);
            EnlistmentRootStr = EnlistmentRoot.ToString(PathTable);

            SolutionRoot    = ideConfig.SolutionRoot;
            SolutionRootStr = SolutionRoot.ToString(PathTable);

            SolutionFilePathStr = IdeGenerator.GetSolutionPath(ideConfig, PathTable).ToString(PathTable);

            CanWriteToSrc = ideConfig.CanWriteToSrc ?? false;
            ProjectsRoot  = CanWriteToSrc
                    ? EnlistmentRoot
                    : SolutionRoot.Combine(PathTable, PathAtom.Create(PathTable.StringTable, "Projects"));

            ResxExtensionName      = PathAtom.Create(StringTable, ".resx");
            CscExeName             = PathAtom.Create(StringTable, "csc.exe");
            CscDllName             = PathAtom.Create(StringTable, "csc.dll");
            XunitConsoleDllName    = PathAtom.Create(StringTable, "xunit.console.dll");
            DotnetName             = PathAtom.Create(StringTable, "dotnet");
            ResgenExeName          = PathAtom.Create(StringTable, "ResGen.exe");
            ResourcesExtensionName = PathAtom.Create(StringTable, ".resources");
            CsExtensionName        = PathAtom.Create(StringTable, ".cs");
            DllExtensionName       = PathAtom.Create(StringTable, ".dll");
            ClExeName             = PathAtom.Create(StringTable, "cl.exe");
            LinkExeName           = PathAtom.Create(StringTable, "Link.exe");
            VsTestExeName         = PathAtom.Create(StringTable, "vstest.console.exe");
            AssemblyDeploymentTag = StringId.Create(StringTable, "assemblyDeployment");
            TestDeploymentTag     = StringId.Create(StringTable, "testDeployment");
        }
예제 #8
0
        /// <summary>
        /// Factory method for the case when pip graph can be reused for graph patching.
        /// A non-null pip graph must be provided; input changes may optionally be provided too.
        /// </summary>
        internal static GraphReuseResult CreateForPartialReuse(PipGraph pipGraph, InputTracker.InputChanges inputChanges)
        {
            Contract.Requires(pipGraph != null);
            Contract.Requires(inputChanges != null);
            Contract.Requires(inputChanges.ChangedPaths.Any());

            return(new GraphReuseResult(
                       pipGraph: pipGraph,
                       engineSchedule: null,
                       inputChanges: inputChanges));
        }
예제 #9
0
        /// <summary>
        /// Adds a process finished by <see cref="TryFinishProcessApplyingOSDefaults(ProcessBuilder, out ProcessOutputs, out Process)"/> to
        /// the pip graph and updates its process outputs with the pip id that the graph assigns to the added process it
        /// </summary>
        public bool TryAddFinishedProcessToGraph(Process pip, ProcessOutputs processOutputs)
        {
            if (PipGraph != null)
            {
                var success = PipGraph.AddProcess(pip, GetValuePipId());
                processOutputs.ProcessPipId = pip.PipId;
                return(success);
            }

            return(true);
        }
예제 #10
0
        /// <nodoc />
        public DirectoryArtifact ReserveSharedOpaqueDirectory(AbsolutePath directoryArtifactRoot)
        {
            if (PipGraph != null)
            {
                return(PipGraph.ReserveSharedOpaqueDirectory(directoryArtifactRoot));
            }

            // If the pip graph is not available (e.g. /phase:evaluate was passed)
            // then a directory artifact with seal id zero should suffice
            return(DirectoryArtifact.CreateWithZeroPartialSealId(directoryArtifactRoot));
        }
예제 #11
0
        /// <summary>
        /// Runs the scheduler using the instance member PipGraph and Configuration objects. This will also carry over
        /// any state from any previous run such as the cache
        /// </summary>
        public ScheduleRunResult RunScheduler(SchedulerTestHooks testHooks = null, SchedulerState schedulerState = null, RootFilter filter = null, TempCleaner tempCleaner = null)
        {
            if (m_graphWasModified || m_lastGraph == null)
            {
                m_lastGraph = PipGraphBuilder.Build();
                XAssert.IsNotNull(m_lastGraph, "Failed to build pip graph");
            }

            m_graphWasModified = false;
            return(RunSchedulerSpecific(m_lastGraph, testHooks, schedulerState, filter, tempCleaner));
        }
예제 #12
0
 /// <summary>
 /// Loads an existing instance of <see cref="IIncrementalSchedulingState"/> from a given file or reuse it from a given <see cref="SchedulerState"/>.
 /// </summary>
 public IIncrementalSchedulingState LoadOrReuse(
     FileEnvelopeId atomicSaveToken,
     PipGraph pipGraph,
     IConfiguration configuration,
     ContentHash preserveOutputSalt,
     string incrementalSchedulingStatePath,
     SchedulerState schedulerState)
 {
     Contract.Requires(atomicSaveToken.IsValid);
     return(LoadOrReuseInternal(atomicSaveToken, pipGraph, configuration, preserveOutputSalt, incrementalSchedulingStatePath, schedulerState));
 }
예제 #13
0
        /// <summary>
        /// Verifies that the file/directory output by a fragment exists in the resulting graph.
        /// </summary>
        /// <param name="graph">Resulting graph.</param>
        /// <param name="fragmentOrigin">Graph fragment where the output originates.</param>
        /// <param name="outputPath">Path to output file/directory.</param>
        private void VerifyProducerExists(PipGraph graph, TestPipGraphFragment fragmentOrigin, AbsolutePath outputPath)
        {
            AbsolutePath remappedOutputPath = RemapFragmentPath(fragmentOrigin, outputPath);
            var          pipId = graph.TryGetProducer(FileArtifact.CreateOutputFile(remappedOutputPath));

            if (!pipId.IsValid)
            {
                pipId = graph.TryGetProducer(DirectoryArtifact.CreateWithZeroPartialSealId(remappedOutputPath));
            }

            XAssert.IsTrue(pipId.IsValid, $"Producer of '{outputPath.ToString(fragmentOrigin.Context.PathTable)}' from fragment '{fragmentOrigin.ModuleName}' could not be found in the resulting graph");
        }
예제 #14
0
        // A convoluted way of finding a PipId knowing some output from the pip and assuming the outputs' filenames are unique
        private PipId FindPipIdThatProducedFile(PipGraph pipGraph, string filename)
        {
            foreach (var kvp in pipGraph.AllFilesAndProducers)
            {
                if (kvp.Key.Path.ToString(PathTable).Contains(filename))
                {
                    return(kvp.Value);
                }
            }

            return(PipId.Invalid);
        }
예제 #15
0
        protected override void AssertPipGraphContent(PipGraph pipGraph, SimpleGraph file2file, StringTable stringTable)
        {
            AssertPipGraphCounts(pipGraph, new Dictionary <PipType, int>
            {
                [PipType.Process] = file2file.NodeCount * 3, // service pip, service shutdown pip, and service finalize pip in each file
                [PipType.Ipc]     = file2file.NodeCount,     // one IPC pip per file
            });
            var ipcPips = pipGraph.RetrievePipsOfType(PipType.Ipc).ToList();

            AssertEdges(pipGraph, file2file, ipcPips, stringTable);
            AssertMonikerConsistencyForIpcPip(ipcPips.Cast <IpcPip>(), pipGraph);
        }
예제 #16
0
        public TestScheduler(
            PipGraph graph,
            TestPipQueue pipQueue,
            PipExecutionContext context,
            FileContentTable fileContentTable,
            EngineCache cache,
            IConfiguration configuration,
            FileAccessWhitelist fileAccessWhitelist,
            DirectoryMembershipFingerprinterRuleSet directoryMembershipFingerprinterRules = null,
            ITempCleaner tempCleaner                  = null,
            PipRuntimeTimeTable runningTimeTable      = null,
            JournalState journalState                 = null,
            PerformanceCollector performanceCollector = null,
            string fingerprintSalt = null,
            PreserveOutputsInfo?previousInputsSalt = null,
            IEnumerable <Pip> successfulPips       = null,
            IEnumerable <Pip> failedPips           = null,
            LoggingContext loggingContext          = null,
            IIpcProvider ipcProvider = null,
            DirectoryTranslator directoryTranslator = null,
            VmInitializer vmInitializer             = null,
            SchedulerTestHooks testHooks            = null) : base(graph, pipQueue, context, fileContentTable, cache,
                                                                   configuration, fileAccessWhitelist, loggingContext, null, directoryMembershipFingerprinterRules,
                                                                   tempCleaner, AsyncLazy <PipRuntimeTimeTable> .FromResult(runningTimeTable), performanceCollector, fingerprintSalt, previousInputsSalt,
                                                                   ipcProvider: ipcProvider,
                                                                   directoryTranslator: directoryTranslator,
                                                                   journalState: journalState,
                                                                   vmInitializer: vmInitializer,
                                                                   testHooks: testHooks)
        {
            m_testPipQueue = pipQueue;

            if (successfulPips != null)
            {
                foreach (var pip in successfulPips)
                {
                    Contract.Assume(pip.PipId.IsValid, "Override results must be added after the pip has been added to the scheduler");
                    m_overridePipResults.Add(pip.PipId, PipResultStatus.Succeeded);
                }
            }

            if (failedPips != null)
            {
                foreach (var pip in failedPips)
                {
                    Contract.Assume(pip.PipId.IsValid, "Override results must be added after the pip has been added to the scheduler");
                    m_overridePipResults.Add(pip.PipId, PipResultStatus.Failed);
                }
            }

            m_loggingContext = loggingContext;
        }
예제 #17
0
        /// <nodoc/>
        public bool TryAssertOutputExistenceInOpaqueDirectory(DirectoryArtifact outputDirectoryArtifact, AbsolutePath outputInOpaque, out FileArtifact fileArtifact)
        {
            Contract.Requires(outputDirectoryArtifact.IsValid);
            Contract.Requires(outputInOpaque.IsValid);

            if (PipGraph is null)
            {
                fileArtifact = FileArtifact.Invalid;
                return(false);
            }

            return(PipGraph.TryAssertOutputExistenceInOpaqueDirectory(outputDirectoryArtifact, outputInOpaque, out fileArtifact));
        }
예제 #18
0
 public ChooseWorkerCpu(
     LoggingContext loggingContext,
     IConfiguration config,
     IReadOnlyList <Worker> workers,
     IPipQueue pipQueue,
     PipGraph pipGraph,
     FileContentManager fileContentManager) : base(loggingContext, config, workers, pipQueue, DispatcherKind.ChooseWorkerCpu, config.Schedule.MaxChooseWorkerCpu)
 {
     m_pipTable = pipGraph.PipTable;
     m_executedProcessOutputs = new ContentTrackingSet(pipGraph);
     m_fileContentManager     = fileContentManager;
     m_pipSetupCostPool       = new ObjectPool <PipSetupCosts>(() => new PipSetupCosts(this), costs => costs, size: config.Schedule.MaxChooseWorkerCpu);
 }
예제 #19
0
        /// <summary>
        /// Class constructor
        /// </summary>
        public CachedGraph(PipGraph pipGraph, DirectedGraph dataflowGraph, PipExecutionContext context, MountPathExpander mountPathExpander)
        {
            Contract.Requires(pipGraph != null);
            Contract.Requires(dataflowGraph != null);
            Contract.Requires(context != null);
            Contract.Requires(mountPathExpander != null);

            DataflowGraph     = dataflowGraph;
            PipTable          = pipGraph.PipTable;
            MountPathExpander = mountPathExpander;
            Context           = context;
            PipGraph          = pipGraph;
        }
예제 #20
0
 public ChooseWorkerCpu(
     LoggingContext loggingContext,
     int maxParallelDegree,
     IReadOnlyList <Worker> workers,
     IPipQueue pipQueue,
     PipGraph pipGraph,
     FileContentManager fileContentManager) : base(loggingContext, workers, pipQueue, DispatcherKind.ChooseWorkerCpu, maxParallelDegree)
 {
     m_pipTable = pipGraph.PipTable;
     m_executedProcessOutputs = new ContentTrackingSet(pipGraph);
     m_fileContentManager     = fileContentManager;
     m_pipSetupCostPool       = new ObjectPool <PipSetupCosts>(() => new PipSetupCosts(this), costs => costs, size: maxParallelDegree);
 }
예제 #21
0
        internal static void AssertPipGraphCounts(PipGraph pipGraph, Dictionary <PipType, int> pipTypeCounts)
        {
            var pips = pipGraph.RetrieveScheduledPips().Where(p => NotMetaPip(p) && p.PipType != PipType.HashSourceFile).ToArray();

            XAssert.All(
                pipTypeCounts,
                pipTypeAndCount =>
            {
                AssertPipTypeCount(pips, pipTypeAndCount.Key, pipTypeAndCount.Value);
            });
            var expectedTotalNonMetaPips = pipTypeCounts.Sum(t => t.Value);

            XAssert.AreEqual(expectedTotalNonMetaPips, pips.Count(), "Expected total number non-meta pips didn't match");
        }
예제 #22
0
        public override void Prepare()
        {
            m_writer = new StreamWriter(OutputFilePath);

            SpecPath      = AbsolutePath.Create(PathTable, @"d:\dbs\el\o8\Build\ProductBuild\liblet_officewebserviceapi_droidx86_ship\build.dsc");
            DirectoryPath = AbsolutePath.Create(PathTable, @"d:\dbs\cx\o8\androidsdk.24.0.4");
            foreach (var producer in PipGraph.GetProducingPips(SpecPath))
            {
                m_writer.WriteLine(GetDescription(producer));
                m_writer.WriteLine();
            }

            // GetPathProducers(path);
        }
예제 #23
0
        private void GetPathProducers(AbsolutePath path)
        {
            Dictionary <AbsolutePath, DirectoryArtifact> directories = new Dictionary <AbsolutePath, DirectoryArtifact>();

            foreach (var directory in PipGraph.AllSealDirectories)
            {
                directories[directory.Path] = directory;
            }

            var latest = PipGraph.TryGetLatestFileArtifactForPath(path);

            if (!latest.IsValid)
            {
                m_writer.WriteLine("No declared file producers");
            }
            else
            {
                for (int i = 0; i <= latest.RewriteCount; i++)
                {
                    var producerId = PipGraph.TryGetProducer(new FileArtifact(path, i));
                    if (producerId.IsValid)
                    {
                        m_writer.WriteLine("File Producer: ({0})", i);
                        m_producers.Add(producerId);
                        m_writer.WriteLine(GetDescription(GetPip(producerId)));
                        m_writer.WriteLine();
                    }
                }
            }

            while (path.IsValid)
            {
                DirectoryArtifact containingDirectory;
                if (directories.TryGetValue(path, out containingDirectory))
                {
                    var directoryNode = PipGraph.GetSealedDirectoryNode(containingDirectory);
                    var sealDirectory = (SealDirectory)GetPip(directoryNode);
                    if (sealDirectory.Kind == SealDirectoryKind.Opaque)
                    {
                        m_writer.WriteLine("Directory Producer:");
                        m_producers.Add(PipGraph.GetProducer(containingDirectory));
                        m_writer.WriteLine(GetDescription(GetPip(PipGraph.GetProducer(containingDirectory))));
                        m_writer.WriteLine("Directory: " + GetDescription(sealDirectory));
                        m_writer.WriteLine();
                    }
                }

                path = path.GetParent(PathTable);
            }
        }
예제 #24
0
        /// <summary>
        /// Class constructor
        /// </summary>
        public CachedGraph(PipGraph pipGraph, IReadonlyDirectedGraph directedGraph, PipExecutionContext context, MountPathExpander mountPathExpander, EngineSerializer serializer = null)
        {
            Contract.Requires(pipGraph != null);
            Contract.Requires(directedGraph != null);
            Contract.Requires(context != null);
            Contract.Requires(mountPathExpander != null);

            DirectedGraph     = directedGraph;
            PipTable          = pipGraph.PipTable;
            MountPathExpander = mountPathExpander;
            Context           = context;
            PipGraph          = pipGraph;
            Serializer        = serializer;
        }
예제 #25
0
        /// <summary>
        /// Creates an instance of <see cref="TestPipGraphFragment"/>.
        /// </summary>
        public TestPipGraphFragment(LoggingContext loggingContext, string sourceRoot, string objectRoot, string redirectedRoot, string moduleName, bool useTopSort = false)
        {
            Contract.Requires(loggingContext != null);
            Contract.Requires(!string.IsNullOrEmpty(sourceRoot));
            Contract.Requires(!string.IsNullOrEmpty(objectRoot));
            Contract.Requires(!string.IsNullOrEmpty(moduleName));

            Context          = BuildXLContext.CreateInstanceForTesting();
            m_loggingContext = loggingContext;
            m_sourceRoot     = AbsolutePath.Create(Context.PathTable, sourceRoot);
            m_objectRoot     = AbsolutePath.Create(Context.PathTable, objectRoot);
            m_expander       = new MountPathExpander(Context.PathTable);

            var configuration = new ConfigurationImpl()
            {
                Schedule =
                {
                    UseFixedApiServerMoniker     = true,
                    ComputePipStaticFingerprints = true,
                }
            };

            m_useTopSort = useTopSort;
            PipGraph     = m_useTopSort
                ? new PipGraphFragmentBuilderTopSort(Context, configuration, m_expander)
                : new PipGraphFragmentBuilder(Context, configuration, m_expander);

            ModuleName = moduleName;
            var specFileName = moduleName + ".dsc";

            m_specPath = m_sourceRoot.Combine(Context.PathTable, specFileName);
            m_moduleId = ModuleId.Create(StringId.Create(Context.StringTable, moduleName));
            var modulePip = ModulePip.CreateForTesting(
                Context.StringTable,
                m_specPath,
                m_moduleId);

            PipGraph.AddModule(modulePip);
            PipGraph.AddSpecFile(new SpecFilePip(new FileArtifact(m_specPath), new LocationData(m_specPath, 0, 0), modulePip.Module));

            m_defaultConstructionHelper = PipConstructionHelper.CreateForTesting(
                Context,
                objectRoot: m_objectRoot,
                redirectedRoot: AbsolutePath.Create(Context.PathTable, redirectedRoot),
                pipGraph: PipGraph,
                moduleName: moduleName,
                specRelativePath: Path.Combine(m_sourceRoot.GetName(Context.PathTable).ToString(Context.StringTable), specFileName),
                specPath: m_specPath,
                symbol: moduleName + "_defaultValue");
        }
예제 #26
0
        private bool ProcessFilter(string filterText, FileStream stream, StreamWriter writer)
        {
            var parser = new FilterParser(CachedGraph.Context, CachedGraph.MountPathExpander.TryGetRootByMountName, filterText, canonicalize: true);

            if (!parser.TryParse(out var rootFilter, out var error))
            {
                Console.WriteLine(string.Format(CultureInfo.InvariantCulture,
                                                "Error at position {1} of command line pip filter {0}. {3} {2}",
                                                filterText,
                                                error.Position,
                                                error.FormatFilterPointingToPosition(filterText),
                                                error.Message));
                return(false);
            }

            var outputs = PipGraph.FilterOutputs(rootFilter);
            var pips    = new List <PipId>();

            if (PipGraph.FilterNodesToBuild(Events.StaticContext, rootFilter, out var nodes))
            {
                foreach (var node in nodes)
                {
                    pips.Add(node.ToPipId());
                }
            }

            writer.WriteLine(I($"Filter: {filterText}"));
            writer.WriteLine(I($"Pips: {pips.Count}"));
            Console.WriteLine(I($"Pips: {pips.Count}"));
            foreach (var pip in pips)
            {
                writer.WriteLine(GetDescription(GetPip(pip)));
            }

            writer.WriteLine();
            Console.WriteLine(I($"Outputs: {outputs.Count}"));
            writer.WriteLine(I($"Outputs: {outputs.Count}"));
            foreach (var output in outputs)
            {
                var kind = output.IsDirectory ? "D" : "F";
                writer.WriteLine(I($"{kind}: {output.Path.ToString(PathTable)} ({GetDescription(GetPip(PipGraph.GetProducer(output)))})"));
            }

            writer.WriteLine();
            writer.WriteLine();
            writer.Flush();
            stream.Flush();

            return(true);
        }
예제 #27
0
        private PipId GetValuePipId()
        {
            if (PipGraph != null)
            {
                if (!m_valuePip.PipId.IsValid)
                {
                    PipGraph.AddOutputValue(m_valuePip);
                }

                Contract.Assert(m_valuePip.PipId.IsValid);
            }

            return(m_valuePip.PipId);
        }
예제 #28
0
        private void TopSortInternal(List <Pip> pips, List <List <Pip> > sortedPipGroups)
        {
            var childrenLeftToVisit = new Dictionary <Pip, int>();

            sortedPipGroups.Add(new List <Pip>());
            int totalAdded = 0;

            foreach (var pip in pips)
            {
                childrenLeftToVisit[pip] = 0;
            }

            foreach (var pip in pips)
            {
                foreach (var dependent in (PipGraph.RetrievePipImmediateDependents(pip) ?? Enumerable.Empty <Pip>()))
                {
                    childrenLeftToVisit[dependent]++;
                }
            }

            foreach (var pip in pips)
            {
                if (childrenLeftToVisit[pip] == 0)
                {
                    totalAdded++;
                    sortedPipGroups[sortedPipGroups.Count - 1].Add(pip);
                }
            }

            int currentLevel = sortedPipGroups.Count - 1;

            while (totalAdded < pips.Count)
            {
                sortedPipGroups.Add(new List <Pip>());
                foreach (var pip in sortedPipGroups[currentLevel])
                {
                    foreach (var dependent in PipGraph.RetrievePipImmediateDependents(pip) ?? Enumerable.Empty <Pip>())
                    {
                        if (--childrenLeftToVisit[dependent] == 0)
                        {
                            totalAdded++;
                            sortedPipGroups[currentLevel + 1].Add(dependent);
                        }
                    }
                }

                currentLevel++;
            }
        }
예제 #29
0
        /// <nodoc/>
        public bool TryAssertOutputExistenceInOpaqueDirectory(DirectoryArtifact outputDirectoryArtifact, AbsolutePath outputInOpaque, out FileArtifact fileArtifact)
        {
            Contract.Requires(outputDirectoryArtifact.IsValid);
            Contract.Requires(outputInOpaque.IsValid);

            // A null pip graph is the case of, for example, /phase:evaluate. Since there is no real execution going on, let's pretend the asserted file exists
            if (PipGraph is null)
            {
                // Outputs in opaques always have rewrite count 1
                fileArtifact = FileArtifact.CreateOutputFile(outputInOpaque);
                return(true);
            }

            return(PipGraph.TryAssertOutputExistenceInOpaqueDirectory(outputDirectoryArtifact, outputInOpaque, out fileArtifact));
        }
예제 #30
0
 protected static void AssertEdges(PipGraph pipGraph, SimpleGraph file2file, List <Pip> pips, StringTable stringTable)
 {
     XAssert.All(
         file2file.Edges,
         edge =>
     {
         var srcPip  = FindPipByTag(pips, GetProcTag(edge.Src), stringTable);
         var destPip = FindPipByTag(pips, GetProcTag(edge.Dest), stringTable);
         var deps    = pipGraph.RetrievePipImmediateDependencies(srcPip).ToList();
         if (!deps.Contains(destPip))
         {
             XAssert.Fail($"Edge ({edge.Src})->({edge.Dest}) not found: expected an edge between {srcPip} <-- {destPip}; dependencies of Pip {srcPip} are: {XAssert.SetToString(deps)}");
         }
     });
 }