Start Debugging

修正: Xcode 16 と Flutter 3.x で Failed to build iOS app

60 秒で直す方法: Flutter を 3.24.4 以降にアップグレードし、Podfile のプラットフォームを iOS 13 に上げ、Pods と DerivedData を消してから pod install を実行します。エラーが Dart コードにあることはまれです。

ひとことで言うと: Xcode 16 へのアップグレード後の Failed to build iOS app は、ほとんどの場合あなたの Dart コードが原因ではありません。頻度順に 4 つの原因のいずれかです。Xcode 16 の新しいモジュール検証器を知らない 3.24.4 より古い Flutter SDK、まだ platform :ios, '11.0' を固定している Podfile (Xcode 16 は iOS 11 シミュレーターのサポートを廃止しました)、前の Xcode で残った ios/Pods~/Library/Developer/Xcode/DerivedData/ModuleCache.noindex の古いキャッシュ、または Swift 6 / Xcode 16 互換のリリースをまだ出していないプラグインです。Flutter をアップグレードし、Podfile を iOS 13 に上げ、両方のキャッシュを消して、pod install を実行し、ビルドし直してください。flutter clean を最初のステップとして頼るのはやめましょう。実際に壊れている iOS のキャッシュには触れません。

Launching lib/main.dart on iPhone 16 Pro in debug mode...
Running Xcode build...
Xcode build done.                                           38.4s
Failed to build iOS app
Error (Xcode): Swift Compiler Error (Xcode): No such module 'Flutter'
/Users/me/MyApp/ios/Runner/AppDelegate.swift:2:8

Could not build the application for the simulator.
Error launching application on iPhone 16 Pro.

このガイドは Flutter 3.41.5 (stable チャンネル、2026 年 5 月)、Xcode 16.x ライン (執筆時点で 16.0 から 16.4)、CocoaPods 1.16.2、Apple Silicon 上の macOS Sequoia 15.3 を対象に書かれています。同じ修正は Flutter 3.24.4 以降にも当てはまります。Flutter 3.19 以前を使っている場合は、まずアップグレードのステップを見てください。そのブランチではポッドをいじっても救われません。Xcode 16 をきれいに動かす関連の Flutter の変更は flutter/flutter#155438 に入り、続く modulemap の修正は flutter/flutter#157461 に入りました。

Failed to build iOS app が実際に伝えていること

Failed to build iOS app は Flutter ツールの傘メッセージです。これが意味するのは「xcodebuild が非ゼロの終了コードを返した」ということだけです。実際の診断はその直上または直下の Error (Xcode): で始まる行です。同じ傘の下に表面化する根本的なエラーはおよそ 6 種類あります。

  1. No such module 'Flutter' — Swift コンパイラーが Flutter フレームワークモジュールを見つけられません。ほぼ常に Xcode 16 へのアップグレード後の Podfile または pod install の問題です。
  2. no such file or directory: '.../ModuleCache.noindex/Session.modulevalidation' — Xcode 16 の新しいモジュール検証器が Xcode 15 によって書かれたキャッシュファイルを読めません。issue #157461 を参照してください。
  3. Using bridging headers with module interfaces is unsupported — Xcode 15 で動いていたプラグインの module.modulemap とブリッジングヘッダーのパターンが、今やハードエラーになっています。
  4. type 'UIApplication' does not conform to protocol 'Launcher' — 古いプラグイン (一般的に 6.3.0 より前の url_launcher_ios) における Swift 6 の厳密適合エラーです。
  5. Undefined symbol: _swift_FORCE_LOAD$_swiftCompatibility56 — Swift ランタイム ABI の不一致、ほぼ常に以前の Xcode SDK からの CocoaPods キャッシュです。
  6. The iOS deployment target 'IPHONEOS_DEPLOYMENT_TARGET' is set to 11.0, but the range of supported deployment target versions is 12.0 to 18.4Podfile がまだ Xcode 16 が削除した iOS 11 を固定しています。

これらはそれぞれ異なる根本原因を持つ別々のバグです。最初の仕事は、ツールが実際にどれにヒットしたかを特定することです。ターミナルを上にスクロールし、ファイルパスと行番号を持つ error: の行を見つけてください。それが真実であり、Failed to build iOS app は症状です。

