- Windows React Native APK パス制限の解決方法 -
1. 概要
Windows で Expo CNG ベースの React Native アプリの Android APK ビルドが、次のように失敗することがあります。
ninja: error: Stat(...): Filename longer than 260 characters
この問題はアプリコードの問題ではなく、Windows のパス長制限と CMake/Ninja のネイティブビルド成果物のパス構造によって発生します。
推奨される解決方法は次の 3 つです。
-
プロジェクトルートに Junctionを作成してビルドの実行パスを短くする。
-
CMake の buildStagingDirectoryを短い絶対パスに移動する。
-
既存の .cxx キャッシュを削除してから、全体を再構成する。
Junction 생성 → buildStagingDirectory 지정 → android/app/.cxx 삭제 → 재빌드
subst 仮想ドライブはパスを短くできますが、Metro・realpath・Gradle キャッシュのパスが混在して別の問題を引き起こす可能性があるため、使用しません。
2. 原因
Windows の一般的な Win32 パス長制限は MAX_PATH、つまり 260 文字です。Windows の Long Path 設定を有効にしても、実際にその機能を使用できるよう準備されていないツールは、依然として長いパスで失敗することがあります。
React Native の New Architecture や自動リンクされたネイティブモジュールは、CMake と Ninja を通じて C++ コードをビルドします。このとき、オブジェクトファイルのパスが非常に長くなることがあります。
<빌드 스테이징 경로>/<빌드 타입>/<해시>/<ABI>/
<target>_autolinked_build/CMakeFiles/<target>.dir/
<원본 소스 경로를 포함한 경로>
特に node_modules 以下の長い C++ ソースパスが、オブジェクトファイルのパスに再び含まれます。プロジェクトのパスが深く、 react-native-screens、 safe-area-context のようなネイティブパッケージが追加されると、260 文字を簡単に超えてしまいます。
次は、ステージング場所による最長オブジェクトファイルパスの例です。
|
ビルドパス |
最長オブジェクトパス |
結果 |
|---|---|---|
|
通常のプロジェクトパス + デフォルトの .cxx |
331 文字 |
失敗 |
|
Junction パス + デフォルトの .cxx |
290 文字 |
失敗 |
|
Junction パス + 短いステージングパス |
248 文字 |
成功 |
プロジェクトルートだけを短くするだけでは不十分で、CMake の中間成果物の場所も短くする必要があります。
3. 適用方法
3.1 Junction の作成
プロジェクトが長いパスにある場合は、モノレポのルートを短いパスに Junction として接続します。
cmd /c mklink /J C:\v "C:\Users\<사용자>\<긴 경로>\<프로젝트 루트>"
以後、ネイティブビルドは Junction パスから実行します。
C:\v\<프로젝트 경로>
Junction は同じボリューム上の実ディレクトリエントリとして動作します。 substのように仮想ドライブのルートが別途作成される方式よりも、ファイルシステムのパス解決が一貫しています。
3.2 CMake ステージングパスの短縮
android/app/build.gradle の android {} ブロックに以下の設定を追加します。
externalNativeBuild {
cmake {
buildStagingDirectory = file("C:/cxx-build")
}
}
buildStagingDirectoryは、CMake の外部ネイティブビルド成果物と Ninja 関連ファイルが生成される場所を指定します。デフォルトの.cxxパスの代わりに短いルートパスを使用して、オブジェクトファイル全体の長さを短縮します。
3.3 既存の CMake キャッシュを削除
パス設定を変更した後は、既存のキャッシュを必ず削除します。
rm -rf android/app/.cxx
Windows PowerShell では、以下のように実行できます。
Remove-Item -Recurse -Force android\app\.cxx
CMake キャッシュには、初回構成時の正規パスが保存されることがあります。キャッシュを削除しないと、Junction と短いステージングパスを適用しても、以前の長いパスが引き続き使用される可能性があります。
3.4 ビルドの実行
ネイティブビルドは Junction パスから実行します。
.\gradlew.bat assembleRelease --max-workers=2
リリースビルドの前には、Metro と複数の Web 開発サーバーを終了することを推奨します。メモリ競合によって Gradle Worker Daemon エラーが発生する可能性があるためです。
4. 運用原則と注意事項
subst ではなく Junction を使用する
substはパスを短いドライブ文字にマッピングできますが、仮想ドライブのパスと実際のC:パスが併用されると、以下の問題が発生する可能性があります。
-
Codegen で異なるルートパスのエラーが発生する
-
Metro でワークスペースパッケージまたは alias の解決に失敗する
-
Gradle のグローバルキャッシュに保存された正規パスと競合する
-
再起動後にマッピングが消えるため、毎回再設定が必要になる
したがって、パス短縮の目的には Junction を使用します。
Metro は正規パスから実行する
ネイティブ Gradle ビルドは Junction パスから実行しますが、Metro は正規のプロジェクトパスから実行します。
|
作業 |
実行パス |
|---|---|
|
ネイティブ C++ ビルド (gradlew, expo run:android) |
Junction パス |
|
Metro バンドラー (expo start) |
正規の C: パス |
一部の Expo/React Native プロジェクトは TypeScript paths、Babel または Metro の設定に基づく alias と、ワークスペースパッケージの解決に依存しています。Metro を Junction パスから実行すると、プロジェクトルートとファイルの realpath が一致せず、alias またはワークスペースパッケージの解決に問題が発生する可能性があります。
Expo CNG によって生成された成果物であることを認識する
android/フォルダーは Expo CNG が生成する成果物です。expo prebuild --cleanを実行すると、android/app/build.gradleに直接追加したbuildStagingDirectory設定が消える可能性があります。
この設定は Windows のローカルビルドにおける中間成果物のパスだけを変更し、APK の成果物には影響しません。したがって、Windows でネイティブビルドを担当する人が手動で適用する方法で運用できます。
長期的に自動化が必要な場合は、Windows ユーザーだけが選択的に値を提供できるように、Gradle Property ベースの opt-in 方式を検討します。絶対パスを Config Plugin ですべての OS と EAS ビルドに強制的に注入してはいけません。
5. 開発環境とデプロイの区分
Java と Android Studio
Android Studio でandroid/プロジェクトを開いたときに Gradle Sync が失敗する場合は、そのプロジェクトの Gradle Wrapper・Android Gradle Plugin・Kotlin プラグインの組み合わせと、JDK バージョンの互換性を確認します。
プロジェクトで検証済みのJDKバージョンをGradle JDKとして使用します。たとえばJava 21を使用する環境では、次のように設定できます。
$env:JAVA_HOME = "C:\Program Files\Microsoft\jdk-21"
$env:ANDROID_HOME = "C:\Users\<사용자>\AppData\Local\Android\Sdk"
Android Studioの android/ フォルダーは永続的なソースではなく、CNGの生成物です。Android StudioはネイティブログとGradleの状態を確認するために使用し、保持する必要がある設定は app.json またはConfig Pluginに配置します。
デバッグAPKとリリースAPK
|
区分 |
デバッグ |
リリース |
|---|---|---|
|
JSバンドル |
Metroからリアルタイムで読み込み |
APK内部に含める |
|
実行条件 |
開発PCのMetroへのアクセスが必要 |
単独で実行可能 |
|
使用目的 |
ローカル開発・デバッグ |
同僚・テスターへの共有 |
|
ビルド時間 |
比較的短い |
すべてのABIを含めるため長くなる場合がある |
APKの生成物は通常、以下のパスで確認できます。
android/app/build/outputs/apk/debug/app-debug.apk
android/app/build/outputs/apk/release/app-release.apk
ハイブリッドアプリでは、大半の画面をWebViewでサーバーから読み込む場合が多くあります。
-
Web画面の変更:Webをデプロイした後、アプリを完全に終了して再起動する
-
RNシェルの変更:タブバー、ディープリンク、ブリッジ、ネイティブSDKなどは、APKの再ビルドと再インストールが必要
Justin