iOS/Flutter: Only Xcode16 Can Do (问题收集)

7,834 阅读11分钟

前言

中秋节过后,电脑收到了 macOS Sequoia 更新,Xcode 也来到 16,支持 iOS 18 开发。

cd426517f6ae2764b12026d0a4466900.png

Flutter 相关问题

我特意看了下 flutter 相关的问题

截屏2024-09-19 17.03.58.png

没有忍住笑,还有用 2.x.x 版本的同学。前 2 个日志都没有提供,然后最后 2 个已经关闭。

截屏2024-09-19 17.03.23.png

都是 beta 通道工具问题。

截屏2024-09-19 17.15.46.png

貌似没有能阻止我更新的问题。

iOS 18 启动

尽管知道肯定有坑,大家都说狗住狗住,但是还是义无反顾的按下了更新键。

fe5e0e18ed89ddda629803c3abfcc81a.png

f63f84451001ed9c43b69322c0dfccf3.png

iOS 18 启动

iOS

terminate_handler

使用到 terminate_handler 的代码编译会报错如下:

image.png

Update SentryCrashMonitor_CPPException.cpp to include exception by Brett-Best · Pull Request #4051 · getsentry/sentry-cocoa (github.com)

解决方案是添加引用 #include <exception>

Undefined symbols: __mh_execute_header

如果你的代码里面用到 _mh_execute_header,你会得到以下错误:

Undefined symbols for architecture x86_64:

  "__mh_execute_header", referenced from:

Linker changes in Xcode 16 / macOS… | Apple Developer Forums

已知问题:某些大型或复杂项目在扫描其二进制文件中的特定 Mach-O 段时,可能会构建或运行失败。(123416939)

解决方法: 尝试将构建设置中的 ENABLE_DEBUG_DYLIB 设为 NO。此操作将禁用用于新预览执行模式的调试 dylib。将其设为 NO 后,仍可以在 Xcode 16 Seed 1 中使用旧的执行模式进行预览,但该模式的支持将在未来的版本中被移除。

IMG_20240919_153229.png

AddSubview maskView Crash

如果在自定义的 UIView 里面定义了一个叫 maskView 的属性,并尝试将它添加为 subview 的时候,会得到以下报错:

Terminating app due to uncaught exception 'NSInternalInconsistencyException', 
reason: 'Set `maskView` (<UIView: 0x7ff565577e60; frame = (0 0; 0 0); layer = <CALayer: 0x600003a63a20>>) to `nil` before adding it as a subview of <XXXView: 0x7ff565541770; 
frame = (0 0; 0 0); clipsToBounds = YES; layer = <CALayer: 0x600003a63a40>>'

xcode16 AddSubview crash · Issue #1557 · Tencent/QMUI_iOS (github.com)

解决方案是将自定义的 UIView里面的这个 maskView 属性名字修改为其他名字

UIView *maskView; 改成 UIView *maskView1;

pod init failed

2238294263556杨DL同学 同学提供。

Xcode16 创建一个新项目, pod init 失败。

pod init failed in Xcode 16 · Issue #12583 · CocoaPods/CocoaPods (github.com)

解决方案:

  • 右键项目根文件夹,转换为group(Convert to Group)

image.png

  • 右键点击projectname.xcodeproj文件,并选择“显示包内容”
    你会看到project.pbxproj文件,可以用文本编辑器打开它

在这个文件中,删除以下行:

minimizedProjectReferenceProxies = 1; 
preferredProjectObjectVersion = 77;

同时,更新版本信息,将 objectVersion = 77; 改成 objectVersion = 56;

Flutter

firebase

胶带zeqinjie 同学提供。

集成 firebase 报错如下:

    Failed to build iOS app  
    Lexical or Preprocessor Issue (Xcode): Include of non-modular header inside framework module 'firebase_messaging.FLTFirebaseMessagingPlugin': '/Users/[path]/[App Folder]l/ios/Pods/Headers/Public/Firebase/Firebase.h'  
    /Users/[path]/.pub-cache/hosted/pub.dev/firebase_messaging-15.0.1/ios/Classes/FLTFirebaseMessagingPlugin.h:11:8

[firebase_messaging]: (Beta) Build Error Using iOS 18 SDK, Xcode 16. · Issue #12993 · firebase/flutterfire (github.com)

解决方法: 增加 CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES 配置并且设置为 YES

image.png

PRODUCT_NAME 中文运行报错

