@@ -303,7 +303,7 @@ private VerbosityOptions GetDefaultVerbosity()
303303
304304 private ICommand GetTargetCommand ( Func < ProjectCollection , ProjectInstance > ? projectFactory )
305305 {
306- FacadeLogger ? logger = DetermineBinlogger ( RestoreArgs ) ;
306+ FacadeLogger ? logger = LoggerUtility . DetermineBinlogger ( RestoreArgs , "dotnet-run" ) ;
307307 var project = EvaluateProject ( ProjectFileFullPath , projectFactory , RestoreArgs , logger ) ;
308308 ValidatePreconditions ( project ) ;
309309 InvokeRunArgumentsTarget ( project , RestoreArgs , Verbosity , logger ) ;
@@ -383,143 +383,8 @@ static void InvokeRunArgumentsTarget(ProjectInstance project, string[] restoreAr
383383 throw new GracefulException ( LocalizableStrings . RunCommandEvaluationExceptionBuildFailed , ComputeRunArgumentsTarget ) ;
384384 }
385385 }
386-
387- static FacadeLogger ? DetermineBinlogger ( string [ ] restoreArgs )
388- {
389- List < BinaryLogger > binaryLoggers = new ( ) ;
390-
391- for ( int i = restoreArgs . Length - 1 ; i >= 0 ; i -- )
392- {
393- string blArg = restoreArgs [ i ] ;
394- if ( ! IsBinLogArgument ( blArg ) )
395- {
396- continue ;
397- }
398-
399- if ( blArg . Contains ( ':' ) )
400- {
401- // split and forward args
402- var split = blArg . Split ( ':' , 2 ) ;
403- var filename = split [ 1 ] ;
404- if ( filename . EndsWith ( ".binlog" ) )
405- {
406- filename = filename . Substring ( 0 , filename . Length - ".binlog" . Length ) ;
407- filename = filename + "-dotnet-run" + ".binlog" ;
408- }
409- binaryLoggers . Add ( new BinaryLogger { Parameters = filename } ) ;
410- }
411- else
412- {
413- // the same name will be used for the build and run-restore-exec steps, so we need to make sure they don't conflict
414- var filename = "msbuild-dotnet-run" + ".binlog" ;
415- binaryLoggers . Add ( new BinaryLogger { Parameters = filename } ) ;
416- }
417-
418- // Like in MSBuild, only the last binary logger is used.
419- break ;
420- }
421-
422- // this binaryLogger needs to be used for both evaluation and execution, so we need to only call it with a single IEventSource across
423- // both of those phases.
424- // We need a custom logger to handle this, because the MSBuild API for evaluation and execution calls logger Initialize and Shutdown methods, so will not allow us to do this.
425- if ( binaryLoggers . Count > 0 )
426- {
427- var fakeLogger = ConfigureDispatcher ( binaryLoggers ) ;
428-
429- return fakeLogger ;
430- }
431- return null ;
432- }
433-
434- static FacadeLogger ConfigureDispatcher ( List < BinaryLogger > binaryLoggers )
435- {
436- var dispatcher = new PersistentDispatcher ( binaryLoggers ) ;
437- return new FacadeLogger ( dispatcher ) ;
438- }
439386 }
440387
441- /// <summary>
442- /// This class acts as a wrapper around the BinaryLogger, to allow us to keep the BinaryLogger alive across multiple phases of the build.
443- /// The methods here are stubs so that the real binarylogger sees that we support these functionalities.
444- /// We need to ensure that the child logger is Initialized and Shutdown only once, so this fake event source
445- /// acts as a buffer. We'll provide this dispatcher to another fake logger, and that logger will
446- /// bind to this dispatcher to foward events from the actual build to the binary logger through this dispatcher.
447- /// </summary>
448- /// <param name="innerLogger"></param>
449- private class PersistentDispatcher : EventArgsDispatcher , IEventSource4
450- {
451- private List < BinaryLogger > innerLoggers ;
452-
453- public PersistentDispatcher ( List < BinaryLogger > innerLoggers )
454- {
455- this . innerLoggers = innerLoggers ;
456- foreach ( var logger in innerLoggers )
457- {
458- logger . Initialize ( this ) ;
459- }
460- }
461- public event TelemetryEventHandler TelemetryLogged { add { } remove { } }
462-
463- public void IncludeEvaluationMetaprojects ( ) { }
464- public void IncludeEvaluationProfiles ( ) { }
465- public void IncludeEvaluationPropertiesAndItems ( ) { }
466- public void IncludeTaskInputs ( ) { }
467-
468- public void Destroy ( )
469- {
470- foreach ( var innerLogger in innerLoggers )
471- {
472- innerLogger . Shutdown ( ) ;
473- }
474- }
475- }
476-
477- /// <summary>
478- /// This logger acts as a forwarder to the provided dispatcher, so that multiple different build engine operations
479- /// can be forwarded to the shared binary logger held by the dispatcher.
480- /// We opt into lots of data to ensure that we can forward all events to the binary logger.
481- /// </summary>
482- /// <param name="dispatcher"></param>
483- private class FacadeLogger ( PersistentDispatcher dispatcher ) : ILogger
484- {
485- public PersistentDispatcher Dispatcher => dispatcher ;
486-
487- public LoggerVerbosity Verbosity { get => LoggerVerbosity . Diagnostic ; set { } }
488- public string ? Parameters { get => "" ; set { } }
489-
490- public void Initialize ( IEventSource eventSource )
491- {
492- if ( eventSource is IEventSource3 eventSource3 )
493- {
494- eventSource3 . IncludeEvaluationMetaprojects ( ) ;
495- dispatcher . IncludeEvaluationMetaprojects ( ) ;
496-
497- eventSource3 . IncludeEvaluationProfiles ( ) ;
498- dispatcher . IncludeEvaluationProfiles ( ) ;
499-
500- eventSource3 . IncludeTaskInputs ( ) ;
501- dispatcher . IncludeTaskInputs ( ) ;
502- }
503-
504- eventSource . AnyEventRaised += ( sender , args ) => dispatcher . Dispatch ( args ) ;
505-
506- if ( eventSource is IEventSource4 eventSource4 )
507- {
508- eventSource4 . IncludeEvaluationPropertiesAndItems ( ) ;
509- dispatcher . IncludeEvaluationPropertiesAndItems ( ) ;
510- }
511- }
512-
513- public void ReallyShutdown ( )
514- {
515- dispatcher . Destroy ( ) ;
516- }
517-
518- // we don't do anything on shutdown, because we want to keep the dispatcher alive for the next phase
519- public void Shutdown ( )
520- {
521- }
522- }
523388
524389 static ILogger MakeTerminalLogger ( VerbosityOptions ? verbosity )
525390 {
0 commit comments