@@ -574,37 +574,14 @@ Future<void> diagnoseXcodeBuildFailure(XcodeBuildResult result, Usage flutterUsa
574
574
).send ();
575
575
}
576
576
577
- // Building for iOS Simulator, but the linked and embedded framework 'App.framework' was built for iOS.
578
- // or
579
- // Building for iOS, but the linked and embedded framework 'App.framework' was built for iOS Simulator.
580
- if ((result.stdout? .contains ('Building for iOS' ) ?? false )
581
- && (result.stdout? .contains ('but the linked and embedded framework' ) ?? false )
582
- && (result.stdout? .contains ('was built for iOS' ) ?? false )) {
583
- logger.printError ('' );
584
- logger.printError ('Your Xcode project requires migration. See https://flutter.dev/docs/development/ios-project-migration for details.' );
585
- logger.printError ('' );
586
- logger.printError ('You can temporarily work around this issue by running:' );
587
- logger.printError (' flutter clean' );
588
- return ;
589
- }
590
- if (xcodeBuildExecution != null
591
- && xcodeBuildExecution.environmentType == EnvironmentType .physical
592
- && (result.stdout? .contains ('BCEROR' ) ?? false )
593
- // May need updating if Xcode changes its outputs.
594
- && (result.stdout? .contains ("Xcode couldn't find a provisioning profile matching" ) ?? false )) {
595
- logger.printError (noProvisioningProfileInstruction, emphasis: true );
596
- return ;
597
- }
598
- // Make sure the user has specified one of:
599
- // * DEVELOPMENT_TEAM (automatic signing)
600
- // * PROVISIONING_PROFILE (manual signing)
601
- if (xcodeBuildExecution != null &&
602
- xcodeBuildExecution.environmentType == EnvironmentType .physical &&
603
- ! < String > ['DEVELOPMENT_TEAM' , 'PROVISIONING_PROFILE' ].any (
604
- xcodeBuildExecution.buildSettings.containsKey)) {
605
- logger.printError (noDevelopmentTeamInstruction, emphasis: true );
606
- return ;
577
+ // Handle errors.
578
+ final bool issueDetected = _handleIssues (result.xcResult, logger, xcodeBuildExecution);
579
+
580
+ if (! issueDetected && xcodeBuildExecution != null ) {
581
+ // Fallback to use stdout to detect and print issues.
582
+ _parseIssueInStdout (xcodeBuildExecution, logger, result);
607
583
}
584
+
608
585
if (xcodeBuildExecution != null
609
586
&& xcodeBuildExecution.environmentType == EnvironmentType .physical
610
587
&& (xcodeBuildExecution.buildSettings['PRODUCT_BUNDLE_IDENTIFIER' ]? .contains ('com.example' ) ?? false )) {
@@ -614,19 +591,6 @@ Future<void> diagnoseXcodeBuildFailure(XcodeBuildResult result, Usage flutterUsa
614
591
logger.printError (' open ios/Runner.xcworkspace' );
615
592
return ;
616
593
}
617
-
618
- // Handle xcresult errors.
619
- final XCResult ? xcResult = result.xcResult;
620
- if (xcResult == null ) {
621
- return ;
622
- }
623
- if (! xcResult.parseSuccess) {
624
- globals.printTrace ('XCResult parsing error: ${xcResult .parsingErrorMessage }' );
625
- return ;
626
- }
627
- for (final XCResultIssue issue in xcResult.issues) {
628
- _handleXCResultIssue (issue: issue, logger: logger);
629
- }
630
594
}
631
595
632
596
/// xcodebuild <buildaction> parameter (see man xcodebuild for details).
@@ -724,7 +688,7 @@ bool upgradePbxProjWithFlutterAssets(IosProject project, Logger logger) {
724
688
return true ;
725
689
}
726
690
727
- void _handleXCResultIssue ({required XCResultIssue issue, required Logger logger}) {
691
+ _XCResultIssueHandlingResult _handleXCResultIssue ({required XCResultIssue issue, required Logger logger}) {
728
692
// Issue summary from xcresult.
729
693
final StringBuffer issueSummaryBuffer = StringBuffer ();
730
694
issueSummaryBuffer.write (issue.subType ?? 'Unknown' );
@@ -744,16 +708,89 @@ void _handleXCResultIssue({required XCResultIssue issue, required Logger logger}
744
708
break ;
745
709
}
746
710
747
- // Add more custom output for flutter users.
748
- if (issue.message != null && issue.message! .toLowerCase ().contains ('provisioning profile' )) {
711
+ final String ? message = issue.message;
712
+ if (message == null ) {
713
+ return _XCResultIssueHandlingResult (requiresProvisioningProfile: false , hasProvisioningProfileIssue: false );
714
+ }
715
+
716
+ // Add more error messages for flutter users for some special errors.
717
+ if (message.toLowerCase ().contains ('requires a provisioning profile.' )) {
718
+ return _XCResultIssueHandlingResult (requiresProvisioningProfile: true , hasProvisioningProfileIssue: true );
719
+ } else if (message.toLowerCase ().contains ('provisioning profile' )) {
720
+ return _XCResultIssueHandlingResult (requiresProvisioningProfile: false , hasProvisioningProfileIssue: true );
721
+ }
722
+ return _XCResultIssueHandlingResult (requiresProvisioningProfile: false , hasProvisioningProfileIssue: false );
723
+ }
724
+
725
+ // Returns `true` if at least one issue is detected.
726
+ bool _handleIssues (XCResult ? xcResult, Logger logger, XcodeBuildExecution ? xcodeBuildExecution) {
727
+ bool requiresProvisioningProfile = false ;
728
+ bool hasProvisioningProfileIssue = false ;
729
+ bool issueDetected = false ;
730
+
731
+ if (xcResult != null && xcResult.parseSuccess) {
732
+ for (final XCResultIssue issue in xcResult.issues) {
733
+ final _XCResultIssueHandlingResult handlingResult = _handleXCResultIssue (issue: issue, logger: logger);
734
+ if (handlingResult.hasProvisioningProfileIssue) {
735
+ hasProvisioningProfileIssue = true ;
736
+ }
737
+ if (handlingResult.requiresProvisioningProfile) {
738
+ requiresProvisioningProfile = true ;
739
+ }
740
+ issueDetected = true ;
741
+ }
742
+ } else if (xcResult != null ) {
743
+ globals.printTrace ('XCResult parsing error: ${xcResult .parsingErrorMessage }' );
744
+ }
745
+
746
+ if (requiresProvisioningProfile) {
747
+ logger.printError (noProvisioningProfileInstruction, emphasis: true );
748
+ } else if (_missingDevelopmentTeam (xcodeBuildExecution)) {
749
+ issueDetected = true ;
750
+ logger.printError (noDevelopmentTeamInstruction, emphasis: true );
751
+ } else if (hasProvisioningProfileIssue) {
749
752
logger.printError ('' );
750
753
logger.printError ('It appears that there was a problem signing your application prior to installation on the device.' );
751
754
logger.printError ('' );
752
755
logger.printError ('Verify that the Bundle Identifier in your project is your signing id in Xcode' );
753
756
logger.printError (' open ios/Runner.xcworkspace' );
754
757
logger.printError ('' );
755
- logger.printError ("Also try selecting 'Product > Build' to fix the problem: " );
758
+ logger.printError ("Also try selecting 'Product > Build' to fix the problem. " );
756
759
}
760
+ return issueDetected;
761
+ }
762
+
763
+ // Return 'true' a missing development team issue is detected.
764
+ bool _missingDevelopmentTeam (XcodeBuildExecution ? xcodeBuildExecution) {
765
+ // Make sure the user has specified one of:
766
+ // * DEVELOPMENT_TEAM (automatic signing)
767
+ // * PROVISIONING_PROFILE (manual signing)
768
+ return xcodeBuildExecution != null && xcodeBuildExecution.environmentType == EnvironmentType .physical &&
769
+ ! < String > ['DEVELOPMENT_TEAM' , 'PROVISIONING_PROFILE' ].any (
770
+ xcodeBuildExecution.buildSettings.containsKey);
771
+ }
772
+ // Detects and handles errors from stdout.
773
+ //
774
+ // As detecting issues in stdout is not usually accurate, this should be used as a fallback when other issue detecting methods failed.
775
+ void _parseIssueInStdout (XcodeBuildExecution xcodeBuildExecution, Logger logger, XcodeBuildResult result) {
776
+ if (xcodeBuildExecution.environmentType == EnvironmentType .physical
777
+ // May need updating if Xcode changes its outputs.
778
+ && (result.stdout? .contains ('requires a provisioning profile. Select a provisioning profile in the Signing & Capabilities editor' ) ?? false )) {
779
+ logger.printError (noProvisioningProfileInstruction, emphasis: true );
780
+ return ;
781
+ }
782
+ }
783
+
784
+ // The result of [_handleXCResultIssue].
785
+ class _XCResultIssueHandlingResult {
786
+
787
+ _XCResultIssueHandlingResult ({required this .requiresProvisioningProfile, required this .hasProvisioningProfileIssue});
788
+
789
+ // An issue indicates that user didn't provide the provisioning profile.
790
+ final bool requiresProvisioningProfile;
791
+
792
+ // An issue indicates that there is a provisioning profile issue.
793
+ final bool hasProvisioningProfileIssue;
757
794
}
758
795
759
796
const String _kResultBundlePath = 'temporary_xcresult_bundle' ;
0 commit comments