BG 同学提供。

项目运行显示空白,并且报下面的错误

fab728956212e91558799ff2e6e4cad3.png

App is blank on macOS Sequoia 15 when app has a Chinese name and OS system language is set to Chinese · Issue #154400 · flutter/flutter (github.com)

原因是 PRODUCT_NAME 如果是中文就有这个问题。

4eafc9612dfb52c2b9b9561bfaa2ede4.png

PRODUCT_NAME 改成英文,然后在代码里面动态设置标题。

11c57a280abc40283f9e71009ef5603f.png

低版本 Flutter

最新更新 3.0.5 版本 flutter_tools patch,复制下面的内容到 xcode16.patch 文件里面,在 3.0.5 Flutter SDK 目录下面执行 git apply xcode16.patch , 删除本地 3.0.5 Flutter SDK

flutter/bin/cache/flutter_tools.snapshot

flutter/bin/cache/flutter_tools.stamp

执行 flutter doctor 重新编译 flutter_tools

diff --git a/packages/flutter_tools/bin/podhelper.rb b/packages/flutter_tools/bin/podhelper.rb
index 108eb23a20..d0c193d70e 100644
--- a/packages/flutter_tools/bin/podhelper.rb
+++ b/packages/flutter_tools/bin/podhelper.rb
@@ -47,16 +47,24 @@ def flutter_additional_ios_build_settings(target)
   end
 
   release_framework_dir = File.expand_path(File.join(artifacts_dir, 'ios-release', 'Flutter.xcframework'), __FILE__)
-
+  # Bundles are com.apple.product-type.bundle, frameworks are com.apple.product-type.framework.
+  target_is_resource_bundle = target.respond_to?(:product_type) && target.product_type == 'com.apple.product-type.bundle'
   target.build_configurations.each do |build_configuration|
     # Build both x86_64 and arm64 simulator archs for all dependencies. If a single plugin does not support arm64 simulators,
     # the app and all frameworks will fall back to x86_64. Unfortunately that case is not detectable in this script.
     # Therefore all pods must have a x86_64 slice available, or linking a x86_64 app will fail.
     build_configuration.build_settings['ONLY_ACTIVE_ARCH'] = 'NO' if build_configuration.type == :debug
-
+    # Workaround https://github.com/CocoaPods/CocoaPods/issues/11402, do not sign resource bundles.
+    if target_is_resource_bundle
+      build_configuration.build_settings['CODE_SIGNING_ALLOWED'] = 'NO'
+      build_configuration.build_settings['CODE_SIGNING_REQUIRED'] = 'NO'
+      build_configuration.build_settings['CODE_SIGNING_IDENTITY'] = '-'
+      build_configuration.build_settings['EXPANDED_CODE_SIGN_IDENTITY'] = '-'
+    end
     # Skip other updates if it's not a Flutter plugin (transitive dependency).
     next unless target.dependencies.any? { |dependency| dependency.name == 'Flutter' }
-
+    # Bitcode is deprecated, Flutter.framework bitcode blob will have been stripped.
+    build_configuration.build_settings['ENABLE_BITCODE'] = 'NO'
     # Profile can't be derived from the CocoaPods build configuration. Use release framework (for linking only).
     configuration_engine_dir = build_configuration.type == :debug ? debug_framework_dir : release_framework_dir
     Dir.new(configuration_engine_dir).each_child do |xcframework_file|
@@ -268,7 +276,7 @@ end
 # https://flutter.dev/go/plugins-list-migration
 def flutter_parse_plugins_file(file, platform)
   file_path = File.expand_path(file)
-  return [] unless File.exists? file_path
+  return [] unless File.exist? file_path
 
   dependencies_file = File.read(file)
   dependencies_hash = JSON.parse(dependencies_file)
diff --git a/packages/flutter_tools/bin/xcode_backend.dart b/packages/flutter_tools/bin/xcode_backend.dart
index 37ad2a4fd0..3cb619a4f7 100644
--- a/packages/flutter_tools/bin/xcode_backend.dart
+++ b/packages/flutter_tools/bin/xcode_backend.dart
@@ -373,10 +373,7 @@ class Context {
       }
       flutterFramework = '${environmentEnsure('FLUTTER_ENGINE')}/out/$localEngine/Flutter.xcframework';
     }
