Note: After further testing, we determined that simply updating ninja.exe bypasses the path length issue (as well as enabling long paths using the PowerShell command below). However, following these steps and using this code will reduce warnings in the terminal when building a React Native / Expo / Android app on Windows.
Android/React Native uses Ninja when it has to build native C/C++ code.
The Android build is coordinated by Gradle, but Gradle does not directly compile all the C/C++ itself. Instead, the Android Gradle Plugin invokes CMake for native builds. CMake then generates build files for a lower-level build tool. On Android, that tool is commonly Ninja.
ninja.exe does not support paths longer than 260 characters well enough for our team’s Android build on Windows.
I adapted this fix for our team at TechJoy Software using ChatGPT Codex: Filename longer than 260 characters Error on React Native Fabric ยท Issue #424 ยท AppAndFlow/react-native-safe-area-context
I adapted the fix because our project’s Android build files are not checked into git and are regenerated / change every build. With ChatGPT Codex, I created an Expo plugin that reads the ninja path from an .env variable and updates the Android Gradle file.
Android build files can be regenerated, overwritten, or changed by prebuild, which is why creating an Expo plugin was the right choice.
Here was the code adapted from the GitHub answer as well as generated with Codex.
const { withAppBuildGradle } = require("@expo/config-plugins");
const NINJA_PATH_ENV_VAR = "CMAKE_NINJA_PATH";
function getNinjaPath() {
const ninjaPath = process.env[NINJA_PATH_ENV_VAR]?.trim();
if (!ninjaPath) {
throw new Error(
`Missing ${NINJA_PATH_ENV_VAR}. Add ${NINJA_PATH_ENV_VAR}=<path-to-ninja.exe> to your .env file.`,
);
}
return ninjaPath.replace(/\\/g, "/");
}
function getExternalNativeBuildBlock(ninjaPath) {
return `
externalNativeBuild {
cmake {
arguments "-DCMAKE_MAKE_PROGRAM=${ninjaPath}", "-DCMAKE_OBJECT_PATH_MAX=1024"
}
}`;
}
const MANAGED_EXTERNAL_NATIVE_BUILD_PATTERN =
/\n\s{8}externalNativeBuild\s*\{\s*\n\s{12}cmake\s*\{\s*\n\s{16}arguments\s+"-D(?:CMAKE_MAKE_PROGRAM=[^"]+|CMAKE_OBJECT_PATH_MAX=\d+)"(?:,\s+"-D(?:CMAKE_MAKE_PROGRAM=[^"]+|CMAKE_OBJECT_PATH_MAX=\d+)")?\s*\n\s{12}\}\s*\n\s{8}\}/g;
const BUILD_STAGING_DIRECTORY_BLOCK_PATTERN =
/\n\s{4}externalNativeBuild\s*\{\s*\n\s{8}cmake\s*\{\s*\n\s{12}buildStagingDirectory\s+file\([^)]*\)\s*\n\s{8}\}\s*\n\s{4}\}/g;
function withCmakeObjectPathMax(config) {
if (process.platform !== "win32") {
return config;
}
return withAppBuildGradle(config, (config) => {
const ninjaPath = getNinjaPath();
if (config.modResults.language !== "groovy") {
throw new Error(
"with-cmake-object-path-max only supports Groovy app build.gradle files.",
);
}
let contents = config.modResults.contents
.replace(MANAGED_EXTERNAL_NATIVE_BUILD_PATTERN, "")
.replace(BUILD_STAGING_DIRECTORY_BLOCK_PATTERN, "");
const releaseLevelField =
/(\n\s*buildConfigField "String", "REACT_NATIVE_RELEASE_LEVEL", "[^\n]+")/;
if (!releaseLevelField.test(contents)) {
throw new Error(
"Could not find REACT_NATIVE_RELEASE_LEVEL in android/app/build.gradle.",
);
}
contents = contents.replace(
releaseLevelField,
`$1${getExternalNativeBuildBlock(ninjaPath)}`,
);
config.modResults.contents = contents;
return config;
});
}
module.exports = withCmakeObjectPathMax;
Adapted steps for our team:
- Download the Latest Version of Ninja:
- Download the latest Ninja release from here.
- Replace the existing
ninja.exein$SDK_PATH$\cmake\$CMAKE_VERSION$\binwith the newly downloaded version. Note: you can verify the existing version of ninja by runningninja.exe --version(or the right filename) in thebinfolder.
- Update / add a line to
.envwith the right path to ninja. For example, this is what I use on my system.CMAKE_NINJA_PATH=C:/Users/javer/AppData/Local/Android/Sdk/cmake/3.22.1/bin/ninja.exe - Enable Long Path Support in Windows:
- Run the following PowerShell command to enable long path support in Windows. This will allow Windows to support file paths longer than 260 characters.
New-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem" -Name "LongPathsEnabled" -Value 1 -PropertyType DWORD -Force
Leave a Reply