.NET MAUI プロジェクトをビルドしたときに、Firebase や GoogleUtilities の xcframework 内にある PrivacyInfo.xcprivacy や Info.plist が「見つからない」と言われて MSB3030 エラーが大量発生し、iOS 向けビルドが全く通らない――そんな状況にハマったときの原因と具体的な解決手順をまとめます。
.NET MAUI で MSB3030(ファイルが見つからない)が連発する状況
まずは、今回のトラブルがどのような状況で発生するのかを整理します。特に .NET 9 時代の .NET MAUI+Firebase 構成では、多くの開発者が一度は遭遇しやすいパターンです。
発生しているエラー メッセージの典型例
ビルド時の出力ウィンドウや CI のログには、次のようなメッセージが大量に並びます。
Microsoft.Common.CurrentVersion.targets(5094,5): error MSB3030:
Could not copy the file "obj/Release/net9.0-ios/ios-arm64/***/PrivacyInfo.xcprivacy"
because it was not found.
あるいは、次のように xcframework 内の Swift モジュールや Info.plist が見つからないと言われることもあります。
error MSB3030: Could not copy the file
"obj/Release/net9.0-ios/ios-arm64/***/FirebaseAnalytics.xcframework/Info.plist"
because it was not found.
Android ターゲットは正常にビルドできるのに、iOS ターゲットだけが MSB3030 で失敗する、というケースがほとんどです。
対象となる環境の一例
質問として挙がりやすい構成をまとめると、次のようになります。
| 項目 | 内容 |
|---|---|
| .NET / MAUI バージョン | .NET 9、.NET MAUI マルチターゲット(Android・iOS) |
| IDE | Visual Studio 2022(Windows) |
| NuGet パッケージ | Firebase、GoogleUtilities、Xamarin 系パッケージなどを併用 |
| エラー | MSB3030(Microsoft.Common.CurrentVersion.targets 5094 行目付近) |
特別に変わったプロジェクト設定をしていなくても、既存の Xamarin 時代のパッケージを MAUI に持ち込んだり、Firebase 関連パッケージをまとめて更新したタイミングで突然発生するケースが多い印象です。
なぜリソース ファイルが「存在しない」と判断されるのか
MSB3030 は MSBuild の汎用エラーで、「コピーしようとしているファイルが見つからない」場合に出力されます。つまり、ビルド タスクの入力として指定されたパスと、実際に存在するファイルのパスが一致していないということです。
MAUI + Firebase で起こりやすいパターン
.NET MAUI プロジェクトで Firebase の iOS SDK(xcframework)を参照している場合、ビルド中に次のようなステップが行われます。
- NuGet パッケージから xcframework や .bundle の中身が
obj配下に展開される - MSBuild が、展開されたファイル(PrivacyInfo.xcprivacy や Info.plist、Swift モジュールなど)をコピー対象として列挙する
- 列挙されたパスにファイルが見つからないと、MSB3030 を投げてビルドが失敗する
今回のポイントは「NuGet パッケージからの展開が途中で止まっている」「古い中間生成物が残っている」といった理由で、MSBuild が期待するファイル構成と、実際の obj フォルダーの中身がズレてしまうことです。
よくある原因のパターン
| 原因候補 | 説明 |
|---|---|
| NuGet パッケージ展開の不整合 | パッケージ更新中に IDE を強制終了したり、ネットワーク切断が起こると、一部のファイルだけ展開されずに中途半端な状態になることがあります。 |
| 古い obj / bin の残骸 | ターゲット フレームワークを変更したり、MAUI / Firebase のバージョンを大きく更新した際に、古い中間成果物が残って MSBuild が誤ったパスを参照してしまうことがあります。 |
| ウイルス対策ソフト等によるロック | リアルタイム スキャンが働いてファイル コピーの途中でロックされ、MSBuild から見ると「存在しない」扱いになってしまうケースもあります。 |
| 手動でのフォルダー削除の不備 | 一部のサブフォルダーだけを削除してしまい、MAUI のマルチターゲット構成のうち iOS 側だけ中途半端な状態になることがあります。 |
最も手軽で効果的な対処:bin / obj フォルダーの削除
実際の質問者のケースでも、もっともシンプルな「bin と obj を丸ごと削除してから再ビルドする」だけで MSB3030 が解消しています。まずはこの手順を試すのが鉄則です。
コマンドラインからのクリーン手順
Windows の開発環境であれば、プロジェクトのルート フォルダーで次のコマンドを実行します。
REM プロジェクト直下で実行
rd /s /q bin
rd /s /q obj
dotnet build REM もしくは dotnet build -t:Run など
PowerShell を使う場合の例です。
Remove-Item -Recurse -Force bin, obj
dotnet build
Visual Studio から操作したい場合は、「ビルド > クリーン ソリューション」の後に「ビルド > ソリューションのリビルド」を実行すると、同様の効果が得られます。
なぜ bin / obj の削除で直るのか
bin / obj フォルダーは、あくまで「中間生成物」と「出力物」が入っているだけで、ソース コードやプロジェクト設定のような本質的な情報は含んでいません。ここを削除することで、次のようなメリットがあります。
- 途中で止まった NuGet 展開の残骸をすべて捨てられる
- 古いターゲット フレームワーク用のファイルが混ざることを防げる
- MSBuild が
objをゼロから再構築するため、ファイル パスの不整合が解消される
特に MAUI は Android / iOS / Windows など複数ターゲットの成果物をまとめて obj に展開するため、一度ズレると手作業での修正はほぼ不可能です。迷ったら「一旦捨てる」が正解です。
再発防止のための追加メンテナンス:NuGet キャッシュのクリア
bin / obj の削除だけで問題が解決することも多いですが、Firebase や Xamarin 由来のパッケージを長年アップデートし続けているプロジェクトでは、NuGet キャッシュ側にも古い情報が残っている場合があります。再発防止のためには、NuGet キャッシュのクリアもあわせて行うのがおすすめです。
dotnet CLI でキャッシュをクリアする
.NET SDK が提供する dotnet nuget locals コマンドを使えば、NuGet のローカル キャッシュをまとめて削除できます。
dotnet nuget locals all --clear
dotnet restore
ここで --clear を付けることで、グローバル パッケージ フォルダーや HTTP キャッシュなどが一気にクリアされます。その後の dotnet restore により、必要なパッケージがすべて最新の状態で取り直されるため、xcframework の中身が欠けるリスクを大きく下げられます。
CI 環境でのおすすめ設定
CI サーバー(GitHub Actions や Azure DevOps など)でビルドしている場合は、次のような工夫も有効です。
- 重要なブランチのビルドでは、定期的に
dotnet restore --no-cacheを実行してキャッシュ依存を減らす - ビルド用の一時ディレクトリを毎回クリーンに作り直す
- キャッシュ機構を使う場合も、MAUI / Firebase のメジャーアップデート時にはキャッシュキーを変更して再取得を強制する
特に xcframework のサイズは大きいため、キャッシュが壊れた状態で長期間使い回されると、原因特定に非常に時間がかかります。多少ビルド時間が伸びても、一度キャッシュを捨ててクリーンな状態で確認することが、結果的に近道になることが多いです。
Visual Studio 側で設定しておきたいポイント
開発用マシンの Visual Studio では、MSB3030 のような「ファイル欠落系」のトラブルを早めに検知できるよう、いくつかの設定をオンにしておくと安心です。
不足パッケージを自動検出する設定
Visual Studio 2022 では、NuGet パッケージの欠落をビルド時に自動チェックする設定が用意されています。
- メニューから Tools > NuGet Package Manager > Package Manager Settings を開く
- 「自動的に不足しているパッケージを確認する(Automatically check for missing packages during build)」にチェックを入れる
- 必要に応じて、パッケージ ソースや復元動作のポリシーも見直す
これにより、xcframework が展開されていない、あるいはバージョンの不整合がある場合でも、より早いタイミングで気付きやすくなります。
クリーン&リビルドをワンセットで実行する習慣
MAUI プロジェクトでは、次のような操作を行った直後に MSB3030 が出やすくなります。
- ターゲット フレームワークの追加・削除(例: net8.0-ios から net9.0-ios へ変更)
- Firebase / Google 関連パッケージのメジャーバージョン アップ
- Xamarin 用ライブラリから MAUI 対応ライブラリへの差し替え
このような変更を加えた直後は、必ず「クリーン ソリューション → ソリューションのリビルド」の流れで一度フル ビルドを行っておくと、安全に状態を揃えることができます。
Firebase iOS SDK と PrivacyInfo.xcprivacy の関係
今回のエラー メッセージでよく見かけるファイル名が、PrivacyInfo.xcprivacy です。これは iOS 17 以降で推奨されている「プライバシー マニフェスト」ファイルで、アプリがどのようなデータを扱い、どのように送信するのかを宣言するためのものです。
Firebase の iOS SDK では、このプライバシー マニフェストが各種 xcframework 内に同梱されており、MAUI プロジェクトで Firebase を参照すると、ビルド時に自動的に取り込まれるようになっています。
ところが、NuGet パッケージの展開がうまくいっていないと、この PrivacyInfo.xcprivacy だけが抜け落ちた状態になり、MSBuild から「ファイルが見つからない」と判定されてしまいます。
手動でファイルを置くよりクリーンアップが優先
一見すると「それなら欠けている PrivacyInfo.xcprivacy を自分でコピーしてきて配置すればよいのでは?」と思いがちですが、これはあまりおすすめできません。
- xcframework の内部構造は SDK のバージョンによって変わることがある
- ビルド スクリプトが想定しているパスと違う場所に置くと、さらに別のエラーを誘発する
- 他の Info.plist や Swift モジュールも同時に欠けている可能性が高い
そのため、欠けたファイルをピンポイントで補うのではなく、「bin / obj の削除」と「NuGet キャッシュのクリア」によって xcframework を丸ごと正しく展開し直す ことが、もっとも安全で再現性の高い解決策になります。
MSB3030 の基本と、今回のケースならではの特徴
ここで一度、MSB3030 そのものの意味を整理しておきます。MSB3030 は、MSBuild の Copy タスクで指定されたファイルが存在しなかった場合に発生する、非常に一般的なエラーです。
典型的には、次のような状況で発生します。
- プロジェクト ファイルで指定したコンテンツ ファイルを、開発者が手動で削除してしまった
- ビルド イベントやカスタム タスクのスクリプトが、古いパスを指している
- 生成コードの出力先が変わったのに、Copy タスクが古い場所を見に行っている
今回の MAUI + Firebase のケースでは、「開発者が何かを消してしまった」というよりも、「NuGet や中間生成物の状態が壊れた結果、MSBuild が期待するパスにファイルが存在しない」というパターンが多いのが特徴です。
そのため、プロジェクト ファイルや csproj の編集に手を入れる前に、まずは次の順序で切り分けることが重要です。
- bin / obj を削除して再ビルド(もっとも効果が高い)
- NuGet キャッシュをクリアして
dotnet restoreを実行 - CI や別マシンでも同じ手順を試し、ローカル固有の問題かどうかを確認
それでも MSB3030 が解消しない場合のチェックリスト
中には、クリーンアップを行っても MSB3030 が残り続けるケースもあります。その場合は、次のポイントを順番に確認してみてください。
対象ファイルが本当に展開されているか確認する
ビルド後、エラー メッセージに出ているパスを元に、実際にファイルが存在するかどうかをエクスプローラーやターミナルで確認します。
cd obj/Release/net9.0-ios
dir /s PrivacyInfo.xcprivacy
ここでファイルが一つも見つからない場合は、やはり NuGet 展開がうまくいっていない可能性が高いです。パッケージのバージョンを一度落としてから再度上げ直す、別プロジェクトを作って同じパッケージを入れ比較する、といったアプローチも有効です。
ターゲット フレームワークの組み合わせを一時的に絞る
マルチターゲットの MAUI プロジェクトでは、TargetFrameworks に複数のフレームワークが指定されています。
<TargetFrameworks>net9.0-android;net9.0-ios</TargetFrameworks>
一時的に iOS のみ、あるいは Android のみなどに絞り、どのターゲットで問題が発生しているか切り分けると原因が見えやすくなります。iOS にだけ MSB3030 が出る場合は、ほぼ xcframework 周りに絞り込めます。
古い Xamarin 用パッケージが混ざっていないか確認する
既存の Xamarin.Forms プロジェクトを MAUI に移行したケースでは、つい「動いているから」と Xamarin 用のパッケージをそのまま参照し続けてしまうことがあります。しかし、これらのパッケージが新しい MAUI / .NET 9 と完全には噛み合わず、ビルド時のパス解決に影響することがあります。
- パッケージ マネージャーで、Xamarin 命名のパッケージが残っていないかチェックする
- MAUI 対応版が存在する場合はそちらに乗り換える
- プロジェクト ファイル(csproj)に直接書かれている参照も確認する
ウイルス対策ソフトやバックアップソフトとの干渉
企業 PC などでセキュリティ製品が強めに設定されている環境では、ビルド中の大量のファイル展開が「怪しい動作」と判定され、一部のファイルだけブロックされることがあります。
その場合は、開発プロジェクトのフォルダーを一時的に除外対象に設定し、開発マシンをオフラインにした状態でクリーン&リビルドを試してみると、状況が改善することがあります。
日常的な運用で意識したい「壊れにくい」プロジェクト管理
MSB3030 のようなエラーは、一度起こると原因特定に時間を取られがちです。日常的な運用の中で、できるだけ「壊れにくい」プロジェクトの扱い方を意識しておくと、トラブルの予防につながります。
- パッケージの大量アップデート前には必ずブランチを切り、必要ならすぐに巻き戻せる状態にしておく
- MAUI や Firebase のメジャーアップデート時には、変更点をまとめて確認し、不要になったパッケージや設定を整理する
- CI のビルド スクリプトにも、定期的なクリーン&キャッシュ削除のステップを組み込む
- 新しい開発者がプロジェクトに参加したときは、「最初に実行すべきクリーン手順」を README などに明記しておく
これらは一見遠回りに見えますが、長期的には「ビルドがよく分からない理由で壊れた」という状況を減らす非常に効果的な投資になります。
まとめ:MSB3030 はまず「中間生成物のリセット」から疑う
.NET MAUI プロジェクトで Firebase や GoogleUtilities を利用しているときに、PrivacyInfo.xcprivacy や Info.plist、Swift モジュールなどが見つからないという MSB3030 が突然出始めることがあります。
しかし多くの場合、その原因はコードやプロジェクト設定ではなく、「壊れた中間生成物」や「不完全な NuGet パッケージ展開」にあります。まずは次の 2 ステップを確実に実行してみてください。
- プロジェクト ルートで bin / obj を削除し、クリーンな状態からビルドし直す
dotnet nuget locals all --clearとdotnet restoreで NuGet キャッシュをリセットする
これで解消するケースは非常に多く、質問者の環境でもこの手順だけでエラーがきれいに消えています。それでも解消しない場合は、ターゲット フレームワークの切り分けや、古い Xamarin パッケージの混入、セキュリティ ソフトとの干渉などを順番に疑っていきましょう。
MSB3030 というメッセージそのものは不親切に見えますが、「ファイルが見つからない=どこかで状態が壊れている」というサインでもあります。焦ってプロジェクト ファイルを書き換える前に、一度立ち止まって「中間生成物をすべて捨ててやり直す」ことから始めてみてください。それが、.NET MAUI 時代の安定したビルド環境への第一歩になります。

コメント