flutter build から実際のエラーを読む

xcodebuild の下層出力が要約されないように、詳細ログ付きで実行してください。

# Flutter 3.41.5
flutter build ios --verbose 2>&1 | tee build.log

そして最初の error: (小文字、これが Xcode のプレフィックスです) をログから探してください。Error (Xcode) (これは Flutter による再フォーマット) ではありません。

grep -n "error:" build.log | head -20

最初の一致が修正すべきものです。後続のエラーは通常、最初のものから連鎖したものです。詳細出力がなければ、推測しているだけです。

一般的な形態の 1 つを示す最小再現

2026 年に最も一般的な形態は、Podfile のプラットフォーム固定と古い Pods ディレクトリの組み合わせです。新しい Flutter プロジェクトを作り、iOS deployment target を 11.0 に固定してください。

# ios/Podfile, Flutter 3.41.5, CocoaPods 1.16.2
platform :ios, '11.0'

# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true'

project 'Runner', {
  'Debug' => :debug,
  'Profile' => :release,
  'Release' => :release,
}

# ... rest of the default Podfile ...

Xcode 16 で flutter build ios --no-codesign を実行すると、ビルドは次のエラーで失敗します。

[!] Automatically assigning platform `iOS` with version `11.0` on target `Runner`
    because no platform was specified. Please specify a platform for this target
    in your Podfile.
...
error: The iOS deployment target 'IPHONEOS_DEPLOYMENT_TARGET' is set to 11.0,
       but the range of supported deployment target versions is 12.0 to 18.4.
       (in target 'firebase_core' from project 'Pods')
Failed to build iOS app

同じ Podfile が Xcode 15.4 では文句なくビルドされます。バグは Xcode 16 の新しい deployment target の下限であり、あなたのコードではありません。

修正、頻度の高い順

これらのステップを順番に適用してください。各ステップは前のステップが効かなかったことを前提としています。

1. Flutter を 3.24.4 以降にアップグレードする

Flutter 3.24.4 (2024 年 10 月) は xcode_backend.sh と Generated.xcconfig テンプレートへの Xcode 16 修正を出荷した最初の stable リリースです。2026 年の 3.41.x ラインのどのリリースも最新です。何を持っているか確認してアップグレードしてください。

flutter --version
flutter upgrade

チャンネルが master であるか、ローカルでエンジンを変更しているために flutter upgrade が拒否される場合は、stable に戻してください。

flutter channel stable
flutter upgrade

この単一のステップで、2024 年と 2025 年に Xcode 16 に対して提出された No such module 'Flutter' の報告の大部分が解決します。Flutter チームはまさにこの理由で issue #155438 を 3.24.4 で修正済みとしてクローズしました。

2. Podfile のプラットフォームを iOS 13 に上げる

Xcode 16 は依然として iOS 12 を deployment target としてサポートしますが、最近のプラグインのほとんど (Firebase、Google Maps、SwiftUI を扱う何でも) は今では iOS 13 を要求します。下限を iOS 13 に設定するのが 2026 年の安全なデフォルトです。

# ios/Podfile, Flutter 3.41.5
platform :ios, '13.0'

これを runner プロジェクトにも反映する必要があります。ios/Runner.xcworkspace を開き、Runner ターゲットを選び、Build Settings に行き、debug と release の両方について iOS Deployment Target13.0 に設定してください。ワークスペースのビルド設定は Runner ターゲットでは Podfile に勝ちます。Podfile の行はポッドターゲットのみに影響します。

Podfile に post_install ブロックがある場合、すべてのポッドに同じ最小値を継承させてください (これは最新の Flutter テンプレートのスニペットです)。

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'] = '13.0'
    end
  end
end

3. Pods、ロックファイル、モジュールキャッシュを消す

このステップが ModuleCache.noindex のエラーと、ほとんどの Undefined symbol: _swift_FORCE_LOAD$_swiftCompatibility56 の報告を修正します。以前の Xcode の Swift ABI キャッシュは Xcode 16 の swiftc と互換性がなく、flutter clean は触れません。プロジェクトのルートから:

