react-native icon indicating copy to clipboard operation
react-native copied to clipboard

NODE_BINARY in .xcode.env not working

Open MicahDavid opened this issue 1 year ago • 30 comments

Description

I would like to use the .xcode.env to set my node version. My .xcode.env looks like:

export NODE_BINARY=$(command -v node)

When I execute this command in a terminal window, it returns the proper node version. I've tested, and the only way I can set the node version is using Build Phases -> Bunde React Native Code and Images -> and exporting NODE_BINARY in the shell commands there to the absolute path:

export NODE_BINARY=/Users/myuser/.nvm/versions/node/v14.18.1/bin/node

Can anyone suggest why NODE_BINARY is not being set through the .xcode.env file? Do I have to take any extra steps to use this during archive?

Version

0.70.4

Output of npx react-native info

System: OS: macOS 12.6 CPU: (12) x64 Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz Memory: 23.84 MB / 32.00 GB Shell: 3.2.57 - /bin/bash Binaries: Node: 14.18.1 - ~/.nvm/versions/node/v14.18.1/bin/node Yarn: 1.22.18 - ~/.nvm/versions/node/v14.18.1/bin/yarn npm: 6.14.15 - ~/.nvm/versions/node/v14.18.1/bin/npm Watchman: 2022.03.21.00 - /usr/local/bin/watchman Managers: CocoaPods: 1.11.3 - /Users/micahsklut/.rbenv/shims/pod SDKs: iOS SDK: Platforms: DriverKit 22.2, iOS 16.2, macOS 13.1, tvOS 16.1, watchOS 9.1 Android SDK: API Levels: 29, 30, 31 Build Tools: 29.0.2, 30.0.2, 30.0.3, 31.0.0 System Images: android-29 | Intel x86 Atom_64, android-29 | Google APIs Intel x86 Atom_64, android-30 | Google APIs Intel x86 Atom Android NDK: Not Found IDEs: Android Studio: 2021.3 AI-213.7172.25.2113.9123335 Xcode: 14.2/14C18 - /usr/bin/xcodebuild Languages: Java: 1.8.0_292 - /usr/bin/javac npmPackages: @react-native-community/cli: Not Found react: 18.1.0 => 18.1.0 react-native: ^0.70.4 => 0.70.6 react-native-macos: Not Found npmGlobalPackages: react-native: Not Found

Steps to reproduce

Run Archive. The system node is being used, unless I set it as explained above.

Snack, code example, screenshot, or link to a repository

Screen Shot 2022-12-15 at 6 29 09 PM

MicahDavid avatar Dec 15 '22 23:12 MicahDavid

in my case it was NVM. Either let nvm go or reconfigure it In your build phases scripts

if [[ -s "$HOME/.nvm/nvm.sh" ]]; then
. "$HOME/.nvm/nvm.sh"
elif [[ -x "$(command -v brew)" && -s "$(brew --prefix nvm)/nvm.sh" ]]; then
. "$(brew --prefix nvm)/nvm.sh"
fi

codesalley avatar Dec 16 '22 13:12 codesalley

In my case I had to add export NODE_BINARY=$(command -v node)\n to the PODS build phases script tail, .xcode.env seemed to make no difference

shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n    # print error to STDERR\n    echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n    exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\nexport NODE_BINARY=$(command -v node)\n";

Running react-native": "0.69.7" on arm64

jaimeagudo avatar Feb 01 '23 09:02 jaimeagudo

Apparently this is caused by nvm A less invasive workaround (that breaks nvm):

ln -s $(which node) /usr/local/bin/node

jaimeagudo avatar Feb 03 '23 17:02 jaimeagudo

nvm is common enough that I would suggest this should work out of the box.

djMax avatar Apr 27 '23 11:04 djMax

Loading nvm from within .xcode.env seems to resolve this for me:

export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm

export NODE_BINARY=$(command -v node)

badsyntax avatar Jul 14 '23 17:07 badsyntax

In my Xcode build logs show me this error:

../node_modules/react-native/scripts/xcode/with-environment.sh: line 35: node: command not found

But after errors, show "Now using node v20.7.0." and this happen too with Upload Debug Symbols to Sentry build phase. I'm using Xcode 14.3.1 and RN v0.69.12. Everything works on terminal (iTerm + zsh)

lucianomlima avatar Oct 07 '23 00:10 lucianomlima

The problem is that Xcode scripts works in a different environment than a regular terminal/ Xcode also overrides some basic ENV var that can shadow and mask other variables we might set.

If you don't have node in the default PATHs, like /usr/local/bin, for example, Xcode is not able to find it. A simple solution could be to create a symlink to node in /usr/local/bin:

sudo ln -s $(command -v node) /usr/local/bin/node

We are investigating better way to handle this, but we haven't found a robust approach yet, unfortunately. :(

cipolleschi avatar Oct 07 '23 09:10 cipolleschi

The problem is that Xcode scripts works in a different environment than a regular terminal/ Xcode also overrides some basic ENV var that can shadow and mask other variables we might set.

