public Args(string[] args) : base(args) { List <Option> analyzerOptions = new List <Option>(); string cachedGraphDirectory = null; // TODO: Embed HashType in XLG file and update analyzer to use that instead of setting HashType globally. ContentHashingUtilities.SetDefaultHashType(); foreach (Option opt in Options) { if (opt.Name.Equals("executionLog", StringComparison.OrdinalIgnoreCase) || opt.Name.Equals("xl", StringComparison.OrdinalIgnoreCase)) { if (string.IsNullOrEmpty(m_analysisInput.ExecutionLogPath)) { m_analysisInput.ExecutionLogPath = ParsePathOption(opt); } else { m_analysisInputOther.ExecutionLogPath = ParseSingletonPathOption(opt, m_analysisInputOther.ExecutionLogPath); } } else if (opt.Name.Equals("graphDirectory", StringComparison.OrdinalIgnoreCase) || opt.Name.Equals("gd", StringComparison.OrdinalIgnoreCase)) { cachedGraphDirectory = ParseSingletonPathOption(opt, cachedGraphDirectory); } else if (opt.Name.Equals("mode", StringComparison.OrdinalIgnoreCase) || opt.Name.Equals("m", StringComparison.OrdinalIgnoreCase)) { m_mode = ParseEnumOption <AnalysisMode>(opt); } else if (opt.Name.Equals("disableTelemetry")) { m_telemetryDisabled = true; } else if (opt.Name.Equals("disableWorkerEvents", StringComparison.OrdinalIgnoreCase)) { m_canHandleWorkerEvents = false; } else if (s_helpStrings.Any(s => opt.Name.Equals(s, StringComparison.OrdinalIgnoreCase))) { // If the analyzer was called with '/help' argument - print help and exit Help = true; WriteHelp(); return; } else { analyzerOptions.Add(opt); } } AnalyzerOptions = analyzerOptions; if (!m_mode.HasValue) { throw Error("Mode parameter is required"); } // Add required parameter errors here switch (m_mode.Value) { case AnalysisMode.ObservedAccess: { if (!analyzerOptions.Any(opt => opt.Name.Equals("o"))) { throw Error("When executing `ObservedAccess` mode, an `/o:PATH_TO_OUTPUT_FILE` parameter is required to store the generated output"); } break; } } // Only send telemetry if all arguments were valid TelemetryStartup(); switch (m_mode.Value) { case AnalysisMode.SpecClosure: var analyzer = InitializeSpecClosureAnalyzer(); analyzer.Analyze(); break; } if (string.IsNullOrEmpty(m_analysisInput.ExecutionLogPath) && string.IsNullOrEmpty(cachedGraphDirectory)) { // Try to find the last build log from the user if none was specied. var invocation = new global::BuildXL.Engine.Invocations().GetLastInvocation(LoggingContext); if (invocation == null || !Directory.Exists(invocation.Value.LogsFolder)) { throw Error("executionLog or graphDirectory parameter is required"); } Console.WriteLine("Using last build from: '{0}', you can use /executionLog or /graphDirectory arguments to explicitly choose a build", invocation.Value.LogsFolder); m_analysisInput.ExecutionLogPath = invocation.Value.LogsFolder; } if (m_mode.Value == AnalysisMode.LogCompare && string.IsNullOrEmpty(m_analysisInput.ExecutionLogPath)) { throw Error("Additional executionLog to compare parameter is required"); } // The fingerprint store based cache miss analyzer and the bxl invocation analyzer // only use graph information from the newer build, so skip loading the graph for the earlier build // TODO: To avoid large "||" statements, convert this to a list or enum or struct and check if the mode is "in" that data structure if (m_mode.Value != AnalysisMode.CacheMiss || m_mode.Value != AnalysisMode.BXLInvocationXLG) { if (!m_analysisInput.LoadCacheGraph(cachedGraphDirectory)) { throw Error($"Could not load cached graph from directory {cachedGraphDirectory}"); } } switch (m_mode.Value) { case AnalysisMode.FingerprintText: m_analyzer = InitializeFingerprintTextAnalyzer(); break; case AnalysisMode.ExportGraph: m_analyzer = InitializePipGraphExporter(); break; case AnalysisMode.DirMembership: m_analyzer = InitializeDirMembershipAnalyzer(); break; case AnalysisMode.Dev: m_analyzer = InitializeDevAnalyzer(); break; case AnalysisMode.DumpProcess: m_analyzer = InitializeDumpProcessAnalyzer(); break; case AnalysisMode.EventStats: m_analyzer = InitializeEventStatsAnalyzer(); break; case AnalysisMode.Simulate: m_analyzer = InitializeBuildSimulatorAnalyzer(m_analysisInput); break; case AnalysisMode.ExportDgml: m_analyzer = InitializeExportDgmlAnalyzer(); break; case AnalysisMode.CriticalPath: m_analyzer = InitializeCriticalPathAnalyzer(); break; case AnalysisMode.FileImpact: m_analyzer = InitializeFileImpactAnalyzer(); break; case AnalysisMode.FileConsumption: m_analyzer = InitializeFileConsumptionAnalyzer(); break; case AnalysisMode.Codex: m_analyzer = InitializeCodexAnalyzer(); break; case AnalysisMode.DumpPip: m_analyzer = InitializeDumpPipAnalyzer(); break; case AnalysisMode.CosineDumpPip: m_analyzer = InitializeCosineDumpPip(); break; case AnalysisMode.CosineJson: m_analyzer = InitializeCosineJsonExport(); break; case AnalysisMode.ProcessRunScript: m_analyzer = InitializeProcessRunScriptAnalyzer(); break; case AnalysisMode.ObservedInput: m_analyzer = InitializeObservedInputResult(); break; case AnalysisMode.ObservedInputSummary: m_analyzer = InitializeObservedInputSummaryResult(); break; case AnalysisMode.ToolEnumeration: m_analyzer = InitializeToolEnumerationAnalyzer(); break; case AnalysisMode.FailedPipInput: m_analyzer = InitializeFailedPipInputAnalyzer(); break; case AnalysisMode.FailedPipsDump: m_analyzer = InitializeFailedPipsDumpAnalyzer(); if (!string.IsNullOrEmpty(m_analysisInputOther.ExecutionLogPath)) { if (!m_analysisInputOther.LoadCacheGraph(null)) { throw Error("Could not load second cached graph"); } m_analyzerOther = ((FailedPipsDumpAnalyzer)m_analyzer).GetDiffAnalyzer(m_analysisInputOther); } break; case AnalysisMode.Whitelist: m_analyzer = InitializeWhitelistAnalyzer(); break; case AnalysisMode.IdeGenerator: m_analyzer = InitializeIdeGenerator(); break; case AnalysisMode.PipExecutionPerformance: m_analyzer = InitializePipExecutionPerformanceAnalyzer(); break; case AnalysisMode.ProcessDetouringStatus: m_analyzer = InitializeProcessDetouringStatusAnalyzer(); break; case AnalysisMode.ObservedAccess: m_analyzer = InitializeObservedAccessAnalyzer(); break; case AnalysisMode.CacheDump: m_analyzer = InitializeCacheDumpAnalyzer(m_analysisInput); break; case AnalysisMode.BuildStatus: m_analyzer = InitializeBuildStatus(m_analysisInput); break; case AnalysisMode.WinIdeDependency: m_analyzer = InitializeWinIdeDependencyAnalyzer(); break; case AnalysisMode.PerfSummary: m_analyzer = InitializePerfSummaryAnalyzer(); break; case AnalysisMode.LogCompare: m_analyzer = InitializeSummaryAnalyzer(m_analysisInput); if (!m_analysisInputOther.LoadCacheGraph(null)) { throw Error("Could not load second cached graph"); } m_analyzerOther = InitializeSummaryAnalyzer(m_analysisInputOther, true); break; case AnalysisMode.CacheMissLegacy: m_analyzer = InitializeCacheMissAnalyzer(m_analysisInput); if (!m_analysisInputOther.LoadCacheGraph(null)) { throw Error("Could not load second cached graph"); } m_analyzerOther = ((CacheMissAnalyzer)m_analyzer).GetDiffAnalyzer(m_analysisInputOther); break; case AnalysisMode.IncrementalSchedulingState: m_analyzer = InitializeIncrementalSchedulingStateAnalyzer(); break; case AnalysisMode.FileChangeTracker: m_analyzer = InitializeFileChangeTrackerAnalyzer(); break; case AnalysisMode.InputTracker: m_analyzer = InitializeInputTrackerAnalyzer(); break; case AnalysisMode.FilterLog: m_analyzer = InitializeFilterLogAnalyzer(); break; case AnalysisMode.PipFilter: m_analyzer = InitializePipFilterAnalyzer(); break; case AnalysisMode.CacheMiss: // This analyzer does not rely on the execution log if (!m_analysisInputOther.LoadCacheGraph(null)) { throw Error("Could not load second cached graph"); } m_analyzer = InitializeFingerprintStoreAnalyzer(m_analysisInput, m_analysisInputOther); break; case AnalysisMode.PipFingerprint: m_analyzer = InitializePipFingerprintAnalyzer(m_analysisInput); break; case AnalysisMode.RequiredDependencies: m_analyzer = InitializeRequiredDependencyAnalyzer(); break; case AnalysisMode.ScheduledInputsOutputs: m_analyzer = InitializeScheduledInputsOutputsAnalyzer(); break; #if FEATURE_VSTS_ARTIFACTSERVICES case AnalysisMode.CacheHitPredictor: m_analyzer = InitializeCacheHitPredictor(); break; #endif case AnalysisMode.DependencyAnalyzer: m_analyzer = InitializeDependencyAnalyzer(); break; case AnalysisMode.GraphDiffAnalyzer: if (!m_analysisInputOther.LoadCacheGraph(null)) { throw Error("Could not load second cached graph"); } m_analyzer = InitializeGraphDiffAnalyzer(); break; case AnalysisMode.DumpMounts: m_analyzer = InitializeDumpMountsAnalyzer(); break; case AnalysisMode.CopyFile: m_analyzer = InitializeCopyFilesAnalyzer(); break; case AnalysisMode.XlgToDb: m_analyzer = InitializeXLGToDBAnalyzer(); break; case AnalysisMode.BXLInvocationXLG: m_analyzer = InitializeBXLInvocationAnalyzer(); break; case AnalysisMode.EventStatsXldb: m_analyzer = InitializeEventStatsXldbAnalyzer(); break; case AnalysisMode.DumpPipXldb: m_analyzer = InitializeDumpPipXldbAnalyzer(); break; case AnalysisMode.DebugLogs: ConsoleListener.RegisterEventSource(ETWLogger.Log); ConsoleListener.RegisterEventSource(FrontEnd.Script.Debugger.ETWLogger.Log); m_analyzer = InitializeDebugLogsAnalyzer(); break; default: Contract.Assert(false, "Unhandled analysis mode"); break; } Contract.Assert(m_analyzer != null, "Analyzer must be set."); m_analyzer.LoggingContext = LoggingContext; m_analyzer.CanHandleWorkerEvents = m_canHandleWorkerEvents; if (m_analyzerOther != null) { m_analyzerOther.CanHandleWorkerEvents = m_canHandleWorkerEvents; } }