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