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