react-native-macos/scripts/react-native-xcode.sh

141 строка
4.2 KiB
Bash
Исходник Обычный вид История

#!/bin/bash
# Copyright (c) Facebook, Inc. and its affiliates.
#
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.
# Bundle React Native app's code and image assets.
# This script is supposed to be invoked as part of Xcode build process
# and relies on environment variables (including PWD) set by Xcode
# Print commands before executing them (useful for troubleshooting)
set -x
DEST=$CONFIGURATION_BUILD_DIR/$UNLOCALIZED_RESOURCES_FOLDER_PATH
# Enables iOS devices to get the IP address of the machine running Metro
if [[ "$CONFIGURATION" = *Debug* && ! "$PLATFORM_NAME" == *simulator ]]; then
IP=$(ipconfig getifaddr en0)
Fix LAN instead of Wi-Fi device bundle config (#27575) Summary: React-native server-device connection must be via Wi-Fi. But if the OS-X server has LAN & Wi-Fi interfaces, then device bundle can be incorrectly configured to use LAN interface instead of Wi-Fi. This patch fix this issue. It greps for "baseT" (e.g. media: autoselect (1000baseT <full-duplex>)) and skip interface if it is. ## Changelog [iOS] [Fixed] - Fix LAN instead of Wi-Fi device bundle configuration Pull Request resolved: https://github.com/facebook/react-native/pull/27575 Test Plan: To reproduce an issue setup Mac OS 10.15.1 with LAN and Wi-Fi active interfaces. And connect real device (not simulator). And "ifconfig en0" in console should display LAN interface e.g.: ``` en0: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500 options=50b<RXCSUM,TXCSUM,VLAN_HWTAGGING,AV,CHANNEL_IO> ether 78:7b:8a:d8:61:42 inet 10.15.61.16 netmask 0xffffff00 broadcast 10.15.61.255 nd6 options=201<PERFORMNUD,DAD> media: autoselect (1000baseT <full-duplex>) status: active ``` "ifconfig eg1" in console should display WiFi interface e.g.: ``` en1: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500 options=400<CHANNEL_IO> ether 14:20:5e:03:5b:2a inet6 fe80::10e6:1cb6:54ec:1b41%en1 prefixlen 64 secured scopeid 0x5 inet 10.15.91.27 netmask 0xffffff00 broadcast 10.15.91.255 nd6 options=201<PERFORMNUD,DAD> media: autoselect status: active ``` In this case device bundle in react-native-xcode.sh script wood be incorrectly configured to use en0 (LAN interface) instead of en1(Wi-Fi) interface. My patch fixes this issue. fragment of script output before patch: ``` ... ++ ipconfig getifaddr en0 + IP=10.15.61.16 + '[' -z 10.15.61.16 '] + '[' -z 10.15.61.16 ']' + echo 10.15.61.16 + [[ -n '' ]] ... ``` After start project ob device we have time lag about 20s then debug out: ` 2019-12-20 16:58:57.530538+0300 AwesomeProject[4590:1923358] Task <164D9AB0-8473-4BA3-BD1A-EC0E92887C17>.<1> finished with error [-1001] Error Domain=NSURLErrorDomain Code=-1001 "The request timed out." UserInfo={NSUnderlyingError=0x2838dc2d0 {Error Domain=kCFErrorDomainCFNetwork Code=-1001 "(null)" UserInfo={_kCFStreamErrorCodeKey=-2102, _kCFStreamErrorDomainKey=4}}, NSErrorFailingURLStringKey=http://10.15.61.16:8081/status, NSErrorFailingURLKey=http://10.15.61.16:8081/status, _kCFStreamErrorDomainKey=4, _kCFStreamErrorCodeKey=-2102, NSLocalizedDescription=The request timed out.} ` fragment of script output after apply patch: ``` ... ++ ipconfig getifaddr en0 + IP=10.15.61.16 + [[ -z 10.15.61.16 ]] ++ ifconfig ++ grep baseT + [[ -n media: autoselect (1000baseT <full-duplex>) media: autoselect (100baseTX <full-duplex>) ]] ++ ipconfig getifaddr en1 + IP=10.15.91.27 + '[' -z 10.15.91.27 ']' + echo 10.15.91.27 + [[ -n '' ]] ... ``` App start OK. On iPhone /iPad simulator works too. Differential Revision: D19200334 Pulled By: hramos fbshipit-source-id: 22d791b657abd16a92d075515682b4fa961b489c
2019-12-20 23:41:18 +03:00
if [[ -z "$IP" || -n "`ifconfig $value | grep 'baseT'`" ]]; then
iOS build - en0 and en1 used when generating ip.txt file (#25462) Summary: When `en0` is not assigned and `en1` is in use along with another interface present on the machine that uses a self-assigned address (169.254.xxx.xxx), the ip.txt file contains the self-assigned address. This causes the app reload/debug actions to fail when deployed to a physical device. see https://github.com/facebook/react-native/issues/25460 Code change looks at the value assigned to `en1` if `en0` is not set. If `en1` is not available on the machine or not set, then it will be empty. If both `en0` and `en1` are not set, the existing code was modified exclude addresses that are self-assigned, as they will most likely be unavailable to the connected device (iPhone, iPad, etc.). ## Changelog [Internal] [Fixed] - en0 and en1 are used when generating the ip.txt file for iOS device debug builds Pull Request resolved: https://github.com/facebook/react-native/pull/25462 Test Plan: execute `ifconfig`: ``` lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> mtu 16384 options=1203<RXCSUM,TXCSUM,TXSTATUS,SW_TIMESTAMP> inet 127.0.0.1 netmask 0xff000000 inet6 ::1 prefixlen 128 inet6 fe80::1%lo0 prefixlen 64 scopeid 0x1 nd6 options=201<PERFORMNUD,DAD> gif0: flags=8010<POINTOPOINT,MULTICAST> mtu 1280 stf0: flags=0<> mtu 1280 XHC20: flags=0<> mtu 0 XHC0: flags=0<> mtu 0 en0: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500 options=10b<RXCSUM,TXCSUM,VLAN_HWTAGGING,AV> ether 38:f9:d3:0d:aa:fe nd6 options=201<PERFORMNUD,DAD> media: autoselect (none) status: inactive en2: flags=8963<UP,BROADCAST,SMART,RUNNING,PROMISC,SIMPLEX,MULTICAST> mtu 1500 options=60<TSO4,TSO6> ether 42:00:84:a8:f6:00 media: autoselect <full-duplex> status: inactive en3: flags=8963<UP,BROADCAST,SMART,RUNNING,PROMISC,SIMPLEX,MULTICAST> mtu 1500 options=60<TSO4,TSO6> ether 42:00:84:a8:f6:01 media: autoselect <full-duplex> status: active bridge0: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500 options=63<RXCSUM,TXCSUM,TSO4,TSO6> ether 42:00:84:a8:f6:00 inet6 fe80::e:80be:b322:79b7%bridge0 prefixlen 64 secured scopeid 0x9 inet 169.254.209.63 netmask 0xffff0000 broadcast 169.254.255.255 Configuration: id 0:0:0:0:0:0 priority 0 hellotime 0 fwddelay 0 maxage 0 holdcnt 0 proto stp maxaddr 100 timeout 1200 root id 0:0:0:0:0:0 priority 0 ifcost 0 port 0 ipfilter disabled flags 0x2 member: en2 flags=3<LEARNING,DISCOVER> ifmaxaddr 0 port 7 priority 0 path cost 0 member: en3 flags=3<LEARNING,DISCOVER> ifmaxaddr 0 port 8 priority 0 path cost 0 nd6 options=201<PERFORMNUD,DAD> media: autoselect status: active ap1: flags=8802<BROADCAST,SIMPLEX,MULTICAST> mtu 1500 ether 3a:f9:d3:9a:14:05 media: autoselect status: inactive en1: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500 ether 38:f9:d3:9a:14:05 inet6 fe80::1444:113e:d65:5fb3%en1 prefixlen 64 secured scopeid 0xb inet 192.168.1.115 netmask 0xffffff00 broadcast 192.168.1.255 nd6 options=201<PERFORMNUD,DAD> media: autoselect status: active p2p0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 2304 ether 0a:f9:d3:9a:14:05 media: autoselect status: inactive awdl0: flags=8943<UP,BROADCAST,RUNNING,PROMISC,SIMPLEX,MULTICAST> mtu 1484 ether 6a:fe:9d:f0:39:3f inet6 fe80::68fe:9dff:fef0:393f%awdl0 prefixlen 64 scopeid 0xd nd6 options=201<PERFORMNUD,DAD> media: autoselect status: active utun0: flags=8051<UP,POINTOPOINT,RUNNING,MULTICAST> mtu 2000 inet6 fe80::c992:4ed:9399:85bc%utun0 prefixlen 64 scopeid 0xe nd6 options=201<PERFORMNUD,DAD> utun1: flags=8051<UP,POINTOPOINT,RUNNING,MULTICAST> mtu 1380 inet6 fe80::f5de:860a:fd07:ee87%utun1 prefixlen 64 scopeid 0xf nd6 options=201<PERFORMNUD,DAD> utun2: flags=8051<UP,POINTOPOINT,RUNNING,MULTICAST> mtu 1380 inet6 fe80::3115:b6a0:6625:23ee%utun2 prefixlen 64 scopeid 0x11 nd6 options=201<PERFORMNUD,DAD> en5: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500 ether e2:33:8e:95:93:9b inet6 fe80::cea:8f7a:b379:ebcd%en5 prefixlen 64 secured scopeid 0x10 inet 169.254.167.11 netmask 0xffff0000 broadcast 169.254.255.255 nd6 options=201<PERFORMNUD,DAD> media: autoselect (100baseTX <full-duplex>) status: active ``` execute `ipconfig getifaddr en0`: (produces nothing) execute `ipconfig getifaddr en1`: ``` 192.168.1.115 ``` execute `ipconfig getifaddr en99`: (produces nothing - non-existent case) existing code `ifconfig | grep 'inet ' | grep -v ' 127.' | cut -d\ -f2 | awk 'NR==1{print $1}'` yields: ``` 169.254.209.63 ``` modified code ` ifconfig | grep 'inet ' | grep -v ' 127.' | grep -v ' 169.254.' | cut -d\ -f2 | awk 'NR==1{print $1}'` yields: ``` 192.168.1.115 ``` Differential Revision: D16099639 Pulled By: cpojer fbshipit-source-id: bd480a5f638efc58611d22cef4ba5193052b713d
2019-07-03 12:27:49 +03:00
IP=$(ipconfig getifaddr en1)
fi
if [ -z "$IP" ]; then
IP=$(ifconfig | grep 'inet ' | grep -v ' 127.' | grep -v ' 169.254.' |cut -d\ -f2 | awk 'NR==1{print $1}')
fi
echo "$IP" > "$DEST/ip.txt"
fi
if [[ "$SKIP_BUNDLING" ]]; then
echo "SKIP_BUNDLING enabled; skipping."
exit 0;
fi
case "$CONFIGURATION" in
*Debug*)
if [[ "$PLATFORM_NAME" == *simulator ]]; then
if [[ "$FORCE_BUNDLING" ]]; then
echo "FORCE_BUNDLING enabled; continuing to bundle."
else
echo "Skipping bundling in Debug for the Simulator (since the packager bundles for you). Use the FORCE_BUNDLING flag to change this behavior."
exit 0;
fi
else
echo "Bundling for physical device. Use the SKIP_BUNDLING flag to change this behavior."
fi
DEV=true
;;
"")
echo "$0 must be invoked by Xcode"
exit 1
;;
*)
DEV=false
;;
esac
feat: improve monorepo support by removing redundant PROJECT_ROOT (#28354) Summary: Historically, React Native didn't support a lot of custom project structures apart from the standard flat directory with `ios` and `android` folders. The CLI had to be explicitly started from the project root, otherwise Metro didn't work right. In order to resolve the project root in the most accurate way, React Native assumed that project root is always `../../` from its location in `node_modules` - this is not true when the installation gets hoisted (e.g. in a monorepo). To address that, janicduplessis brought support for custom [`PROJECT_ROOT`](https://github.com/facebook/react-native/commit/9ccde378b6e6379df61f9d968be6346ca6be7ead) that allowed overriding the `../../` in case it wasn't true. Today, CLI is able to automatically resolve the project root, no matter where it's started. It will traverse the tree of the directories upwards and stop as soon as it meets `package.json`. As a result, it doesn't really matter from where we start the CLI anymore as a part of `react-native-xcode.sh`. By replacing the default value of `$REACT_NATIVE_DIR/../../` with `$PWD, that is default for all Xcode scripts, we can make the setup for monorepo easier - nobody will need to set `$PROJECT_ROOT` in order to override the incorrect defaults. By default, all scripts defined in Xcode run from `$PWD` directory, which is the location of the iOS project. In the future, we will be able to remove `cd` entirely. To better understand this PR, let's look a few hypothetical structures as an example: #### Monorepo: > tl;dr works out of the box, no need to mess around with paths ``` - package.json - packages/ - my-app/ - index.js - package.json - ios/ - MyApp.xcodeproj ``` **Before this PR**, the `react-native-xcode.sh` will start the CLI like this: ```bash cd $REACT_NATIVE_DIR/../../ node <absolute_path_to_cli.js> bundle --entry-point index.js ``` - Because we change the directory to the root of monorepo, CLI throws an error. All in all, there's no `react-native` dependency at the workspace root. - Some users turn `no hoist` in an act of troubleshooting the errors, which resolves the problem - `react-native` is moved under `my-app/node_modules` which makes this mechanism resolve properly. - Some users find out about `PROJECT_ROOT` and set it to overwrite the default value. For example, setting `export PROJECT_ROOT = "$PWD/../` will set the directory to `my-app`, which has a dependency on `react-native` in a `package.json` and makes the CLI happy. **After this PR**, the `react-native-xcode.sh` will start the CLI like this: ```bash cd $PWD node <absolute_path_to_cli.js> bundle --entry-point index.js ``` - The `$PWD` is `packages/my-app/ios/` because that's where the Xcode project is located. CLI will automatically set the root to `../` because that's where it finds `package.json` with `react-native` dependency. It will pass that root to Metro, unless users have set a different one themselves. Thanks to that, all paths to JavaScript files remain working and unaffected. - No need to set `PROJECT_ROOT` anymore. - We don't rely on the location of `node_modules`, which is cleaner and future proof. #### Standard: > tl;dr no changes ``` - ios/ - MyApp.xcodeproj - index.js - package.json ``` **Before this PR**, the `react-native-xcode.sh` will start the CLI like this: ```bash cd $REACT_NATIVE_DIR/../../ node <absolute_path_to_cli.js> bundle --entry-point index.js ``` - Everything works fine. Path from `react-native` inside `node_modules` is correct - the project root is set right to `/` **After this PR**, the `react-native-xcode.sh` will start the CLI like this: ```bash cd $PWD node <absolute_path_to_cli.js> bundle --entry-point index.js ``` - The root will be set to where Xcode project is located, which is `/ios`. This is the PWD for all Xcode scripts. CLI will look for the `package.json` going upwards from `ios` folder. Will stop at `/`, find out it has `react-native` dependency, load it and its commands and proceed further. ## Changelog [iOS] [Feature] - Better monorepo support when building release apk Pull Request resolved: https://github.com/facebook/react-native/pull/28354 Test Plan: - All projects (standard/monorepo) run without issues. - PROJECT_ROOT is not needed. CC: Titozzz (who wrote monorepo guide), alloy, bartolkaruza Reviewed By: cpojer Differential Revision: D20558005 Pulled By: hramos fbshipit-source-id: 2551120beadcfd4c2f1393ce8a2c2fa6b93c9290
2020-03-20 21:33:09 +03:00
# Setting up a project root was a workaround to enable support for non-standard
# structures, including monorepos. Today, CLI supports that out of the box
# and setting custom `PROJECT_ROOT` only makes it confusing.
#
# As a backwards-compatible change, I am leaving "PROJECT_ROOT" support for those
# who already use it - it is likely a non-breaking removal.
#
# For new users, we default to $PWD - not changing things all.
#
# For context: https://github.com/facebook/react-native/commit/9ccde378b6e6379df61f9d968be6346ca6be7ead#commitcomment-37914902
PROJECT_ROOT=${PROJECT_ROOT:-$PWD}
cd "$PROJECT_ROOT" || exit
# Define NVM_DIR and source the nvm.sh setup script
[ -z "$NVM_DIR" ] && export NVM_DIR="$HOME/.nvm"
# Define entry file
if [[ "$ENTRY_FILE" ]]; then
# Use ENTRY_FILE defined by user
:
elif [[ -s "index.ios.js" ]]; then
ENTRY_FILE=${1:-index.ios.js}
else
ENTRY_FILE=${1:-index.js}
fi
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
# Set up the nodenv node version manager if present
if [[ -x "$HOME/.nodenv/bin/nodenv" ]]; then
eval "$("$HOME/.nodenv/bin/nodenv" init -)"
elif [[ -x "$(command -v brew)" && -x "$(brew --prefix nodenv)/bin/nodenv" ]]; then
eval "$("$(brew --prefix nodenv)/bin/nodenv" init -)"
fi
# Set up the ndenv of anyenv if preset
if [[ ! -x node && -d ${HOME}/.anyenv/bin ]]; then
export PATH=${HOME}/.anyenv/bin:${PATH}
if [[ "$(anyenv envs | grep -c ndenv )" -eq 1 ]]; then
eval "$(anyenv init -)"
fi
fi
feat: improve monorepo support by removing redundant PROJECT_ROOT (#28354) Summary: Historically, React Native didn't support a lot of custom project structures apart from the standard flat directory with `ios` and `android` folders. The CLI had to be explicitly started from the project root, otherwise Metro didn't work right. In order to resolve the project root in the most accurate way, React Native assumed that project root is always `../../` from its location in `node_modules` - this is not true when the installation gets hoisted (e.g. in a monorepo). To address that, janicduplessis brought support for custom [`PROJECT_ROOT`](https://github.com/facebook/react-native/commit/9ccde378b6e6379df61f9d968be6346ca6be7ead) that allowed overriding the `../../` in case it wasn't true. Today, CLI is able to automatically resolve the project root, no matter where it's started. It will traverse the tree of the directories upwards and stop as soon as it meets `package.json`. As a result, it doesn't really matter from where we start the CLI anymore as a part of `react-native-xcode.sh`. By replacing the default value of `$REACT_NATIVE_DIR/../../` with `$PWD, that is default for all Xcode scripts, we can make the setup for monorepo easier - nobody will need to set `$PROJECT_ROOT` in order to override the incorrect defaults. By default, all scripts defined in Xcode run from `$PWD` directory, which is the location of the iOS project. In the future, we will be able to remove `cd` entirely. To better understand this PR, let's look a few hypothetical structures as an example: #### Monorepo: > tl;dr works out of the box, no need to mess around with paths ``` - package.json - packages/ - my-app/ - index.js - package.json - ios/ - MyApp.xcodeproj ``` **Before this PR**, the `react-native-xcode.sh` will start the CLI like this: ```bash cd $REACT_NATIVE_DIR/../../ node <absolute_path_to_cli.js> bundle --entry-point index.js ``` - Because we change the directory to the root of monorepo, CLI throws an error. All in all, there's no `react-native` dependency at the workspace root. - Some users turn `no hoist` in an act of troubleshooting the errors, which resolves the problem - `react-native` is moved under `my-app/node_modules` which makes this mechanism resolve properly. - Some users find out about `PROJECT_ROOT` and set it to overwrite the default value. For example, setting `export PROJECT_ROOT = "$PWD/../` will set the directory to `my-app`, which has a dependency on `react-native` in a `package.json` and makes the CLI happy. **After this PR**, the `react-native-xcode.sh` will start the CLI like this: ```bash cd $PWD node <absolute_path_to_cli.js> bundle --entry-point index.js ``` - The `$PWD` is `packages/my-app/ios/` because that's where the Xcode project is located. CLI will automatically set the root to `../` because that's where it finds `package.json` with `react-native` dependency. It will pass that root to Metro, unless users have set a different one themselves. Thanks to that, all paths to JavaScript files remain working and unaffected. - No need to set `PROJECT_ROOT` anymore. - We don't rely on the location of `node_modules`, which is cleaner and future proof. #### Standard: > tl;dr no changes ``` - ios/ - MyApp.xcodeproj - index.js - package.json ``` **Before this PR**, the `react-native-xcode.sh` will start the CLI like this: ```bash cd $REACT_NATIVE_DIR/../../ node <absolute_path_to_cli.js> bundle --entry-point index.js ``` - Everything works fine. Path from `react-native` inside `node_modules` is correct - the project root is set right to `/` **After this PR**, the `react-native-xcode.sh` will start the CLI like this: ```bash cd $PWD node <absolute_path_to_cli.js> bundle --entry-point index.js ``` - The root will be set to where Xcode project is located, which is `/ios`. This is the PWD for all Xcode scripts. CLI will look for the `package.json` going upwards from `ios` folder. Will stop at `/`, find out it has `react-native` dependency, load it and its commands and proceed further. ## Changelog [iOS] [Feature] - Better monorepo support when building release apk Pull Request resolved: https://github.com/facebook/react-native/pull/28354 Test Plan: - All projects (standard/monorepo) run without issues. - PROJECT_ROOT is not needed. CC: Titozzz (who wrote monorepo guide), alloy, bartolkaruza Reviewed By: cpojer Differential Revision: D20558005 Pulled By: hramos fbshipit-source-id: 2551120beadcfd4c2f1393ce8a2c2fa6b93c9290
2020-03-20 21:33:09 +03:00
# Path to react-native folder inside node_modules
REACT_NATIVE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
# check and assign NODE_BINARY env
# shellcheck source=/dev/null
source "$REACT_NATIVE_DIR/scripts/node-binary.sh"
[ -z "$NODE_ARGS" ] && export NODE_ARGS=""
[ -z "$CLI_PATH" ] && export CLI_PATH="$REACT_NATIVE_DIR/cli.js"
[ -z "$BUNDLE_COMMAND" ] && BUNDLE_COMMAND="bundle"
if [[ -z "$BUNDLE_CONFIG" ]]; then
CONFIG_ARG=""
else
CONFIG_ARG="--config $BUNDLE_CONFIG"
fi
BUNDLE_FILE="$DEST/main.jsbundle"
"$NODE_BINARY" $NODE_ARGS "$CLI_PATH" $BUNDLE_COMMAND \
$CONFIG_ARG \
--entry-file "$ENTRY_FILE" \
--platform ios \
--dev $DEV \
--reset-cache \
--bundle-output "$BUNDLE_FILE" \
--assets-dest "$DEST" \
$EXTRA_PACKAGER_ARGS
if [[ $DEV != true && ! -f "$BUNDLE_FILE" ]]; then
echo "error: File $BUNDLE_FILE does not exist. This must be a bug with" >&2
echo "React Native, please report it here: https://github.com/facebook/react-native/issues"
exit 2
fi