@@ -18,6 +18,7 @@ import '../base/project_migrator.dart';
1818import '../base/utils.dart' ;
1919import '../base/version.dart' ;
2020import '../build_info.dart' ;
21+ import '../build_system/build_trace.dart' ;
2122import '../cache.dart' ;
2223import '../darwin/darwin.dart' ;
2324import '../device.dart' ;
@@ -353,6 +354,26 @@ Future<XcodeBuildResult> buildXcodeProject({
353354 return XcodeBuildResult (success: true );
354355 }
355356
357+ final int buildStartMicros = DateTime .now ().microsecondsSinceEpoch;
358+ final BuildTracer ? tracer = buildInfo.traceFilePath != null
359+ ? BuildTracer ()
360+ : null ;
361+
362+ // Pass trace file path as an intermediate location for flutter assemble.
363+ // mac.dart will merge this into the final trace file.
364+ final String ? assembleTraceFilePath;
365+ if (buildInfo.traceFilePath != null ) {
366+ assembleTraceFilePath = globals.fs.path.join (
367+ globals.fs.currentDirectory.path,
368+ getBuildDirectory (),
369+ 'ios' ,
370+ 'flutter_assemble_trace.json' ,
371+ );
372+ buildCommands.add ('TRACE_FILE=$assembleTraceFilePath ' );
373+ } else {
374+ assembleTraceFilePath = null ;
375+ }
376+
356377 if (globals.logger.isVerbose) {
357378 // An environment variable to be passed to xcode_backend.sh determining
358379 // whether to echo back executed commands.
@@ -531,6 +552,16 @@ Future<XcodeBuildResult> buildXcodeProject({
531552 ]);
532553 }
533554
555+ final int preXcodeEndMicros = DateTime .now ().microsecondsSinceEpoch;
556+ tracer? .addCompleteEvent (
557+ name: 'pre-xcode setup' ,
558+ cat: 'flutter' ,
559+ tid: 1 ,
560+ startMicros: buildStartMicros,
561+ endMicros: preXcodeEndMicros,
562+ );
563+
564+ final int xcodeStartMicros = DateTime .now ().microsecondsSinceEpoch;
534565 final sw = Stopwatch ()..start ();
535566 initialBuildStatus = globals.logger.startProgress ('Running Xcode build...' );
536567
@@ -555,6 +586,43 @@ Future<XcodeBuildResult> buildXcodeProject({
555586 ),
556587 );
557588
589+ // Record Xcode span and merge assemble trace if tracing is enabled.
590+ if (tracer != null ) {
591+ final int xcodeEndMicros = DateTime .now ().microsecondsSinceEpoch;
592+ tracer.addCompleteEvent (
593+ name: 'xcode ${xcodeBuildActionToString (buildAction )}' ,
594+ cat: 'xcode' ,
595+ tid: 2 ,
596+ startMicros: xcodeStartMicros,
597+ endMicros: xcodeEndMicros,
598+ );
599+ // Merge the assemble trace file that flutter assemble wrote.
600+ if (assembleTraceFilePath != null ) {
601+ final File assembleTraceFile = globals.fs.file (assembleTraceFilePath);
602+ tracer.mergeEventsFromFile (assembleTraceFile);
603+ }
604+ tracer.addCompleteEvent (
605+ name: 'post-xcode processing' ,
606+ cat: 'flutter' ,
607+ tid: 1 ,
608+ startMicros: xcodeEndMicros,
609+ endMicros: DateTime .now ().microsecondsSinceEpoch,
610+ );
611+ tracer.addCompleteEvent (
612+ name: 'flutter build ios' ,
613+ cat: 'flutter' ,
614+ tid: 1 ,
615+ startMicros: buildStartMicros,
616+ endMicros: DateTime .now ().microsecondsSinceEpoch,
617+ );
618+ final File traceFile = globals.fs.file (buildInfo.traceFilePath);
619+ tracer.writeToFile (traceFile);
620+ globals.printStatus (
621+ 'Build trace written to ${buildInfo .traceFilePath }. '
622+ 'View at https://ui.perfetto.dev' ,
623+ );
624+ }
625+
558626 if (tempDir.existsSync ()) {
559627 // Display additional warning and error message from xcresult bundle.
560628 final Directory resultBundle = tempDir.childDirectory (_kResultBundlePath);
0 commit comments