Fix(ios): Remove arm64 exclusion to support Xcode 26 simulators (#177065)

With the release of Xcode 26, Apple has removed Rosetta support for the
iOS 26 simulator. This causes builds to fail on Apple Silicon Macs if
any plugin excludes the `arm64` simulator architecture.

This change introduces an early check during the pod install step to
detect and abort the build if it finds a plugin configured to exclude
the arm64 simulator architecture (via EXCLUDED_ARCHS or VALID_ARCHS).

## Testing

- Verified that the build is unsuccessful when `arm64` is excluded.
- If a plugin excludes arm64, an error is raised showing the plugin that
caused it

*List which issues are fixed by this PR. You must list at least one
issue. An issue is not required if the PR fixes something trivial like a
typo.*
Fixes #176188 

*If you had to change anything in the [flutter/tests] repo, include a
link to the migration guide as per the [breaking change policy].*

## Pre-launch Checklist

- [X] I read the [Contributor Guide] and followed the process outlined
there for submitting PRs.
- [X] I read the [Tree Hygiene] wiki page, which explains my
responsibilities.
- [X] I read and followed the [Flutter Style Guide], including [Features
we expect every widget to implement].
- [X] I signed the [CLA].
- [X] I listed at least one issue that this PR fixes in the description
above.
- [X] I updated/added relevant documentation (doc comments with `///`).
- [X] I added new tests to check the change I am making, or this PR is
[test-exempt].
- [ ] I followed the [breaking change policy] and added [Data Driven
Fixes] where supported.
- [X] All existing and new tests are passing.

If you need help, consider asking for advice on the #hackers-new channel
on [Discord].

**Note**: The Flutter team is currently trialing the use of [Gemini Code
Assist for
GitHub](https://developers.google.com/gemini-code-assist/docs/review-github-code).
Comments from the `gemini-code-assist` bot should not be taken as
authoritative feedback from the Flutter team. If you find its comments
useful you can update your code accordingly, but if you are unsure or
disagree with the feedback, please feel free to wait for a Flutter team
member's review for guidance on which automated comments should be
addressed.

<!-- Links -->
[Contributor Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview
[Tree Hygiene]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md
[test-exempt]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests
[Flutter Style Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md
[Features we expect every widget to implement]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement
[CLA]: https://cla.developers.google.com/
[flutter/tests]: https://github.com/flutter/tests
[breaking change policy]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes
[Discord]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md
[Data Driven Fixes]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
diff --git a/packages/flutter_tools/lib/src/ios/xcode_build_settings.dart b/packages/flutter_tools/lib/src/ios/xcode_build_settings.dart
index 6a54493..be4ddb3 100644
--- a/packages/flutter_tools/lib/src/ios/xcode_build_settings.dart
+++ b/packages/flutter_tools/lib/src/ios/xcode_build_settings.dart
@@ -5,6 +5,7 @@
 import '../artifacts.dart';
 import '../base/common.dart';
 import '../base/file_system.dart';
+import '../base/version.dart';
 import '../build_info.dart';
 import '../cache.dart';
 import '../flutter_manifest.dart';
@@ -232,10 +233,11 @@
     // If any plugins or their dependencies do not support arm64 simulators
     // (to run natively without Rosetta translation on an ARM Mac),
     // the app will fail to build unless it also excludes arm64 simulators.
-    var excludedSimulatorArchs = 'i386';
-    if (!(await project.ios.pluginsSupportArmSimulator())) {
-      excludedSimulatorArchs += ' arm64';
+    final Version? xcodeVersion = globals.xcode?.currentVersion;
+    if (xcodeVersion != null && xcodeVersion.major >= 26) {
+      await project.ios.checkForPluginsExcludingArmSimulator();
     }
+    const excludedSimulatorArchs = 'i386';
     xcodeBuildSettings.add(
       'EXCLUDED_ARCHS[sdk=${XcodeSdk.IPhoneSimulator.platformName}*]=$excludedSimulatorArchs',
     );
diff --git a/packages/flutter_tools/lib/src/xcode_project.dart b/packages/flutter_tools/lib/src/xcode_project.dart
index c9a3e02..11d47b9 100644
--- a/packages/flutter_tools/lib/src/xcode_project.dart
+++ b/packages/flutter_tools/lib/src/xcode_project.dart
@@ -25,6 +25,7 @@
 import 'macos/swift_package_manager.dart';
 import 'macos/xcode.dart';
 import 'platform_plugins.dart';
+import 'plugins.dart';
 import 'project.dart';
 import 'template.dart';
 
@@ -475,30 +476,77 @@
   /// True if the app project uses Swift.
   bool get isSwift => appDelegateSwift.existsSync();
 
-  /// Do all plugins support arm64 simulators to run natively on an ARM Mac?
-  Future<bool> pluginsSupportArmSimulator() async {
+  /// Prints a warning if any plugin(s) are excluding `arm64` architecture.
+  ///
+  /// Xcode 26 no longer allows you to build x86-only architecture for the simulator
+  Future<void> checkForPluginsExcludingArmSimulator() async {
     final Directory podXcodeProject = hostAppRoot
         .childDirectory('Pods')
         .childDirectory('Pods.xcodeproj');
     if (!podXcodeProject.existsSync()) {
-      // No plugins.
-      return true;
+      return;
     }
 
     final XcodeProjectInterpreter? xcodeProjectInterpreter = globals.xcodeProjectInterpreter;
     if (xcodeProjectInterpreter == null) {
-      // Xcode isn't installed, don't try to check.
-      return false;
+      return;
     }
     final String? buildSettings = await xcodeProjectInterpreter.pluginsBuildSettingsOutput(
       podXcodeProject,
     );
 
-    // See if any plugins or their dependencies exclude arm64 simulators
-    // as a valid architecture, usually because a binary is missing that slice.
-    // Example: EXCLUDED_ARCHS = arm64 i386
-    // NOT: EXCLUDED_ARCHS = i386
-    return buildSettings != null && !buildSettings.contains(RegExp('EXCLUDED_ARCHS.*arm64'));
+    if (buildSettings == null || buildSettings.isEmpty) {
+      return;
+    }
+
+    final List<Plugin> allPlugins = await findPlugins(parent);
+    final iosPluginTargetNames = <String>{
+      for (final Plugin plugin in allPlugins)
+        if (plugin.platforms.containsKey(IOSPlugin.kConfigKey)) plugin.name,
+    };
+    if (iosPluginTargetNames.isEmpty) {
+      return;
+    }
+
+    final targetHeader = RegExp(
+      r'^Build settings for action build and target "?([^":\r\n]+)"?:\s*$',
+    );
+
+    final pluginsExcludingArmArch = <String>{};
+    String? currentTarget;
+
+    for (final String eachLine in buildSettings.split('\n')) {
+      final String settingsLine = eachLine.trim();
+
+      final RegExpMatch? headerMatch = targetHeader.firstMatch(settingsLine);
+      if (headerMatch != null) {
+        currentTarget = headerMatch.group(1)!.trim();
+        continue;
+      }
+
+      if (currentTarget == null || !iosPluginTargetNames.contains(currentTarget)) {
+        continue;
+      }
+
+      if (!settingsLine.startsWith('EXCLUDED_ARCHS') || !settingsLine.contains('=')) {
+        continue;
+      }
+
+      final Iterable<String> tokens = settingsLine.split(' ');
+      if (tokens.contains('arm64')) {
+        pluginsExcludingArmArch.add(currentTarget);
+      }
+    }
+
+    if (pluginsExcludingArmArch.isNotEmpty) {
+      final String list = pluginsExcludingArmArch.map((String n) => '  - $n').join('\n');
+
+      globals.logger.printWarning(
+        'The following plugin(s) are excluding the arm64 architecture, which is a requirement for Xcode 26+:\n'
+        '$list\n'
+        'Consider installing the "Universal" Xcode or file an issue with the plugin(s) to support arm64.',
+      );
+    }
   }
 
   @override
diff --git a/packages/flutter_tools/test/general.shard/ios/xcodeproj_test.dart b/packages/flutter_tools/test/general.shard/ios/xcodeproj_test.dart
index 3c2c445..f2cdeac 100644
--- a/packages/flutter_tools/test/general.shard/ios/xcodeproj_test.dart
+++ b/packages/flutter_tools/test/general.shard/ios/xcodeproj_test.dart
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import 'dart:convert';
+
 import 'package:file/memory.dart';
 import 'package:flutter_tools/src/artifacts.dart';
 import 'package:flutter_tools/src/base/file_system.dart';
@@ -12,12 +14,14 @@
 import 'package:flutter_tools/src/build_info.dart';
 import 'package:flutter_tools/src/ios/xcode_build_settings.dart';
 import 'package:flutter_tools/src/ios/xcodeproj.dart';
+import 'package:flutter_tools/src/macos/xcode.dart';
 import 'package:flutter_tools/src/project.dart';
 import 'package:unified_analytics/unified_analytics.dart';
 
 import '../../src/common.dart';
 import '../../src/context.dart';
 import '../../src/fake_process_manager.dart';
+import '../../src/package_config.dart';
 
 const xcodebuild = '/usr/bin/xcodebuild';
 
@@ -1110,27 +1114,100 @@
       fs.file(xcodebuild).createSync(recursive: true);
     });
 
-    group('arm simulator', () {
+    group('arm simulator architecture check', () {
       late FakeProcessManager fakeProcessManager;
       late XcodeProjectInterpreter xcodeProjectInterpreter;
+      late Xcode xcode;
 
       setUp(() {
         fakeProcessManager = FakeProcessManager.empty();
-        xcodeProjectInterpreter = XcodeProjectInterpreter.test(processManager: fakeProcessManager);
+        xcodeProjectInterpreter = XcodeProjectInterpreter.test(
+          processManager: fakeProcessManager,
+          version: Version(26, 0, 0),
+        );
+        xcode = Xcode.test(
+          processManager: fakeProcessManager,
+          xcodeProjectInterpreter: xcodeProjectInterpreter,
+        );
       });
 
+      void createFakePlugins(
+        FlutterProject flutterProject,
+        FileSystem fileSystem,
+        List<String> pluginNames,
+      ) {
+        const pluginYamlTemplate = '''
+  flutter:
+    plugin:
+      platforms:
+        ios:
+          pluginClass: PLUGIN_CLASS
+        macos:
+          pluginClass: PLUGIN_CLASS
+  ''';
+
+        final Directory fakePubCache = fileSystem.systemTempDirectory.childDirectory(
+          'fake_pub_cache',
+        );
+
+        writePackageConfigFiles(
+          directory: flutterProject.directory,
+          mainLibName: 'my_app',
+          packages: <String, String>{
+            for (final String name in pluginNames) name: fakePubCache.childDirectory(name).path,
+          },
+        );
+
+        for (final name in pluginNames) {
+          final Directory pluginDirectory = fakePubCache.childDirectory(name);
+          pluginDirectory.childFile('pubspec.yaml')
+            ..createSync(recursive: true)
+            ..writeAsStringSync(pluginYamlTemplate.replaceAll('PLUGIN_CLASS', name));
+        }
+
+        final File graph = flutterProject.dartTool.childFile('package_graph.json')
+          ..createSync(recursive: true);
+
+        final packages = <Map<String, Object>>[
+          <String, Object>{
+            'name': 'my_app',
+            'dependencies': pluginNames,
+            'devDependencies': <String>[],
+          },
+          for (final String name in pluginNames)
+            <String, Object>{
+              'name': name,
+              'dependencies': <String>[],
+              'devDependencies': <String>[],
+            },
+        ];
+
+        graph.writeAsStringSync(
+          jsonEncode(<String, Object>{'configVersion': 1, 'packages': packages}),
+        );
+      }
+
       testUsingContext(
-        'does not exclude arm64 simulator when supported by all plugins',
+        'prints Warning when a plugin excludes arm64 on Xcode 26+',
         () async {
           const BuildInfo buildInfo = BuildInfo.debug;
-          final FlutterProject project = FlutterProject.fromDirectoryTest(
-            fs.directory('path/to/project'),
-          );
+
+          final Directory projectDir = fs.directory('path/to/project')..createSync(recursive: true);
+          projectDir.childFile('pubspec.yaml')
+            ..createSync(recursive: true)
+            ..writeAsStringSync('name: my_app\n');
+
+          final FlutterProject project = FlutterProject.fromDirectoryTest(projectDir);
+
           final Directory podXcodeProject =
               project.ios.hostAppRoot.childDirectory('Pods').childDirectory('Pods.xcodeproj')
                 ..createSync(recursive: true);
+          project.ios.podManifestLock.createSync(recursive: true);
 
-          final String buildDirectory = fileSystem.path.absolute('build', 'ios');
+          createFakePlugins(project, fs, <String>['bad_plugin', 'good_plugin']);
+
+          final String buildDirectory = fs.path.absolute('build', 'ios');
+
           fakeProcessManager.addCommands(<FakeCommand>[
             kWhichSysctlCommand,
             kARMCheckCommand,
@@ -1150,28 +1227,24 @@
                 'OBJROOT=$buildDirectory',
               ],
               stdout: '''
-Build settings for action build and target plugin1:
-    ENABLE_BITCODE = NO;
-    EXCLUDED_ARCHS = i386;
-    INFOPLIST_FILE = Runner/Info.plist;
-    UNRELATED_BUILD_SETTING = arm64;
+Build settings for action build and target bad_plugin:
+    EXCLUDED_ARCHS = i386 arm64
 
-Build settings for action build and target plugin2:
-    ENABLE_BITCODE = NO;
-    EXCLUDED_ARCHS = i386;
-    INFOPLIST_FILE = Runner/Info.plist;
-    UNRELATED_BUILD_SETTING = arm64;
-				''',
+Build settings for action build and target good_plugin:
+    EXCLUDED_ARCHS = i386
+''',
             ),
           ]);
+
           await updateGeneratedXcodeProperties(project: project, buildInfo: buildInfo);
 
-          final File config = fs.file('path/to/project/ios/Flutter/Generated.xcconfig');
           expect(
-            config.readAsStringSync(),
-            contains('EXCLUDED_ARCHS[sdk=iphonesimulator*]=i386\n'),
+            logger.warningText,
+            contains(
+              'The following plugin(s) are excluding the arm64 architecture, which is a requirement for Xcode 26+',
+            ),
           );
-          expect(config.readAsStringSync(), contains('EXCLUDED_ARCHS[sdk=iphoneos*]=armv7\n'));
+          expect(logger.warningText, contains('bad_plugin'));
           expect(fakeProcessManager, hasNoRemainingExpectations);
         },
         overrides: <Type, Generator>{
@@ -1180,73 +1253,29 @@
           FileSystem: () => fs,
           ProcessManager: () => fakeProcessManager,
           XcodeProjectInterpreter: () => xcodeProjectInterpreter,
+          Xcode: () => xcode,
+          Logger: () => logger,
         },
       );
-
       testUsingContext(
-        'excludes arm64 simulator when build setting fetch fails',
+        'succeeds when no plugins exclude arm64 on Xcode 26+',
         () async {
           const BuildInfo buildInfo = BuildInfo.debug;
-          final FlutterProject project = FlutterProject.fromDirectoryTest(
-            fs.directory('path/to/project'),
-          );
+
+          final Directory projectDir = fs.directory('path/to/project')..createSync(recursive: true);
+          projectDir.childFile('pubspec.yaml')
+            ..createSync(recursive: true)
+            ..writeAsStringSync('name: my_app\n');
+
+          final FlutterProject project = FlutterProject.fromDirectoryTest(projectDir);
+
           final Directory podXcodeProject =
               project.ios.hostAppRoot.childDirectory('Pods').childDirectory('Pods.xcodeproj')
                 ..createSync(recursive: true);
+          project.ios.podManifestLock.createSync(recursive: true);
+          createFakePlugins(project, fs, <String>['good_plugin']);
+          final String buildDirectory = fs.path.absolute('build', 'ios');
 
-          final String buildDirectory = fileSystem.path.absolute('build', 'ios');
-          fakeProcessManager.addCommands(<FakeCommand>[
-            kWhichSysctlCommand,
-            kARMCheckCommand,
-            FakeCommand(
-              command: <String>[
-                '/usr/bin/arch',
-                '-arm64e',
-                'xcrun',
-                'xcodebuild',
-                '-alltargets',
-                '-sdk',
-                'iphonesimulator',
-                '-project',
-                podXcodeProject.path,
-                '-showBuildSettings',
-                'BUILD_DIR=$buildDirectory',
-                'OBJROOT=$buildDirectory',
-              ],
-              exitCode: 1,
-            ),
-          ]);
-          await updateGeneratedXcodeProperties(project: project, buildInfo: buildInfo);
-
-          final File config = fs.file('path/to/project/ios/Flutter/Generated.xcconfig');
-          expect(
-            config.readAsStringSync(),
-            contains('EXCLUDED_ARCHS[sdk=iphonesimulator*]=i386 arm64\n'),
-          );
-          expect(config.readAsStringSync(), contains('EXCLUDED_ARCHS[sdk=iphoneos*]=armv7\n'));
-          expect(fakeProcessManager, hasNoRemainingExpectations);
-        },
-        overrides: <Type, Generator>{
-          Artifacts: () => localIosArtifacts,
-          Platform: () => macOS,
-          FileSystem: () => fs,
-          ProcessManager: () => fakeProcessManager,
-          XcodeProjectInterpreter: () => xcodeProjectInterpreter,
-        },
-      );
-
-      testUsingContext(
-        'excludes arm64 simulator when unsupported by plugins',
-        () async {
-          const BuildInfo buildInfo = BuildInfo.debug;
-          final FlutterProject project = FlutterProject.fromDirectoryTest(
-            fs.directory('path/to/project'),
-          );
-          final Directory podXcodeProject =
-              project.ios.hostAppRoot.childDirectory('Pods').childDirectory('Pods.xcodeproj')
-                ..createSync(recursive: true);
-
-          final String buildDirectory = fileSystem.path.absolute('build', 'ios');
           fakeProcessManager.addCommands(<FakeCommand>[
             kWhichSysctlCommand,
             kARMCheckCommand,
@@ -1266,28 +1295,17 @@
                 'OBJROOT=$buildDirectory',
               ],
               stdout: '''
-Build settings for action build and target plugin1:
-    ENABLE_BITCODE = NO;
-    EXCLUDED_ARCHS = i386;
-    INFOPLIST_FILE = Runner/Info.plist;
-    UNRELATED_BUILD_SETTING = arm64;
-
-Build settings for action build and target plugin2:
-    ENABLE_BITCODE = NO;
-    EXCLUDED_ARCHS = i386 arm64;
-    INFOPLIST_FILE = Runner/Info.plist;
-    UNRELATED_BUILD_SETTING = arm64;
-				''',
+Build settings for action build and target good_plugin:
+    EXCLUDED_ARCHS = i386
+''',
             ),
           ]);
+
           await updateGeneratedXcodeProperties(project: project, buildInfo: buildInfo);
 
           final File config = fs.file('path/to/project/ios/Flutter/Generated.xcconfig');
-          expect(
-            config.readAsStringSync(),
-            contains('EXCLUDED_ARCHS[sdk=iphonesimulator*]=i386 arm64\n'),
-          );
-          expect(config.readAsStringSync(), contains('EXCLUDED_ARCHS[sdk=iphoneos*]=armv7\n'));
+          expect(config.readAsStringSync(), contains('EXCLUDED_ARCHS[sdk=iphonesimulator*]=i386'));
+          expect(config.readAsStringSync(), contains('EXCLUDED_ARCHS[sdk=iphoneos*]=armv7'));
           expect(fakeProcessManager, hasNoRemainingExpectations);
         },
         overrides: <Type, Generator>{
@@ -1296,6 +1314,242 @@
           FileSystem: () => fs,
           ProcessManager: () => fakeProcessManager,
           XcodeProjectInterpreter: () => xcodeProjectInterpreter,
+          Xcode: () => xcode,
+        },
+      );
+
+      testUsingContext(
+        'does not warn when EXCLUDED_ARCHS contains arm64e (not arm64)',
+        () async {
+          const BuildInfo buildInfo = BuildInfo.debug;
+
+          final Directory projectDir = fs.directory('path/to/project')..createSync(recursive: true);
+          projectDir.childFile('pubspec.yaml')
+            ..createSync(recursive: true)
+            ..writeAsStringSync('name: my_app\n');
+
+          final FlutterProject project = FlutterProject.fromDirectoryTest(projectDir);
+
+          final Directory podXcodeProject =
+              project.ios.hostAppRoot.childDirectory('Pods').childDirectory('Pods.xcodeproj')
+                ..createSync(recursive: true);
+          project.ios.podManifestLock.createSync(recursive: true);
+
+          createFakePlugins(project, fs, <String>['good_plugin']);
+
+          final String buildDirectory = fs.path.absolute('build', 'ios');
+          final testLogger = BufferLogger.test();
+
+          fakeProcessManager.addCommands(<FakeCommand>[
+            kWhichSysctlCommand,
+            kARMCheckCommand,
+            FakeCommand(
+              command: <String>[
+                '/usr/bin/arch',
+                '-arm64e',
+                'xcrun',
+                'xcodebuild',
+                '-alltargets',
+                '-sdk',
+                'iphonesimulator',
+                '-project',
+                podXcodeProject.path,
+                '-showBuildSettings',
+                'BUILD_DIR=$buildDirectory',
+                'OBJROOT=$buildDirectory',
+              ],
+              stdout: '''
+Build settings for action build and target good_plugin:
+    EXCLUDED_ARCHS[sdk=iphonesimulator*] = i386 arm64e
+''',
+            ),
+          ]);
+
+          await updateGeneratedXcodeProperties(project: project, buildInfo: buildInfo);
+
+          expect(testLogger.warningText, isEmpty);
+          expect(fakeProcessManager, hasNoRemainingExpectations);
+        },
+        overrides: <Type, Generator>{
+          Artifacts: () => localIosArtifacts,
+          Platform: () => macOS,
+          FileSystem: () => fs,
+          ProcessManager: () => fakeProcessManager,
+          XcodeProjectInterpreter: () => xcodeProjectInterpreter,
+          Xcode: () => xcode,
+          Logger: () => BufferLogger.test(),
+        },
+      );
+
+      testUsingContext(
+        'warns when bracketed EXCLUDED_ARCHS contains arm64',
+        () async {
+          const BuildInfo buildInfo = BuildInfo.debug;
+
+          final Directory projectDir = fs.directory('path/to/project')..createSync(recursive: true);
+          projectDir.childFile('pubspec.yaml')
+            ..createSync(recursive: true)
+            ..writeAsStringSync('name: my_app\n');
+
+          final FlutterProject project = FlutterProject.fromDirectoryTest(projectDir);
+
+          final Directory podXcodeProject =
+              project.ios.hostAppRoot.childDirectory('Pods').childDirectory('Pods.xcodeproj')
+                ..createSync(recursive: true);
+          project.ios.podManifestLock.createSync(recursive: true);
+
+          createFakePlugins(project, fs, <String>['bad_plugin']);
+
+          final String buildDirectory = fs.path.absolute('build', 'ios');
+
+          fakeProcessManager.addCommands(<FakeCommand>[
+            kWhichSysctlCommand,
+            kARMCheckCommand,
+            FakeCommand(
+              command: <String>[
+                '/usr/bin/arch',
+                '-arm64e',
+                'xcrun',
+                'xcodebuild',
+                '-alltargets',
+                '-sdk',
+                'iphonesimulator',
+                '-project',
+                podXcodeProject.path,
+                '-showBuildSettings',
+                'BUILD_DIR=$buildDirectory',
+                'OBJROOT=$buildDirectory',
+              ],
+              stdout: '''
+Build settings for action build and target bad_plugin:
+    EXCLUDED_ARCHS[sdk=iphonesimulator*] = i386 arm64
+''',
+            ),
+          ]);
+
+          await updateGeneratedXcodeProperties(project: project, buildInfo: buildInfo);
+
+          expect(
+            logger.warningText,
+            contains(
+              'The following plugin(s) are excluding the arm64 architecture, which is a requirement for Xcode 26+',
+            ),
+          );
+          expect(logger.warningText, contains('bad_plugin'));
+          expect(fakeProcessManager, hasNoRemainingExpectations);
+        },
+        overrides: <Type, Generator>{
+          Artifacts: () => localIosArtifacts,
+          Platform: () => macOS,
+          FileSystem: () => fs,
+          ProcessManager: () => fakeProcessManager,
+          XcodeProjectInterpreter: () => xcodeProjectInterpreter,
+          Xcode: () => xcode,
+          Logger: () => logger,
+        },
+      );
+
+      testUsingContext(
+        'ignores non-plugin targets that exclude arm64',
+        () async {
+          const BuildInfo buildInfo = BuildInfo.debug;
+
+          final Directory projectDir = fs.directory('path/to/project')..createSync(recursive: true);
+          projectDir.childFile('pubspec.yaml')
+            ..createSync(recursive: true)
+            ..writeAsStringSync('name: my_app\n');
+
+          final FlutterProject project = FlutterProject.fromDirectoryTest(projectDir);
+
+          final Directory podXcodeProject =
+              project.ios.hostAppRoot.childDirectory('Pods').childDirectory('Pods.xcodeproj')
+                ..createSync(recursive: true);
+          project.ios.podManifestLock.createSync(recursive: true);
+
+          createFakePlugins(project, fs, <String>['good_plugin']);
+
+          final String buildDirectory = fs.path.absolute('build', 'ios');
+          final testLogger = BufferLogger.test();
+
+          fakeProcessManager.addCommands(<FakeCommand>[
+            kWhichSysctlCommand,
+            kARMCheckCommand,
+            FakeCommand(
+              command: <String>[
+                '/usr/bin/arch',
+                '-arm64e',
+                'xcrun',
+                'xcodebuild',
+                '-alltargets',
+                '-sdk',
+                'iphonesimulator',
+                '-project',
+                podXcodeProject.path,
+                '-showBuildSettings',
+                'BUILD_DIR=$buildDirectory',
+                'OBJROOT=$buildDirectory',
+              ],
+              stdout: '''
+Build settings for action build and target SomeNonPluginTarget:
+    EXCLUDED_ARCHS = arm64
+
+Build settings for action build and target good_plugin:
+    EXCLUDED_ARCHS = i386
+''',
+            ),
+          ]);
+
+          await updateGeneratedXcodeProperties(project: project, buildInfo: buildInfo);
+
+          expect(testLogger.warningText, isEmpty);
+          expect(fakeProcessManager, hasNoRemainingExpectations);
+        },
+        overrides: <Type, Generator>{
+          Artifacts: () => localIosArtifacts,
+          Platform: () => macOS,
+          FileSystem: () => fs,
+          ProcessManager: () => fakeProcessManager,
+          XcodeProjectInterpreter: () => xcodeProjectInterpreter,
+          Xcode: () => xcode,
+          Logger: () => BufferLogger.test(),
+        },
+      );
+
+      testUsingContext(
+        'succeeds and skips check on Xcode 16 even if a plugin excludes arm64',
+        () async {
+          xcodeProjectInterpreter = XcodeProjectInterpreter.test(
+            processManager: fakeProcessManager,
+            version: Version(16, 0, 0),
+          );
+          xcode = Xcode.test(
+            processManager: fakeProcessManager,
+            xcodeProjectInterpreter: xcodeProjectInterpreter,
+          );
+
+          const BuildInfo buildInfo = BuildInfo.debug;
+          final FlutterProject project = FlutterProject.fromDirectoryTest(
+            fs.directory('path/to/project'),
+          );
+          project.ios.hostAppRoot
+              .childDirectory('Pods')
+              .childDirectory('Pods.xcodeproj')
+              .createSync(recursive: true);
+
+          await updateGeneratedXcodeProperties(project: project, buildInfo: buildInfo);
+
+          final File config = fs.file('path/to/project/ios/Flutter/Generated.xcconfig');
+          expect(config.readAsStringSync(), contains('EXCLUDED_ARCHS[sdk=iphonesimulator*]=i386'));
+          expect(config.readAsStringSync(), contains('EXCLUDED_ARCHS[sdk=iphoneos*]=armv7'));
+          expect(fakeProcessManager, hasNoRemainingExpectations);
+        },
+        overrides: <Type, Generator>{
+          Artifacts: () => localIosArtifacts,
+          Platform: () => macOS,
+          FileSystem: () => fs,
+          ProcessManager: () => fakeProcessManager,
+          XcodeProjectInterpreter: () => xcodeProjectInterpreter,
+          Xcode: () => xcode,
         },
       );
     });
@@ -1801,6 +2055,21 @@
     });
 
     group('CoreDevice', () {
+      late FakeProcessManager fakeProcessManager;
+      late XcodeProjectInterpreter xcodeProjectInterpreter;
+      late Xcode xcode;
+
+      setUp(() {
+        fakeProcessManager = FakeProcessManager.empty();
+        xcodeProjectInterpreter = XcodeProjectInterpreter.test(
+          processManager: fakeProcessManager,
+          version: Version(26, 0, 0),
+        );
+        xcode = Xcode.test(
+          processManager: fakeProcessManager,
+          xcodeProjectInterpreter: xcodeProjectInterpreter,
+        );
+      });
       testUsingContext(
         'sets CONFIGURATION_BUILD_DIR when configurationBuildDir is set',
         () async {
@@ -1825,8 +2094,9 @@
           Artifacts: () => localIosArtifacts,
           // Platform: () => macOS,
           FileSystem: () => fs,
-          ProcessManager: () => FakeProcessManager.any(),
+          ProcessManager: () => fakeProcessManager,
           XcodeProjectInterpreter: () => xcodeProjectInterpreter,
+          Xcode: () => xcode,
         },
       );
 
@@ -1849,8 +2119,9 @@
           Artifacts: () => localIosArtifacts,
           Platform: () => macOS,
           FileSystem: () => fs,
-          ProcessManager: () => FakeProcessManager.any(),
+          ProcessManager: () => fakeProcessManager,
           XcodeProjectInterpreter: () => xcodeProjectInterpreter,
+          Xcode: () => xcode,
         },
       );
     });