# Flutter 3.41.5, CocoaPods 1.16.2
flutter clean
cd ios
rm -rf Pods Podfile.lock .symlinks
rm -rf ~/Library/Developer/Xcode/DerivedData
pod cache clean --all
pod install --repo-update
cd ..
flutter pub get

pod install --repo-update (注意: 単なる pod install ではない) は CocoaPods specs リポジトリを更新し、前回のビルド以降に公開されたプラグインの podspec を取得できるようにします。これをスキップすると、まだ iOS 11 を固定している昨日の firebase_core.podspec をインストールすることになります。

4. プラグイン、特にエラーに名前が挙がっているものを更新する

エラーが type 'UIApplication' does not conform to protocol 'Launcher' の場合、プラグインが古くなっています。最も一般的な 2 つの違反者は url_launcher_ioswebview_flutter_wkwebview です。最新の minor バージョンに上げてください。

flutter pub upgrade --major-versions

何らかの依存関係が固定しているために全体のアップグレードができない場合、エラーに名前が挙がっているプラグインだけを更新してください。

flutter pub upgrade --major-versions url_launcher_ios

それからステップ 3 をやり直してください (ポッドはバージョンごとにキャッシュされます。pubspec.yaml の変更で pod install が自動的に再実行されることはありません)。pub upgrade 自体が失敗する場合の pubspec リゾルバーの不満を読むためのより深いガイドについては、「Version solving failed」 がバグではなく証明である理由 を参照してください。

5. すべてのポッドで Swift のバージョンを単一に強制する

ビルド失敗のサブセットは、SWIFT_VERSION を宣言しなかったポッドから来ます。Xcode 16 ではデフォルトで Swift 6 厳密モードになり、完全に合法な Swift 5 コードで爆発します。修正は、同じ post_install ブロックですべてのポッドを Swift 5 に固定することです。

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'] = '13.0'
      config.build_settings['SWIFT_VERSION'] = '5.0'
    end
  end
end

これは回避策であり、修正ではありません。正しい長期的な解決策は、プラグインに対して自身の Swift バージョンを宣言するように issue を立てることですが、この固定は今日あなたのブロックを解除します。

6. 最後の手段としてのみ、ios/Runner.xcodeproj の設定を削除して再生成する

project.pbxproj を手動で編集した (ネイティブターゲットを追加した、カスタムビルドフェーズを入れた、App Clip エクステンションを追加した) ことがあり、上記のどれも効かなかった場合、Runner ターゲットには Xcode 16 以前の古いビルド設定が残っている可能性があります。ios/Runner.xcodeproj をバックアップし、新たに生成したものと差分を取ってください。

# Flutter 3.41.5
flutter create --platforms=ios --project-name=runner /tmp/scratch
diff -r ios/Runner.xcodeproj /tmp/scratch/ios/Runner.xcodeproj

関連するビルド設定 (IPHONEOS_DEPLOYMENT_TARGETSWIFT_VERSIONENABLE_USER_SCRIPT_SANDBOXINGSTRING_CATALOG_GENERATE_SYMBOLS) を scratch プロジェクトから自分のものへ 1 つずつ移植し、その都度ビルドし直してください。面倒ですが、5 年分の Xcode アップグレードの残骸を蓄積したプロジェクトを回復する唯一の信頼できる方法です。

落とし穴と似た事例

このエラーに似ているがそうではないいくつかの事例:

ステップ 1 から 5 を 2 度繰り返してもまだ同じエラーが出る場合、次の手はプラグインの二分探索です。pubspec.yamlfluttercupertino_icons 以外のすべての直接依存をコメントアウトし、消去とビルドのサイクルを実行し、空のプロジェクトがビルドされることを確認してください。それから依存関係を 3 つずつのグループでコメントを外していきます。失敗を再導入する最初のグループに犯人のプラグインが含まれています。遅いですが決定論的で、提出可能なバグレポートを与えてくれます。

関連

参考資料

Comments

Sign in with GitHub to comment. Reactions and replies thread back to the comments repo.

< 戻る