1#!/bin/bash 2# Copyright (c) Meta Platforms, Inc. and affiliates. 3# 4# This source code is licensed under the MIT license found in the 5# LICENSE file in the root directory of this source tree. 6 7# Bundle React Native app's code and image assets. 8# This script is supposed to be invoked as part of Xcode build process 9# and relies on environment variables (including PWD) set by Xcode 10 11# Print commands before executing them (useful for troubleshooting) 12set -x 13DEST=$CONFIGURATION_BUILD_DIR/$UNLOCALIZED_RESOURCES_FOLDER_PATH 14 15# Enables iOS devices to get the IP address of the machine running Metro 16if [[ ! "$SKIP_BUNDLING_METRO_IP" && "$CONFIGURATION" = *Debug* && ! "$PLATFORM_NAME" == *simulator ]]; then 17 for num in 0 1 2 3 4 5 6 7 8; do 18 IP=$(ipconfig getifaddr en${num}) 19 if [ ! -z "$IP" ]; then 20 break 21 fi 22 done 23 if [ -z "$IP" ]; then 24 IP=$(ifconfig | grep 'inet ' | grep -v ' 127.' | grep -v ' 169.254.' |cut -d\ -f2 | awk 'NR==1{print $1}') 25 fi 26 27 echo "$IP" > "$DEST/ip.txt" 28fi 29 30if [[ "$SKIP_BUNDLING" ]]; then 31 echo "SKIP_BUNDLING enabled; skipping." 32 exit 0; 33fi 34 35case "$CONFIGURATION" in 36 *Debug*) 37 if [[ "$PLATFORM_NAME" == *simulator ]]; then 38 if [[ "$FORCE_BUNDLING" ]]; then 39 echo "FORCE_BUNDLING enabled; continuing to bundle." 40 else 41 echo "Skipping bundling in Debug for the Simulator (since the packager bundles for you). Use the FORCE_BUNDLING flag to change this behavior." 42 exit 0; 43 fi 44 else 45 echo "Bundling for physical device. Use the SKIP_BUNDLING flag to change this behavior." 46 fi 47 48 DEV=true 49 ;; 50 "") 51 echo "$0 must be invoked by Xcode" 52 exit 1 53 ;; 54 *) 55 DEV=false 56 ;; 57esac 58 59# Path to react-native folder inside node_modules 60REACT_NATIVE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" 61# Most projects have their project root, one level up from their Xcode project dir (the "ios" directory) 62PROJECT_ROOT=${PROJECT_ROOT:-"$PROJECT_DIR/.."} 63 64cd "$PROJECT_ROOT" || exit 65 66# Define entry file 67if [[ "$ENTRY_FILE" ]]; then 68 # Use ENTRY_FILE defined by user 69 : 70elif [[ -s "index.ios.js" ]]; then 71 ENTRY_FILE=${1:-index.ios.js} 72else 73 ENTRY_FILE=${1:-index.js} 74fi 75 76# check and assign NODE_BINARY env 77# shellcheck source=/dev/null 78source "$REACT_NATIVE_DIR/scripts/node-binary.sh" 79 80# If hermes-engine is in the Podfile.lock, it means that Hermes is a dependency of the project 81# and it is enabled. If not, it means that hermes is disabled. 82HERMES_ENABLED=$(grep hermes-engine $PODS_PODFILE_DIR_PATH/Podfile.lock) 83 84# If hermes-engine is not in the Podfile.lock, it means that the app is not using Hermes. 85# Setting USE_HERMES is no the only way to set whether the app can use hermes or not: users 86# can also modify manually the Podfile. 87if [[ -z "$HERMES_ENABLED" ]]; then 88 USE_HERMES=false 89fi 90 91HERMES_ENGINE_PATH="$PODS_ROOT/hermes-engine" 92[ -z "$HERMES_CLI_PATH" ] && HERMES_CLI_PATH="$HERMES_ENGINE_PATH/destroot/bin/hermesc" 93 94# Hermes is enabled in new projects by default, so we cannot assume that USE_HERMES=1 is set as an envvar. 95# If hermes-engine is found in Pods, we can assume Hermes has not been disabled. 96# If hermesc is not available and USE_HERMES is either unset or true, show error. 97if [[ ! -z "$HERMES_ENABLED" && -f "$HERMES_ENGINE_PATH" && ! -f "$HERMES_CLI_PATH" ]]; then 98 echo "error: Hermes is enabled but the hermesc binary could not be found at ${HERMES_CLI_PATH}." \ 99 "Perhaps you need to run 'bundle exec pod install' or otherwise " \ 100 "point the HERMES_CLI_PATH variable to your custom location." >&2 101 exit 2 102fi 103 104[ -z "$NODE_ARGS" ] && export NODE_ARGS="" 105 106[ -z "$CLI_PATH" ] && export CLI_PATH="$REACT_NATIVE_DIR/cli.js" 107 108[ -z "$BUNDLE_COMMAND" ] && BUNDLE_COMMAND="bundle" 109 110[ -z "$COMPOSE_SOURCEMAP_PATH" ] && COMPOSE_SOURCEMAP_PATH="$REACT_NATIVE_DIR/scripts/compose-source-maps.js" 111 112if [[ -z "$BUNDLE_CONFIG" ]]; then 113 CONFIG_ARG="" 114else 115 CONFIG_ARG="--config $BUNDLE_CONFIG" 116fi 117 118BUNDLE_FILE="$CONFIGURATION_BUILD_DIR/main.jsbundle" 119 120EXTRA_ARGS= 121 122case "$PLATFORM_NAME" in 123 "macosx") 124 BUNDLE_PLATFORM="macos" 125 ;; 126 *) 127 BUNDLE_PLATFORM="ios" 128 ;; 129esac 130 131if [ "${IS_MACCATALYST}" = "YES" ]; then 132 BUNDLE_PLATFORM="ios" 133fi 134 135EMIT_SOURCEMAP= 136if [[ ! -z "$SOURCEMAP_FILE" ]]; then 137 EMIT_SOURCEMAP=true 138fi 139 140PACKAGER_SOURCEMAP_FILE= 141if [[ $EMIT_SOURCEMAP == true ]]; then 142 if [[ $USE_HERMES != false ]]; then 143 PACKAGER_SOURCEMAP_FILE="$CONFIGURATION_BUILD_DIR/$(basename $SOURCEMAP_FILE)" 144 else 145 PACKAGER_SOURCEMAP_FILE="$SOURCEMAP_FILE" 146 fi 147 EXTRA_ARGS="$EXTRA_ARGS --sourcemap-output $PACKAGER_SOURCEMAP_FILE" 148fi 149 150# Hermes doesn't require JS minification. 151if [[ $USE_HERMES != false && $DEV == false ]]; then 152 EXTRA_ARGS="$EXTRA_ARGS --minify false" 153fi 154 155"$NODE_BINARY" $NODE_ARGS "$CLI_PATH" $BUNDLE_COMMAND \ 156 $CONFIG_ARG \ 157 --entry-file "$ENTRY_FILE" \ 158 --platform "$BUNDLE_PLATFORM" \ 159 --dev $DEV \ 160 --reset-cache \ 161 --bundle-output "$BUNDLE_FILE" \ 162 --assets-dest "$DEST" \ 163 $EXTRA_ARGS \ 164 $EXTRA_PACKAGER_ARGS 165 166if [[ $USE_HERMES == false ]]; then 167 cp "$BUNDLE_FILE" "$DEST/" 168 BUNDLE_FILE="$DEST/main.jsbundle" 169else 170 EXTRA_COMPILER_ARGS= 171 if [[ $DEV == true ]]; then 172 EXTRA_COMPILER_ARGS=-Og 173 else 174 EXTRA_COMPILER_ARGS=-O 175 fi 176 if [[ $EMIT_SOURCEMAP == true ]]; then 177 EXTRA_COMPILER_ARGS="$EXTRA_COMPILER_ARGS -output-source-map" 178 fi 179 "$HERMES_CLI_PATH" -emit-binary -max-diagnostic-width=80 $EXTRA_COMPILER_ARGS -out "$DEST/main.jsbundle" "$BUNDLE_FILE" 180 if [[ $EMIT_SOURCEMAP == true ]]; then 181 HBC_SOURCEMAP_FILE="$DEST/main.jsbundle.map" 182 "$NODE_BINARY" "$COMPOSE_SOURCEMAP_PATH" "$PACKAGER_SOURCEMAP_FILE" "$HBC_SOURCEMAP_FILE" -o "$SOURCEMAP_FILE" 183 rm "$HBC_SOURCEMAP_FILE" 184 rm "$PACKAGER_SOURCEMAP_FILE" 185 fi 186 BUNDLE_FILE="$DEST/main.jsbundle" 187fi 188 189if [[ $DEV != true && ! -f "$BUNDLE_FILE" ]]; then 190 echo "error: File $BUNDLE_FILE does not exist. This must be a bug with React Native, please report it here: https://github.com/facebook/react-native/issues" >&2 191 exit 2 192fi 193