Generate .xcode.env.local at pod install time (#38879)

Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/38879

When creating a new app for iOS, you need to have Node installed properly and in the right paths in order for Xcode to pick it up.

Xcode, by default, looks into the following folders for executables:
- /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
- /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/appleinternal/bin:
- /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/local/bin:
- /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/libexec
- /Applications/Xcodefb.app/Contents/Developer/Platforms/iPhoneSimulator.platform/usr/bin
- /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/usr/appleinternal/bin
- /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/usr/local/bin
- /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin
- /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/usr/local/bin
- /Applications/Xcode.app/Contents/Developer/usr/bin
- /Applications/Xcode.app/Contents/Developer/usr/local/bin
- /usr/local/bin
- /usr/bin
- /bin
- /usr/sbin
- /sbin

If `node` is not in one of them, our JS codegen scripts will fail to run. However, as soon as we run some scripts in Xcode, it is too late to properly look for node.

We already had a cocoapod step, running before the build phase, which was creating the `.xode.env` file, setting `NODE_BINARY` to `$(command -v node)`. Unfortunately, when executed by Xcode, that's too late too.

This change creates an `.xcode.env.local` file with the `$(command -v node)` command expanded, so I user can start working locally and quickly.

We had multiple reports and issues related to this configuration online. For example:
- https://www.reddit.com/r/reactnative/comments/15jpj0a/is_there_a_react_native_version_that_just_works/?utm_source=share&utm_medium=web2x&context=3

Note: we cannot automatically create simlinks to node in `/usr/local/bin` as it requires `sudo`.

## Changelog:
[Internal] - Generate `.xcode.env.local` to simplify the creation of an app.

Reviewed By: rshest

Differential Revision: D48111724

fbshipit-source-id: 49cc6375bd80458d69adbc343ead6c4408805eee
This commit is contained in:
Riccardo Cipolleschi
2023-08-09 08:38:22 -07:00
committed by Facebook GitHub Bot
parent e14d27c714
commit 5140d6438d
2 changed files with 16 additions and 8 deletions
@@ -560,24 +560,28 @@ class UtilsTests < Test::Unit::TestCase
# =================================== #
# Test - Prepare React Native Project #
# =================================== #
def test_createXcodeEnvIfMissing_whenItIsPresent_doNothing
def test_createXcodeEnvIfMissing_whenTheyArePresent_doNothing
# Arrange
FileMock.mocked_existing_files("/.xcode.env")
FileMock.mocked_existing_files("/.xcode.env.local")
# Act
ReactNativePodsUtils.create_xcode_env_if_missing(file_manager: FileMock)
# Assert
assert_equal(FileMock.exist_invocation_params, ["/.xcode.env"])
assert_equal(FileMock.exist_invocation_params, ["/.xcode.env", "/.xcode.env.local"])
assert_equal($collected_commands, [])
end
def test_createXcodeEnvIfMissing_whenItIsNotPresent_createsIt
def test_createXcodeEnvIfMissing_whenTheyAreNotPresent_createsThem
# Arrange
# Act
ReactNativePodsUtils.create_xcode_env_if_missing(file_manager: FileMock)
# Assert
assert_equal(FileMock.exist_invocation_params, ["/.xcode.env"])
assert_equal($collected_commands, ["echo 'export NODE_BINARY=$(command -v node)' > /.xcode.env"])
assert_equal(FileMock.exist_invocation_params, ["/.xcode.env", "/.xcode.env.local"])
assert_equal($collected_commands[0], "echo 'export NODE_BINARY=$(command -v node)' > /.xcode.env")
assert_true($collected_commands[1].start_with? "echo 'export NODE_BINARY=")
assert_true($collected_commands[1].end_with? "' > /.xcode.env.local")
end
# ============================ #
@@ -186,11 +186,15 @@ class ReactNativePodsUtils
def self.create_xcode_env_if_missing(file_manager: File)
relative_path = Pod::Config.instance.installation_root.relative_path_from(Pathname.pwd)
file_path = file_manager.join(relative_path, '.xcode.env')
if file_manager.exist?(file_path)
return
if !file_manager.exist?(file_path)
system("echo 'export NODE_BINARY=$(command -v node)' > #{file_path}")
end
system("echo 'export NODE_BINARY=$(command -v node)' > #{file_path}")
if !file_manager.exist?("#{file_path}.local")
node_binary = `command -v node`
system("echo 'export NODE_BINARY=#{node_binary}' > #{file_path}.local")
end
end
# It examines the target_definition property and sets the appropriate value for