If you don't have node in the default PATHs, like /usr/local/bin, for example, Xcode is not able to find it. A simple solution could be to create a symlink to node in /usr/local/bin:

sudo ln -s $(command -v node) /usr/local/bin/node

We are investigating better way to handle this, but we haven't found a robust approach yet, unfortunately. :(

In my case, Xcode can find node (using the ,export NVM_DIR=path/to/.nvm approach) but can't find command, that is a built-in shell library. Sounds weird.

lucianomlima avatar Oct 08 '23 15:10 lucianomlima

@lucianomlima yeah, that's definitely very weird. Can you try add a script phase after building just calling which command? :/

cipolleschi avatar Oct 09 '23 13:10 cipolleschi

which command shows me : command: shell built-in command but I do some tests and I realize that nothing going work with Xcode build and .xcode.env. Now my .xcode.env is:

export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" --no-use

nvm use default # I need to put this because when use nvm current returns none

export NODE_BINARY=$NVM_DIR/versions/node/v20.7.0/bin/node

echo $NVM_DIR # Prints /Users/luciano.lima/.nvm
echo $NODE_BINARY # Prints /Users/luciano.lima/.nvm/versions/node/v20.7.0/bin/node

And, on Xcode log, I have these messages:

Now using node v20.7.0 (npm v10.1.0)
/Users/luciano.lima/.nvm # echo $NVM_DIR
/Users/luciano.lima/.nvm/versions/node/v20.7.0/bin/node # echo $NODE_BINARY
Node found at: /Users/luciano.lima/.nvm/versions/node/v20.7.0/bin/node

And some time later:

+ type node
+ echo 'error: node not found! Modules won'\''t be collected.' 'Please export NODE_BINARY in '\''Build Phase'\'' - '\''Bundle React Native code and images'\''' 'to an absolute path of your node binary. Check your node path by '\''which node'\''.'
error: node not found! Modules won't be collected. Please export NODE_BINARY in 'Build Phase' - 'Bundle React Native code and images' to an absolute path of your node binary. Check your node path by 'which node'.
+ exit 0
Command PhaseScriptExecution emitted errors but did not return a nonzero exit code to indicate failure

So, even using an absolute path to NODE_BINARY, build script phase fails.

The only way that make things works is with symlink like @cipolleschi suggests. Now my .xcode.env have only this:

export NODE_BINARY=/usr/local/bin/node

And now finally works. 🤷

lucianomlima avatar Oct 09 '23 23:10 lucianomlima

From which script phase the message:

+ type node
+ echo 'error: node not found! Modules won'\''t be collected.' 'Please export NODE_BINARY in '\''Build Phase'\'' - '\''Bundle React Native code and images'\''' 'to an absolute path of your node binary. Check your node path by '\''which node'\''.'
error: node not found! Modules won't be collected. Please export NODE_BINARY in 'Build Phase' - 'Bundle React Native code and images' to an absolute path of your node binary. Check your node path by 'which node'.
+ exit 0
Command PhaseScriptExecution emitted errors but did not return a nonzero exit code to indicate failure

arrives? I have no memory of any of our scripts emitting that message! Could it be a third party library? The problem is likely that that script is not using loading the with-environment.sh script that is responsible to load the .xcode.env. Without loading that, it is expected not to find the ENV vars.

cipolleschi avatar Oct 11 '23 13:10 cipolleschi

It's from @sentry/react-native and my script build phase is

export SENTRY_PROPERTIES=sentry.properties
export EXTRA_PACKAGER_ARGS="--sourcemap-output $DERIVED_FILE_DIR/main.jsbundle.map"
set -e

WITH_ENVIRONMENT="../node_modules/react-native/scripts/xcode/with-environment.sh"
REACT_NATIVE_XCODE="../node_modules/react-native/scripts/react-native-xcode.sh"
SENTRY_CLI="../node_modules/@sentry/cli/bin/sentry-cli"

/bin/sh -c "$WITH_ENVIRONMENT \"$SENTRY_CLI react-native xcode $REACT_NATIVE_XCODE\""
/bin/sh ../node_modules/@sentry/react-native/scripts/collect-modules.sh

Maybe the last line is where the problem is? I'll try to add WITH_ENVIRONMENT to it.

lucianomlima avatar Oct 11 '23 15:10 lucianomlima

i think i'm getting a similar issue

Node found at: /opt/homebrew/bin/node
/Users/adamwright/Documents/Development/AB3MobileUpgrade/AB3MobileUpgrade/ios/Pods/../../node_modules/react-native/React/FBReactNativeSpec/../../scripts/react_native_pods_utils/script_phases.sh: line 34: /opt/homebrew/bin/node: No such file or directory
Command PhaseScriptExecution failed with a nonzero exit code

My .xcode.env is

# This `.xcode.env` file is versioned and is used to source the environment
# used when running script phases inside Xcode.
# To customize your local environment, you can create an `.xcode.env.local`
# file that is not versioned.
# NODE_BINARY variable contains the PATH to the node executable.
#
# Customize the NODE_BINARY variable here.
# For example, to use nvm with brew, add the following line
# . "$(brew --prefix nvm)/nvm.sh" --no-use
export NODE_BINARY=$(command -v node)export NODE_BINARY=/opt/homebrew/bin/node

