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