Creation of .xcode.env.local points to a temp file for node when run using yarn
Description
Who this affects: Anyone using a yarn alias to run pod install. This includes expo prebuild.
When using yarn to set up pods, Yarn generates temporary references to node and yarn executables that are not supposed to persist, but RN is capturing them and storing them in .xcode.env.local.
This will actually continue to work for most people, because the files in this temporary dir /var/folders/.../T should only be deleted after 3 days of not accessing them. Source: https://magnusviri.com/what-is-var-folders.html. I took a long weekend and my project broke 😄
Workaround: Delete .xcode.env.local if it exists, and then run bundle exec pod install directly, not using yarn, or run npx expo prebuild if you're using a recent expo project that uses prebuild. This should generate the .xcode.env.local file correctly.
Note: I'm not sure why .xcode.env.local is being generated automatically in the first place. My projects run fine without it present. This is especially painful with Expo CNG, because I can't choose to skip generation of this file, it means I have to avoid using yarn for prebuild, or add a config plugin just to manage .xcode.env.local.
Steps to reproduce
- Have or create an RN app using yarn. Ensure there is no existing
.xcode.env.localfile: a. If this is a new project from template, say no to the cocoapods install when prompted. Runbundle install. b. If this was an existing project, delete theios/.xcode.env.localfile (it will be recreated bypod install). - Add a yarn alias for pod install in package.json:
"scripts": { "pod-install": "cd ios && bundle exec pod install" ... }, - Run the yarn alias:
yarn pod-install. Note thatios/.xcode.env.localhas been created, with a path to NODE_BINARY under/var/folders, like this:export NODE_BINARY=/var/folders/76/2f12v5nx7tq1vqbfptq455l00000gn/T/yarn--1709317581711-0.9959945438201141/node - Try to build the app with
yarn ios. The build will work because the temporary alias to node still exists. However, once the temp file is deleted, builds will start failing. - Delete the temp file referenced in
.xcode.env.local.
React Native Version
0.73.5.
Affected Platforms
Runtime - iOS, Build - MacOS
Output of npx react-native info
System:
OS: macOS 14.3.1
CPU: (8) arm64 Apple M1
Memory: 73.97 MB / 16.00 GB
Shell:
version: "5.9"
path: /bin/zsh
Binaries:
Node:
version: 20.9.0
path: ~/.nvm/versions/node/v20.9.0/bin/node
Yarn:
version: 1.22.21
path: ~/.nvm/versions/node/v20.9.0/bin/yarn
npm:
version: 10.1.0
path: ~/.nvm/versions/node/v20.9.0/bin/npm
Watchman:
version: 2024.01.22.00
path: /opt/homebrew/bin/watchman
Managers:
CocoaPods: Not Found
SDKs:
iOS SDK:
Platforms:
- DriverKit 23.2
- iOS 17.2
- macOS 14.2
- tvOS 17.2
- visionOS 1.0
- watchOS 10.2
Android SDK: Not Found
IDEs:
Android Studio: 2023.1 AI-231.9392.1.2311.11330709
Xcode:
version: 15.2/15C500b
path: /usr/bin/xcodebuild
Languages:
Java:
version: 17.0.10
path: /Users/lizzi/.jenv/shims/javac
Ruby:
version: 2.6.10
path: /Users/lizzi/.rbenv/shims/ruby
npmPackages:
"@react-native-community/cli": Not Found
react:
installed: 18.2.0
wanted: 18.2.0
react-native:
installed: 0.73.5
wanted: 0.73.5
react-native-macos: Not Found
npmGlobalPackages:
"*react-native*": Not Found
Android:
hermesEnabled: true
newArchEnabled: false
iOS:
hermesEnabled: true
newArchEnabled: false
Stacktrace or Logs
The following build commands failed:
PhaseScriptExecution [CP-User]\ [Hermes]\ Replace\ Hermes\ for\ the\ right\ configuration,\ if\ needed /Users/lizzi/Library/Developer/Xcode/DerivedData/TodoSharer-bpdgubyufiaiekcndqxujflhqusl/Build/Intermediates.noindex/Pods.build/Debug-iphonesimulator/hermes-engine.build/Script-46EB2E0001C8A0.sh (in target 'hermes-engine' from project 'Pods')
(1 failure)
log file says this:
1099 Node found at: /var/folders/2d/_8p7fdvj1v13vkh7wyrbk14h0000gn/T/yarn--1707870956680-0.647996518200334/node
1100 /Users/lizzi/Library/Developer/Xcode/DerivedData/TodoSharer-bpdgubyufiaiekcndqxujflhqusl/Build/Intermediates.noindex/Pods.build/Debug-iphonesimulator/hermes-engine.build/Scri pt-46EB2E0001C8A0.sh: line 9: /var/folders/2d/_8p7fdvj1v13vkh7wyrbk14h0000gn/T/yarn--1707870956680-0.647996518200334/node: No such file or directory
1101 Command PhaseScriptExecution failed with a nonzero exit code
Reproducer
https://github.com/lindboe/temp-node-reproducer
Screenshots and Videos
No response
| :warning: | Add or Reformat Version Info |
|---|---|
| :information_source: | We could not find or parse the version number of React Native in your issue report. Please use the template, and report your version including major, minor, and patch numbers - e.g. 0.70.2 |
I discovered this and described the earlier issue https://github.com/facebook/react-native/issues/39903#issuecomment-1960239150, backlinking for posterity
I have also come across this issue. Have found if you run the below command before you run expo prebuild or your yarn alias, it will generate the file with the path to the NODE_BINARY correctly, and the RN pod install process won't overwrite it.
echo "export NODE_BINARY=$(printf '%q' "$(node -e 'console.log(process.execPath)')")" > ./ios/.xcode.env.local
so for example you can do
"pod-install": "./createXcodeEnvLocalFile.sh && cd ios && bundle exec pod install"
(you will probably need to do rm ./ios/.xcode.env.local first)
This is super weird, we don't have anything in the react-native repo that can generate that file. Looking at this search.
What we do is to create the .xcode.env if it does not exists yet, but not the .local.
But this is unrelated from yarn. It does that for any project when pod install is used the first time.
Does it happens also in non-expo apps?
This is super weird, we don't have anything in the react-native repo that can generate that file. Looking at this search.
What we do is to create the
.xcode.envif it does not exists yet, but not the.local.But this is unrelated from yarn. It does that for any project when pod install is used the first time.
Does it happens also in non-expo apps?
Hi @cipolleschi, this PR added it in I believe https://github.com/facebook/react-native/pull/38879. The specific line in the main branch for react-native is here https://github.com/facebook/react-native/blob/main/packages/react-native/scripts/cocoapods/utils.rb#L230
I can confirm it also happens in non-expo apps.
(I assume this is it, sorry if not)
Ah, yeah, 🤦 I haven't read properly the second part.
anyway... I think that it is safe to keep it, it has resolved so many issues that users opened because their environment was wrong.
I think that the proper solution is to generate a .xcode.env.local which is stable, i.e.: it is not using what is generated by yarn in the temporary folder.
I'll try to reproduce the issue and find a way to fix-forward.
Ah, yeah, 🤦 I haven't read properly the second part.
anyway... I think that it is safe to keep it, it has resolved so many issues that users opened because their environment was wrong.
I think that the proper solution is to generate a
.xcode.env.localwhich is stable, i.e.: it is not using what is generated by yarn in the temporary folder.I'll try to reproduce the issue and find a way to fix-forward.
Not sure if a combination of my solution would work, e.g something like:
if !file_manager.exist?("#{file_path}.local")
node_binary = `printf '%q' "$(node -e 'console.log(process.execPath)')"`
system("echo 'export NODE_BINARY=#{node_binary}' > #{file_path}.local")
end
I'm not particuarly well-versed in Ruby so not sure if running the inline executable node command would work. But process.execPath appears to be the correct path to the actual node executable, when running through yarn (on my machine and my colleagues machines, at least).
I would be happy to try and work on this and contribute back to RN. However I'm unsure how to test this.
Hi,
I would like to share my experience on that file I have a project on react native and sometimes I encounter an error and my app wont start building or running on my emulator. I just delete the file and after that my app runs on the emulator. I'm just using this "pods": "cd ios && rm -rf Podfile.lock && pod deintegrate && pod install && rm -rf .xcode.env.local", by running yarn pods or npm run pods every time I need to update my pod file. I hope it helps you guys. Thank you.
I'm using this in my package.json to workaround this issue
{
"scripts": {
"pods": "PATH=$(echo $PATH | sed 's/[^:]*://'); cd ios; pod install"
}
}
Another workaround for those using expo is to change your package.json as follows:
{
...
"scripts": {
...
"ios": "yarn expo prebuild; rm ios/.xcode.env.local; echo \"export NODE_BINARY=$(printf '%s' \"$(node -e 'console.log(process.execPath)')\")\" > ./ios/.xcode.env.local; yarn expo run:ios",
...
}
...
}