but my node path when running which node is - /usr/local/bin/node

How can i fix this?

adamjw3 avatar Oct 14 '23 13:10 adamjw3

Hey @adamjw3! Your Xcode env has 2 export NODE_BINARY on the same line. That would not work.

You should have either

export NODE_BINARY=$(command -v node)

Or

export NODE_BINARY=/usr/local/bin/node

cipolleschi avatar Oct 14 '23 17:10 cipolleschi

@cipolleschi thanks, they are on two lines in the file and it was auto generated like that! i commented out

export NODE_BINARY=$(command -v node)

and updated the other with my node path

export NODE_BINARY=/usr/local/bin/node

project now builds

Thanks

adamjw3 avatar Oct 15 '23 17:10 adamjw3

I am using RN version 0.72.3, which can run, package and flash back. I feel that it is the reason for switching to the default version with NVM. I have added a script here, and switching to 20 or above is normal. It should be 18, but our team is using 20, so switching to 20 is necessary image

export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm

nvm use 20

export NODE_BINARY=node
../node_modules/react-native/scripts/react-native-xcode.sh

jswangtao avatar Oct 18 '23 03:10 jswangtao

What worked for us was to get the NVM directory: export NODE_BINARY=$HOME/.nvm/nodes/versions/v18.0.0/bin/node

We have NVM setup in our README so could reasonably expect local devs to have that set, and doesn't to explicitly state the node version. Then, it runs same locally and on CircleCi.

banane avatar Nov 28 '23 21:11 banane

The problem is that Xcode scripts works in a different environment than a regular terminal/ Xcode also overrides some basic ENV var that can shadow and mask other variables we might set.

If you don't have node in the default PATHs, like /usr/local/bin, for example, Xcode is not able to find it. A simple solution could be to create a symlink to node in /usr/local/bin:

sudo ln -s $(command -v node) /usr/local/bin/node

We are investigating better way to handle this, but we haven't found a robust approach yet, unfortunately. :(

This analysis is correct. I solved this problem by completely uninstalling node and then downloading the .pkg installation from the node.js ,because the installation location of the installation package is /usr/local/bin/node by default.

aTreey avatar Jan 29 '24 09:01 aTreey

Just adding more info in case it's helpful. I'm using Homebrew and this is happening too, right after downgrading from node 20 to node 18. Not using Expo, RN 0.70.6. Here are some of the xcode logs when the error occurs:

...Desktop/Inventory/ios/Pods/../../node_modules/react-native/React/FBReactNativeSpec/../../scripts/xcode/with-environment.sh: line 35: .xcode.env: command not found .../Desktop/Inventory/ios/Pods/../../node_modules/react-native/React/FBReactNativeSpec/../../scripts/xcode/with-environment.sh: line 35: node: command not found [Warning] You need to configure your node path in the environment. You can set it up quickly by running: echo 'export NODE_BINARY=' > .xcode.env in the ios folder. This is needed by React Native to work correctly. We fallback to the DEPRECATED behavior of finding . This will be REMOVED in a future version. You can read more about this here: https://reactnative.dev/docs/environment-setup#optional-configuring-your-environment [Error] Could not find node. It looks like that the .xcode.env or .xcode.env.local Command PhaseScriptExecution failed with a nonzero exit code

I have .xcode.env inside my ios folder with the line: export NODE_BINARY=$(command -v node). command -v node prints out the correct path(/opt/homebrew/opt/node@18/bin/node). Switching out $(command -v node) with that path works.

I get now that Xcode runs in a different environment that doesn't have access to variables that the terminal has, but it was working before I changed the node version, and that is all I changed, so it seems weird that it suddenly wouldn't work.

gabriellend avatar Feb 12 '24 23:02 gabriellend

Note, this other issue seems to suggest the .xcode.env thing will fix it, so just referencing here that that solution does not work: https://github.com/facebook/react-native/issues/33695

guikubivan avatar Mar 13 '24 01:03 guikubivan

This fixed the issue for me https://stackoverflow.com/a/66497247/6590549. I had a symlinked version of node that was node longer actually installed via nvm.

moulie415 avatar Apr 02 '24 20:04 moulie415

Apparently this is caused by nvm A less invasive workaround (that breaks nvm):

ln -s $(which node) /usr/local/bin/node

The problem is that Xcode scripts works in a different environment than a regular terminal/ Xcode also overrides some basic ENV var that can shadow and mask other variables we might set. If you don't have node in the default PATHs, like /usr/local/bin, for example, Xcode is not able to find it. A simple solution could be to create a symlink to node in /usr/local/bin:

sudo ln -s $(command -v node) /usr/local/bin/node

We are investigating better way to handle this, but we haven't found a robust approach yet, unfortunately. :(

This analysis is correct. I solved this problem by completely uninstalling node and then downloading the .pkg installation from the node.js ,because the installation location of the installation package is /usr/local/bin/node by default.

Thanks for good answer. The important thing is uninstalling unused node version.