-    String bitcodeFlag = '';
-    if (environment['ENABLE_BITCODE'] == 'YES' && environment['ACTION'] == 'install') {
-      bitcodeFlag = 'true';
-    }
+ 
 
     // TODO(jmagman): use assemble copied engine in add-to-app.
     if (existsDir('$projectPath/.ios')) {
@@ -421,7 +418,6 @@ class Context {
       '-dTreeShakeIcons=${environment['TREE_SHAKE_ICONS'] ?? ''}',
       '-dTrackWidgetCreation=${environment['TRACK_WIDGET_CREATION'] ?? ''}',
       '-dDartObfuscation=${environment['DART_OBFUSCATION'] ?? ''}',
-      '-dEnableBitcode=$bitcodeFlag',
       '--ExtraGenSnapshotOptions=${environment['EXTRA_GEN_SNAPSHOT_OPTIONS'] ?? ''}',
       '--DartDefines=${environment['DART_DEFINES'] ?? ''}',
       '--ExtraFrontEndOptions=${environment['EXTRA_FRONT_END_OPTIONS'] ?? ''}',
diff --git a/packages/flutter_tools/lib/src/base/build.dart b/packages/flutter_tools/lib/src/base/build.dart
index 674bf4eb93..30a9671b98 100644
--- a/packages/flutter_tools/lib/src/base/build.dart
+++ b/packages/flutter_tools/lib/src/base/build.dart
@@ -115,16 +115,13 @@ class AOTSnapshotter {
     DarwinArch? darwinArch,
     String? sdkRoot,
     List<String> extraGenSnapshotOptions = const <String>[],
-    required bool bitcode,
+    // required bool bitcode,
     String? splitDebugInfo,
     required bool dartObfuscation,
     bool quiet = false,
   }) async {
     assert(platform != TargetPlatform.ios || darwinArch != null);
-    if (bitcode && platform != TargetPlatform.ios) {
-      _logger.printError('Bitcode is only supported for iOS.');
-      return 1;
-    }
+ 
 
     if (!_isValidAotPlatform(platform, buildMode)) {
       _logger.printError('${getNameForTargetPlatform(platform)} does not support AOT compilation.');
@@ -225,7 +222,6 @@ class AOTSnapshotter {
         sdkRoot: sdkRoot,
         assemblyPath: assembly,
         outputPath: outputDir.path,
-        bitcode: bitcode,
         quiet: quiet,
       );
       if (result.exitCode != 0) {
@@ -243,7 +239,6 @@ class AOTSnapshotter {
     String? sdkRoot,
     required String assemblyPath,
     required String outputPath,
-    required bool bitcode,
     required bool quiet
   }) async {
     final String targetArch = getNameForDarwinArch(appleArch);
@@ -265,12 +260,12 @@ class AOTSnapshotter {
       ],
     ];
 
-    const String embedBitcodeArg = '-fembed-bitcode';
+    
     final String assemblyO = _fileSystem.path.join(outputPath, 'snapshot_assembly.o');
 
     final RunResult compileResult = await _xcode.cc(<String>[
       ...commonBuildOptions,
-      if (bitcode) embedBitcodeArg,
+      
       '-c',
       assemblyPath,
       '-o',
@@ -290,7 +285,7 @@ class AOTSnapshotter {
       '-Xlinker', '-rpath', '-Xlinker', '@executable_path/Frameworks',
       '-Xlinker', '-rpath', '-Xlinker', '@loader_path/Frameworks',
       '-install_name', '@rpath/App.framework/App',
-      if (bitcode) embedBitcodeArg,
+   
       '-o', appLib,
       assemblyO,
     ];
diff --git a/packages/flutter_tools/lib/src/build_info.dart b/packages/flutter_tools/lib/src/build_info.dart
index 1ef94c7376..1619680500 100644
--- a/packages/flutter_tools/lib/src/build_info.dart
+++ b/packages/flutter_tools/lib/src/build_info.dart
@@ -881,7 +881,7 @@ const String kTargetPlatform = 'TargetPlatform';
 const String kTargetFile = 'TargetFile';
 
 /// The define to control whether the AOT snapshot is built with bitcode.
-const String kBitcodeFlag = 'EnableBitcode';
+// const String kBitcodeFlag = 'EnableBitcode';
 
 /// Whether to enable or disable track widget creation.
 const String kTrackWidgetCreation = 'TrackWidgetCreation';
diff --git a/packages/flutter_tools/lib/src/build_system/targets/android.dart b/packages/flutter_tools/lib/src/build_system/targets/android.dart
index ee86042f74..2a63137aae 100644
--- a/packages/flutter_tools/lib/src/build_system/targets/android.dart
+++ b/packages/flutter_tools/lib/src/build_system/targets/android.dart
@@ -248,7 +248,6 @@ class AndroidAot extends AotElfBase {
       buildMode: buildMode,
       mainPath: environment.buildDir.childFile('app.dill').path,
       outputPath: output.path,
-      bitcode: false,
       extraGenSnapshotOptions: extraGenSnapshotOptions,
       splitDebugInfo: splitDebugInfo,
       dartObfuscation: dartObfuscation,
diff --git a/packages/flutter_tools/lib/src/build_system/targets/common.dart b/packages/flutter_tools/lib/src/build_system/targets/common.dart
index c0e78b7398..1b11ca5cf9 100644
--- a/packages/flutter_tools/lib/src/build_system/targets/common.dart
+++ b/packages/flutter_tools/lib/src/build_system/targets/common.dart
@@ -291,7 +291,6 @@ abstract class AotElfBase extends Target {
       buildMode: buildMode,
       mainPath: environment.buildDir.childFile('app.dill').path,
       outputPath: outputPath,
-      bitcode: false,
       extraGenSnapshotOptions: extraGenSnapshotOptions,
       splitDebugInfo: splitDebugInfo,
       dartObfuscation: dartObfuscation,
diff --git a/packages/flutter_tools/lib/src/build_system/targets/ios.dart b/packages/flutter_tools/lib/src/build_system/targets/ios.dart
index ae2b2014fd..51fb03f746 100644
--- a/packages/flutter_tools/lib/src/build_system/targets/ios.dart
+++ b/packages/flutter_tools/lib/src/build_system/targets/ios.dart
@@ -54,7 +54,7 @@ abstract class AotAssemblyBase extends Target {
     }
 
     final List<String> extraGenSnapshotOptions = decodeCommaSeparated(environment.defines, kExtraGenSnapshotOptions);
-    final bool bitcode = environment.defines[kBitcodeFlag] == 'true';
+  
     final BuildMode buildMode = getBuildModeForName(environmentBuildMode);
     final TargetPlatform targetPlatform = getTargetPlatformForName(environmentTargetPlatform);
     final String? splitDebugInfo = environment.defines[kSplitDebugInfo];
@@ -99,7 +99,6 @@ abstract class AotAssemblyBase extends Target {
         outputPath: environment.fileSystem.path.join(buildOutputPath, getNameForDarwinArch(darwinArch)),
         darwinArch: darwinArch,
         sdkRoot: sdkRoot,
-        bitcode: bitcode,
         quiet: true,
         splitDebugInfo: splitDebugInfo,
         dartObfuscation: dartObfuscation,
@@ -280,9 +279,7 @@ abstract class UnpackIOS extends Target {
     if (archs == null) {
       throw MissingDefineException(kIosArchs, name);
     }
-    if (environment.defines[kBitcodeFlag] == null) {
-      throw MissingDefineException(kBitcodeFlag, name);
-    }
+
     _copyFramework(environment, sdkRoot);
 
     final File frameworkBinary = environment.outputDir.childDirectory('Flutter.framework').childFile('Flutter');
@@ -291,7 +288,9 @@ abstract class UnpackIOS extends Target {
       throw Exception('Binary $frameworkBinaryPath does not exist, cannot thin');
     }
     _thinFramework(environment, frameworkBinaryPath, archs);
-    _bitcodeStripFramework(environment, frameworkBinaryPath);
+    if (buildMode == BuildMode.release) {{
+      _bitcodeStripFramework(environment, frameworkBinaryPath);
+    }}
     _signFramework(environment, frameworkBinaryPath, buildMode);
   }
 
@@ -368,14 +367,12 @@ abstract class UnpackIOS extends Target {
 
   /// Destructively strip bitcode from the framework, if needed.
   void _bitcodeStripFramework(Environment environment, String frameworkBinaryPath) {
-    if (environment.defines[kBitcodeFlag] == 'true') {
-      return;
-    }
+ 
     final ProcessResult stripResult = environment.processManager.runSync(<String>[
       'xcrun',
       'bitcode_strip',
       frameworkBinaryPath,
-      '-m', // leave the bitcode marker.
+      '-r', // leave the bitcode marker.
       '-o',
       frameworkBinaryPath,
     ]);
@@ -599,7 +596,7 @@ Future<void> _createStubAppFramework(File outputFile, Environment environment,
       for (String arch in iosArchNames ?? <String>{}) ...<String>['-arch', arch],
       stubSource.path,
       '-dynamiclib',
-      '-fembed-bitcode-marker',
+      // '-fembed-bitcode-marker',
       // Keep version in sync with AOTSnapshotter flag
       if (environmentType == EnvironmentType.physical)
         '-miphoneos-version-min=9.0'
diff --git a/packages/flutter_tools/lib/src/build_system/targets/macos.dart b/packages/flutter_tools/lib/src/build_system/targets/macos.dart
index d29fadad19..3c949fb894 100644
--- a/packages/flutter_tools/lib/src/build_system/targets/macos.dart
+++ b/packages/flutter_tools/lib/src/build_system/targets/macos.dart
@@ -283,7 +283,6 @@ class CompileMacOSFramework extends Target {
       }
 
       pending.add(snapshotter.build(
-        bitcode: false,
         buildMode: buildMode,
         mainPath: environment.buildDir.childFile('app.dill').path,
         outputPath: environment.fileSystem.path.join(buildOutputPath, getNameForDarwinArch(darwinArch)),
diff --git a/packages/flutter_tools/lib/src/commands/build_ios.dart b/packages/flutter_tools/lib/src/commands/build_ios.dart
index 5607ff6a38..48f34b9801 100644
--- a/packages/flutter_tools/lib/src/commands/build_ios.dart
+++ b/packages/flutter_tools/lib/src/commands/build_ios.dart
@@ -243,25 +243,13 @@ class BuildIOSArchiveCommand extends _BuildIOSSubCommand {
 <plist version="1.0">
     <dict>
         <key>method</key>
-''');
-
-    plistContents.write('''
         <string>${stringArg('export-method')}</string>
-    ''');
-    if (xcodeBuildResult?.xcodeBuildExecution?.buildSettings['ENABLE_BITCODE'] != 'YES') {
-      // Bitcode is off by default in Flutter iOS apps.
-      plistContents.write('''
-    <key>uploadBitcode</key>
+        <key>uploadBitcode</key>
         <false/>
     </dict>
 </plist>
 ''');
-    } else {
-      plistContents.write('''
-</dict>
-</plist>
-''');
-    }
+    
 
     final File tempPlist = globals.fs.systemTempDirectory
         .createTempSync('flutter_build_ios.').childFile('ExportOptions.plist');
diff --git a/packages/flutter_tools/lib/src/commands/build_ios_framework.dart b/packages/flutter_tools/lib/src/commands/build_ios_framework.dart
index 1af299a55e..1d6d88bdd8 100644
--- a/packages/flutter_tools/lib/src/commands/build_ios_framework.dart
+++ b/packages/flutter_tools/lib/src/commands/build_ios_framework.dart
@@ -359,7 +359,7 @@ end
           defines: <String, String>{
             kTargetFile: targetFile,
             kTargetPlatform: getNameForTargetPlatform(TargetPlatform.ios),
-            kBitcodeFlag: 'true',
+            
             kIosArchs: defaultIOSArchsForEnvironment(sdkType)
                 .map(getNameForDarwinArch)
                 .join(' '),
@@ -413,8 +413,6 @@ end
       ' ├─Building plugins...'
     );
     try {
-      final String bitcodeGenerationMode = mode == BuildMode.release ?
-          'bitcode' : 'marker'; // In release, force bitcode embedding without archiving.
 
       List<String> pluginsBuildCommand = <String>[
         ...globals.xcode!.xcrunCommand(),
@@ -425,7 +423,6 @@ end
         '-configuration',
         xcodeBuildConfiguration,
         'SYMROOT=${iPhoneBuildOutput.path}',
-        'BITCODE_GENERATION_MODE=$bitcodeGenerationMode',
         'ONLY_ACTIVE_ARCH=NO', // No device targeted, so build all valid architectures.
         'BUILD_LIBRARY_FOR_DISTRIBUTION=YES',
       ];
@@ -450,7 +447,6 @@ end
         '-configuration',
         simulatorConfiguration,
         'SYMROOT=${simulatorBuildOutput.path}',
-        'ENABLE_BITCODE=YES', // Support host apps with bitcode enabled.
         'ONLY_ACTIVE_ARCH=NO', // No device targeted, so build all valid architectures.
         'BUILD_LIBRARY_FOR_DISTRIBUTION=YES',
       ];
@@ -516,8 +512,7 @@ end
         ...framework.parent
             .listSync()
             .where((FileSystemEntity entity) =>
-                entity.basename.endsWith('bcsymbolmap') ||
-                entity.basename.endsWith('dSYM'))
+            entity.basename.endsWith('dSYM'))
             .map((FileSystemEntity entity) =>
                 <String>['-debug-symbols', entity.path])
             .expand<String>((List<String> parameter) => parameter)
diff --git a/packages/flutter_tools/lib/src/ios/bitcode.dart b/packages/flutter_tools/lib/src/ios/bitcode.dart
deleted file mode 100644
index e07d89219d..0000000000
--- a/packages/flutter_tools/lib/src/ios/bitcode.dart
+++ /dev/null
@@ -1,66 +0,0 @@
-// Copyright 2014 The Flutter Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-import '../artifacts.dart';
-import '../base/common.dart';
-import '../base/context.dart';
-import '../base/process.dart';
-import '../base/version.dart';
-import '../build_info.dart';
-import '../globals.dart' as globals;
-import '../macos/xcode.dart';
-
-const bool kBitcodeEnabledDefault = false;
-
-Future<void> validateBitcode(BuildMode buildMode, TargetPlatform targetPlatform, EnvironmentType environmentType) async {
-  final Artifacts? localArtifacts = globals.artifacts;
-  final String? flutterFrameworkPath = localArtifacts?.getArtifactPath(
-    Artifact.flutterFramework,
-    mode: buildMode,
-    platform: targetPlatform,
-    environmentType: environmentType,
-  );
-  final Xcode? xcode = context.get<Xcode>();
-
-  final RunResult? clangResult = await xcode?.clang(<String>['--version']);
-  final String? clangVersion = clangResult?.stdout.split('\n').first;
-  final String? engineClangVersion = flutterFrameworkPath == null
-      ? null
-      : globals.plistParser.getStringValueFromFile(
-          globals.fs.path.join(flutterFrameworkPath, 'Info.plist'),
-          'ClangVersion',
-        );
-  final Version engineClangSemVer = _parseVersionFromClang(engineClangVersion);
-  final Version clangSemVer = _parseVersionFromClang(clangVersion);
-  if (engineClangSemVer > clangSemVer) {
-    throwToolExit(
-      'The Flutter.framework at $flutterFrameworkPath was built '
-      'with "${engineClangVersion ?? 'unknown'}", but the current version '
-      'of clang is "$clangVersion". This will result in failures when trying to '
-      'archive an IPA. To resolve this issue, update your version of Xcode to '
-      'at least $engineClangSemVer.',
-    );
-  }
-}
-
-Version _parseVersionFromClang(String? clangVersion) {
-  final RegExp pattern = RegExp(r'Apple (LLVM|clang) version (\d+\.\d+\.\d+) ');
-  Never _invalid() {
-    throwToolExit('Unable to parse Clang version from "$clangVersion". '
-                  'Expected a string like "Apple (LLVM|clang) #.#.# (clang-####.#.##.#)".');
-  }
-
-  if (clangVersion == null || clangVersion.isEmpty) {
-    _invalid();
-  }
-  final RegExpMatch? match = pattern.firstMatch(clangVersion);
-  if (match == null || match.groupCount != 2) {
-    _invalid();
-  }
-  final Version? version = Version.parse(match.group(2));
-  if (version == null) {
-    _invalid();
-  }
-  return version;
-}
diff --git a/packages/flutter_tools/lib/src/ios/xcresult.dart b/packages/flutter_tools/lib/src/ios/xcresult.dart
index 4f505735f9..c2af38aa2f 100644
--- a/packages/flutter_tools/lib/src/ios/xcresult.dart
+++ b/packages/flutter_tools/lib/src/ios/xcresult.dart
@@ -5,6 +5,7 @@
 import '../../src/base/process.dart';
 import '../../src/convert.dart' show json;
 import '../../src/macos/xcode.dart';
+import '../base/version.dart';
 import '../convert.dart';
 
 /// The generator of xcresults.
@@ -40,11 +41,15 @@ class XCResultGenerator {
   Future<XCResult> generate(
       {List<XCResultIssueDiscarder> issueDiscarders =
           const <XCResultIssueDiscarder>[]}) async {
+    final Version? xcodeVersion = xcode.currentVersion;
     final RunResult result = await processUtils.run(
       <String>[
         ...xcode.xcrunCommand(),
         'xcresulttool',
         'get',
+        // See https://github.com/flutter/flutter/issues/151502
+        if (xcodeVersion != null && xcodeVersion >= Version(16, 0, 0))
+          '--legacy',
         '--path',
         resultPath,
         '--format',
@@ -76,7 +81,10 @@ class XCResultGenerator {
 /// The result contains useful information such as build errors and warnings.
 class XCResult {
   /// Parse the `resultJson` and stores useful informations in the returned `XCResult`.
-  factory XCResult({required Map<String, Object?> resultJson, List<XCResultIssueDiscarder> issueDiscarders = const <XCResultIssueDiscarder>[]}) {
+  factory XCResult(
+      {required Map<String, Object?> resultJson,
+      List<XCResultIssueDiscarder> issueDiscarders =
+          const <XCResultIssueDiscarder>[]}) {
     final List<XCResultIssue> issues = <XCResultIssue>[];
 
     final Object? issuesMap = resultJson['issues'];
diff --git a/packages/flutter_tools/templates/module/ios/host_app_ephemeral_cocoapods/Podfile.copy.tmpl b/packages/flutter_tools/templates/module/ios/host_app_ephemeral_cocoapods/Podfile.copy.tmpl
index e52930d6bc..5d84a5ac81 100644
--- a/packages/flutter_tools/templates/module/ios/host_app_ephemeral_cocoapods/Podfile.copy.tmpl
+++ b/packages/flutter_tools/templates/module/ios/host_app_ephemeral_cocoapods/Podfile.copy.tmpl
@@ -36,5 +36,8 @@ end
 post_install do |installer|
   installer.pods_project.targets.each do |target|
     flutter_additional_ios_build_settings(target)
+    target.build_configurations.each do |config|
+      config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '9.0'
+     end       
   end
 end
diff --git a/packages/flutter_tools/templates/module/ios/library/Flutter.tmpl/podhelper.rb.tmpl b/packages/flutter_tools/templates/module/ios/library/Flutter.tmpl/podhelper.rb.tmpl
index 3b065203dd..0aa28cb5b9 100644
--- a/packages/flutter_tools/templates/module/ios/library/Flutter.tmpl/podhelper.rb.tmpl
+++ b/packages/flutter_tools/templates/module/ios/library/Flutter.tmpl/podhelper.rb.tmpl
@@ -131,7 +131,7 @@ end
 # https://flutter.dev/go/plugins-list-migration
 def flutter_parse_dependencies_file_for_ios_plugin(file)
   file_path = File.expand_path(file)
-  return [] unless File.exists? file_path
+  return [] unless File.exist? file_path
 
   dependencies_file = File.read(file)
   dependencies_hash = JSON.parse(dependencies_file)
diff --git a/packages/flutter_tools/test/general.shard/build_system/targets/common_test.dart b/packages/flutter_tools/test/general.shard/build_system/targets/common_test.dart
index 31258f16f8..3c9bbe2368 100644
--- a/packages/flutter_tools/test/general.shard/build_system/targets/common_test.dart
+++ b/packages/flutter_tools/test/general.shard/build_system/targets/common_test.dart
@@ -569,7 +569,7 @@ void main() {
 
   testUsingContext('AotAssemblyProfile with bitcode sends correct argument to snapshotter (one arch)', () async {
     iosEnvironment.defines[kIosArchs] = 'arm64';
-    iosEnvironment.defines[kBitcodeFlag] = 'true';
+ 
     iosEnvironment.defines[kSdkRoot] = 'path/to/iPhoneOS.sdk';
     final String build = iosEnvironment.buildDir.path;
     processManager.addCommands(<FakeCommand>[
@@ -644,7 +644,7 @@ void main() {
     iosEnvironment.defines[kCodeSizeDirectory] = 'code_size_1';
     iosEnvironment.defines[kIosArchs] = 'arm64';
     iosEnvironment.defines[kSdkRoot] = 'path/to/iPhoneOS.sdk';
-    iosEnvironment.defines[kBitcodeFlag] = 'true';
+
     final String build = iosEnvironment.buildDir.path;
     processManager.addCommands(<FakeCommand>[
       FakeCommand(command: <String>[

针对高版本的 Flutter (3.24.x) ,暂时没有发现其他问题。以下内容是针对低版本,比如我这里是使用的 3.0.5 ,最后一个支持 ios 9.0Flutter SDK

因为在 3.0.5 运行失败,下面是根据日志自行查找问题的过程。

legacy flag

运行 flutter run -v,第一个发现错误是下面的错误,这个应该不是最终导致编译失败的原因,因为编译日志断在后面。

/usr/bin/arch -arm64e xcrun xcresulttool get --path /var/folders/fm/wjzsj_z95ydgn4khxqgbtqx000mfq2/T/flutter_tools.PkqAFW/flutter_ios_build_temp_dirFAy4yP/temporary_xcresult_bundle --format json
[ +856 ms] Error: This command is deprecated and will be removed in a future release, --legacy flag is required to use it.
                    Usage: xcresulttool get object [--legacy] --path <path> [--id <id>] [--version <version>] [--format <format>]
                      See 'xcresulttool get object --help' for more information.

搜索了一下 issue ,发现最新才合并的一个问题:

Add xcresulttool --legacy flag for deprecated usage by jmagman · Pull Request #152988 · flutter/flutter (github.com)

按照提示修改了 github.com/flutter/flu… 代码。

截屏2024-09-19 16.36.57.png

删除本地 Flutter SDK

flutter/bin/cache/flutter_tools.snapshot

flutter/bin/cache/flutter_tools.stamp

执行 flutter doctor 重新编译 flutter_tools ,再次运行项目,还是报错。

bitcode 导致的报错

运行 flutter run -v,跟踪到 process.dart 执行一个命令时报错。

arget debug_universal_framework failed: ProcessException: Process exited abnormally:
                          ld: warning: -bitcode_bundle is no longer supported and will be ignored
                          ld: warning: -bitcode_process_mode is no longer supported and will be ignored
                          ld: file cannot be open()ed, errno=2 path=marker in 'marker'
                          clang: error: linker command failed with exit code 1 (use -v to see invocation)
                            Command: /usr/bin/arch -arm64e xcrun clang -x c -arch arm64
                            /var/folders/dh/g2znj0xd5w33ywhvv4wxvd240000gn/T/flutter_tools.RthOAn/flutter_tools_stub_source.62gemK/debug_app.cc -dynamiclib
-fembed-bitcode-marker
                            -miphonesimulator-version-min=9.0 -Xlinker -rpath -Xlinker @executable_path/Frameworks -Xlinker -rpath -Xlinker @loader_path/Frameworks
-install_name
                            @rpath/App.framework/App -isysroot
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator18.0.sdk -o
                            /Users/zmtzawqlp/Documents/flutter/github/abcd/.dart_tool/flutter_build/57ba3070442bc6d1a61e4871c8443a69/App.framework/App
                          #0      RunResult.throwException (package:flutter_tools/src/base/process.dart:124:5)
                          #1      _DefaultProcessUtils.run (package:flutter_tools/src/base/process.dart:276:19)

定位到:ld: file cannot be open()ed, errno=2 path=marker in 'marker' clang: error: linker command failed with exit code 1 (use -v to see invocation)

后面的 /usr/bin/arch -arm64e xcrun clang -x c -arch arm64 为命令的开始,后面的是各种参数。 -fembed-bitcode-marker 这个东西很显眼,跟我们的报错信息也有关联。

找到本地 Flutter SDK 文件位置为:

flutter/packages/flutter_tools/lib/src/build_system/targets/ios.dart

截屏2024-09-19 16.47.27.png

翻看了最新的 Flutter SDK 记录,发现这个命令已经在

Stop embedding bitcode for iOS in tool by jmagman · Pull Request #112831 · flutter/flutter (github.com) 中删除掉了。

接着我们注释掉 -fembed-bitcode-marker,然后

删除本地 Flutter SDK

flutter/bin/cache/flutter_tools.snapshot

flutter/bin/cache/flutter_tools.stamp

执行 flutter doctor 重新编译 flutter_tools ,再次运行项目, 成功。

注意,去掉 -fembed-bitcode-marker 只能保证你 debug 运行成功,Stop embedding bitcode for iOS in tool by jmagman · Pull Request #112831 · flutter/flutter (github.com) 中的改动请都修改完成。

结语

每次 Xcode 升级,都会带来新的惊喜,既然早晚都要适配,为啥头铁的不可以是我呢?如果发现其他问题,将持续更新,也欢迎大家反馈。

Flutter,爱糖果,欢迎加入Flutter Candies,一起生产可爱的Flutter小糖果 最最后放上 Flutter Candies 全家桶,真香。