Environment
System:
OS: macOS 27.0.1
Binaries:
Node: 24.18.0
pnpm: 11
IDEs:
Xcode: 27.0/27A266a
npmPackages:
"@react-native-community/cli-platform-apple": 20.2.0
react-native: 0.85
The bug does not depend on the Xcode version; the relevant code is unchanged on main (21.0.0-alpha.1).
Description
run-ios --buildFolder <dir> builds into <dir> but installs the app from Xcode's default DerivedData.
buildProject passes the folder to the build as -derivedDataPath <dir>. After the build, installApp resolves the app through getBuildSettings, which runs xcodebuild … -showBuildSettings -json without -derivedDataPath. TARGET_BUILD_DIR therefore points into ~/Library/Developer/Xcode/DerivedData/<Project>-<hash>/… and not into <dir>. As a result:
-
If the default DerivedData holds an older build of the project (for example from an Xcode IDE build), the CLI installs and launches that stale .app without any warning.
-
If it holds no build, the command fails after success Successfully built the app:
UnhandledPromiseRejection: … The promise rejected with the reason "Error: target build directory /Users/…/Library/Developer/Xcode/DerivedData/<Project>-<hash>/Build/Products/Debug-iphonesimulator does not exist".
The same applies to runOnDevice (physical device and Mac Catalyst) and to openApp (macOS), because they all go through getBuildSettings.
--binary-path does not work around this: it skips the build and passes buildOutput: '', so getBuildSettings throws on getPlatformName('') (#2517).
Code references on main:
packages/cli-platform-apple/src/commands/buildCommand/buildProject.ts adds -derivedDataPath from args.buildFolder.
packages/cli-platform-apple/src/commands/runCommand/getBuildSettings.ts builds the -showBuildSettings call without it.
runOnSimulator.ts, runOnDevice.ts and createRun.ts (macOS) do not pass args.buildFolder to installApp / openApp / getBuildSettings.
Related: createRun calls process.chdir(sourceDir) (the ios/ directory) before building, so a relative --buildFolder resolves against ios/ and not the project root. The option description does not say which directory it is relative to.
Proposed fix: thread buildFolder from the run paths into getBuildSettings and append -derivedDataPath <buildFolder> to the -showBuildSettings call when it is set. I applied this as a local patch on 20.2.0: run-ios --buildFolder build/DerivedData then installs and launches the freshly built app from ios/build/DerivedData/Build/Products/Debug-iphonesimulator/. PR to follow.
Reproducible Demo
- In any React Native project, make sure the default DerivedData has no build for it:
rm -rf ~/Library/Developer/Xcode/DerivedData/<Project>-*.
- Run
npx react-native run-ios --buildFolder build/DerivedData.
- The build succeeds into
ios/build/DerivedData, then the CLI fails with target build directory …/Library/Developer/Xcode/DerivedData/<Project>-<hash>/Build/Products/Debug-iphonesimulator does not exist.
Expected: the CLI installs and launches the app it just built in ios/build/DerivedData.
Environment
The bug does not depend on the Xcode version; the relevant code is unchanged on
main(21.0.0-alpha.1).Description
run-ios --buildFolder <dir>builds into<dir>but installs the app from Xcode's default DerivedData.buildProjectpasses the folder to the build as-derivedDataPath <dir>. After the build,installAppresolves the app throughgetBuildSettings, which runsxcodebuild … -showBuildSettings -jsonwithout-derivedDataPath.TARGET_BUILD_DIRtherefore points into~/Library/Developer/Xcode/DerivedData/<Project>-<hash>/…and not into<dir>. As a result:If the default DerivedData holds an older build of the project (for example from an Xcode IDE build), the CLI installs and launches that stale
.appwithout any warning.If it holds no build, the command fails after
success Successfully built the app:The same applies to
runOnDevice(physical device and Mac Catalyst) and toopenApp(macOS), because they all go throughgetBuildSettings.--binary-pathdoes not work around this: it skips the build and passesbuildOutput: '', sogetBuildSettingsthrows ongetPlatformName('')(#2517).Code references on
main:packages/cli-platform-apple/src/commands/buildCommand/buildProject.tsadds-derivedDataPathfromargs.buildFolder.packages/cli-platform-apple/src/commands/runCommand/getBuildSettings.tsbuilds the-showBuildSettingscall without it.runOnSimulator.ts,runOnDevice.tsandcreateRun.ts(macOS) do not passargs.buildFoldertoinstallApp/openApp/getBuildSettings.Related:
createRuncallsprocess.chdir(sourceDir)(theios/directory) before building, so a relative--buildFolderresolves againstios/and not the project root. The option description does not say which directory it is relative to.Proposed fix: thread
buildFolderfrom the run paths intogetBuildSettingsand append-derivedDataPath <buildFolder>to the-showBuildSettingscall when it is set. I applied this as a local patch on 20.2.0:run-ios --buildFolder build/DerivedDatathen installs and launches the freshly built app fromios/build/DerivedData/Build/Products/Debug-iphonesimulator/. PR to follow.Reproducible Demo
rm -rf ~/Library/Developer/Xcode/DerivedData/<Project>-*.npx react-native run-ios --buildFolder build/DerivedData.ios/build/DerivedData, then the CLI fails withtarget build directory …/Library/Developer/Xcode/DerivedData/<Project>-<hash>/Build/Products/Debug-iphonesimulator does not exist.Expected: the CLI installs and launches the app it just built in
ios/build/DerivedData.