From 5686ed9e54cf1c3489ffe7349a97a82b2b1991c1 Mon Sep 17 00:00:00 2001 From: rory Date: Sat, 7 Sep 2024 00:58:10 -0700 Subject: [PATCH 1/3] Create run-android script to setup ccache --- package.json | 2 +- scripts/run-android.sh | 70 ++++++++++++++++++++++++++++++++++++++++++ scripts/shellUtils.sh | 42 +++++++++++++++++++++++++ 3 files changed, 113 insertions(+), 1 deletion(-) create mode 100755 scripts/run-android.sh diff --git a/package.json b/package.json index 0b18f04667a5..c2909158e685 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "startAndroidEmulator": "scripts/start-android.sh", "postinstall": "scripts/postInstall.sh", "clean": "npx react-native clean-project-auto", - "android": "scripts/set-pusher-suffix.sh && npx react-native run-android --mode=developmentDebug --appId=com.expensify.chat.dev --active-arch-only", + "android": "scripts/run-android.sh", "ios": "scripts/set-pusher-suffix.sh && npx react-native run-ios --list-devices --mode=\"DebugDevelopment\" --scheme=\"New Expensify Dev\"", "pod-install": "scripts/pod-install.sh", "ipad": "concurrently \"npx react-native run-ios --simulator=\\\"iPad Pro (12.9-inch) (6th generation)\\\" --mode=\\\"DebugDevelopment\\\" --scheme=\\\"New Expensify Dev\\\"\"", diff --git a/scripts/run-android.sh b/scripts/run-android.sh new file mode 100755 index 000000000000..29aa68980582 --- /dev/null +++ b/scripts/run-android.sh @@ -0,0 +1,70 @@ +#!/bin/bash + +SCRIPTS_DIR=$(dirname "${BASH_SOURCE[0]}") + +source "$SCRIPTS_DIR/shellUtils.sh" + +"$SCRIPTS_DIR"/set-pusher-suffix.sh + +# Install ccache to perform cached build +if ! which ccache; then + if ask_yes_no "ccache not found. Would you like to install it to speed up your local builds?"; then + brew install ccache + fi +fi + +# Coming from https://reactnative.dev/docs/build-speed#local-caches, symlink ccache to C compilers used by React Native. +# Typically these packages exist in /usr/bin. Also typical is that `/usr/local/bin` appears before `/usr/bin` in your $PATH. +# So the way this works is to symlink ccache to the `/usr/local/bin` version of the package so it gets picked up by RN build commands. +packagesToSymlink=( + gcc + g++ + cc + c++ + clang + clang++ +) + +# Directory to store stashed original files in `/usr/local/bin` if they exist +tempDir=$(mktemp -d) + +#if [[ ${#packagesToSymlinkToUsrLocal[@]} -ne 0 && ! -d /usr/local/bin ]]; then +# mkdir -pv /usr/local/bin +#fi + +# But before actually creating the symlinks, prepare a cleanup function to remove them +cleanup() { + info "Cleaning up symlinks and restoring stashed packages" + for pkg in "${packagesToSymlink[@]}"; do + # remove symlinks + if [[ -L "/usr/local/bin/$pkg" ]]; then + sudo unlink -v "/usr/local/bin/$pkg" + fi + + # restore stashed binaries + if [[ -f "$tempDir/$pkg" ]]; then + sudo mv -v "$tempDir/$pkg" "/usr/local/bin/$pkg" + fi + done + + # Remove the temporary directory + rmdir "$tempDir" +} + +# and remove the symlinks before exiting so we don't leave symlinks developers may not be aware of +trap cleanup EXIT + +info "Stashing local C++ compilers and symlinking them with ccache" +for pkg in "${packagesToSymlink[@]}"; do + # stash the existing binaries if present + if [[ -f "/usr/local/bin/$pkg" ]]; then + sudo mv -v "/usr/local/bin/$pkg" "$tempDir/$pkg" + fi + + # create the symlinks + sudo ln -sv "$(which ccache)" "/usr/local/bin/$pkg" +done + +# Run the android build +trap 'warning "ccache was used for this failing build. Consider clearing the cache with `ccache --clear`"' ERR +npx react-native run-android --mode=developmentDebug --appId=com.expensify.chat.dev --active-arch-only diff --git a/scripts/shellUtils.sh b/scripts/shellUtils.sh index c1ceace09d0a..ffea69525b5e 100644 --- a/scripts/shellUtils.sh +++ b/scripts/shellUtils.sh @@ -10,6 +10,11 @@ if [ -z "${RED+x}" ]; then declare -r RED=$'\e[1;31m' fi +# Check if YELLOW has already been defined +if [ -z "${YELLOW+x}" ]; then + declare -r YELLOW=$'\e[1;33m' +fi + # Check if BLUE has already been defined if [ -z "${BLUE+x}" ]; then declare -r BLUE=$'\e[1;34m' @@ -33,6 +38,10 @@ function error { echo "💥 $RED$1$RESET" } +function warning { + echo "⚠️ $YELLOW$1$RESET" +} + function info { echo "$BLUE$1$RESET" } @@ -122,3 +131,36 @@ read_lines_into_array() { eval "$array_name+=(\"$line\")" done } + +ask_yes_no() { + local prompt_text="$1" + local default="$2" + local response + + # Determine the prompt with the default option shown + if [[ "$default" == "Y" ]]; then + prompt_text="$prompt_text [Y/n] " + elif [[ "$default" == "N" ]]; then + prompt_text="$prompt_text [y/N] " + else + prompt_text="$prompt_text [y/n] " + fi + + # Loop until a valid response is given + while true; do + # Prompt the user for input + read -r -p "$prompt_text" response + + # If response is empty, use the default + if [[ -z "$response" ]]; then + response="$default" + fi + + # Check if the response is Yes or No + case "$response" in + [yY][eE][sS]|[yY]) return 0 ;; # Yes: Return true (success) + [nN][oO]|[nN]) return 1 ;; # No: Return false (failure) + *) echo "Please answer yes or no." ;; + esac + done +} From c252e16ef7ced9c8de32c287bf0841a83cdce50e Mon Sep 17 00:00:00 2001 From: rory Date: Sat, 7 Sep 2024 01:02:44 -0700 Subject: [PATCH 2/3] Make all the symlinking logic conditional --- scripts/run-android.sh | 91 ++++++++++++++++++++++-------------------- 1 file changed, 47 insertions(+), 44 deletions(-) diff --git a/scripts/run-android.sh b/scripts/run-android.sh index 29aa68980582..34c7d5a6eb31 100755 --- a/scripts/run-android.sh +++ b/scripts/run-android.sh @@ -13,58 +13,61 @@ if ! which ccache; then fi fi -# Coming from https://reactnative.dev/docs/build-speed#local-caches, symlink ccache to C compilers used by React Native. -# Typically these packages exist in /usr/bin. Also typical is that `/usr/local/bin` appears before `/usr/bin` in your $PATH. -# So the way this works is to symlink ccache to the `/usr/local/bin` version of the package so it gets picked up by RN build commands. -packagesToSymlink=( - gcc - g++ - cc - c++ - clang - clang++ -) +if which ccache; then + # Coming from https://reactnative.dev/docs/build-speed#local-caches, symlink ccache to C compilers used by React Native. + # Typically these packages exist in /usr/bin. Also typical is that `/usr/local/bin` appears before `/usr/bin` in your $PATH. + # So the way this works is to symlink ccache to the `/usr/local/bin` version of the package so it gets picked up by RN build commands. + packagesToSymlink=( + gcc + g++ + cc + c++ + clang + clang++ + ) -# Directory to store stashed original files in `/usr/local/bin` if they exist -tempDir=$(mktemp -d) + # Directory to store stashed original files in `/usr/local/bin` if they exist + tempDir=$(mktemp -d) -#if [[ ${#packagesToSymlinkToUsrLocal[@]} -ne 0 && ! -d /usr/local/bin ]]; then -# mkdir -pv /usr/local/bin -#fi + #if [[ ${#packagesToSymlinkToUsrLocal[@]} -ne 0 && ! -d /usr/local/bin ]]; then + # mkdir -pv /usr/local/bin + #fi -# But before actually creating the symlinks, prepare a cleanup function to remove them -cleanup() { - info "Cleaning up symlinks and restoring stashed packages" - for pkg in "${packagesToSymlink[@]}"; do - # remove symlinks - if [[ -L "/usr/local/bin/$pkg" ]]; then - sudo unlink -v "/usr/local/bin/$pkg" - fi + # But before actually creating the symlinks, prepare a cleanup function to remove them + cleanup() { + info "Cleaning up symlinks and restoring stashed packages" + for pkg in "${packagesToSymlink[@]}"; do + # remove symlinks + if [[ -L "/usr/local/bin/$pkg" ]]; then + sudo unlink -v "/usr/local/bin/$pkg" + fi - # restore stashed binaries - if [[ -f "$tempDir/$pkg" ]]; then - sudo mv -v "$tempDir/$pkg" "/usr/local/bin/$pkg" - fi - done + # restore stashed binaries + if [[ -f "$tempDir/$pkg" ]]; then + sudo mv -v "$tempDir/$pkg" "/usr/local/bin/$pkg" + fi + done - # Remove the temporary directory - rmdir "$tempDir" -} + # Remove the temporary directory + rmdir "$tempDir" + } -# and remove the symlinks before exiting so we don't leave symlinks developers may not be aware of -trap cleanup EXIT + # and remove the symlinks before exiting so we don't leave symlinks developers may not be aware of + trap cleanup EXIT -info "Stashing local C++ compilers and symlinking them with ccache" -for pkg in "${packagesToSymlink[@]}"; do - # stash the existing binaries if present - if [[ -f "/usr/local/bin/$pkg" ]]; then - sudo mv -v "/usr/local/bin/$pkg" "$tempDir/$pkg" - fi + info "Stashing local C++ compilers and symlinking them with ccache" + for pkg in "${packagesToSymlink[@]}"; do + # stash the existing binaries if present + if [[ -f "/usr/local/bin/$pkg" ]]; then + sudo mv -v "/usr/local/bin/$pkg" "$tempDir/$pkg" + fi - # create the symlinks - sudo ln -sv "$(which ccache)" "/usr/local/bin/$pkg" -done + # create the symlinks + sudo ln -sv "$(which ccache)" "/usr/local/bin/$pkg" + done + + trap 'warning "ccache was used for this failing build. Consider clearing the cache with `ccache --clear`"' ERR +fi # Run the android build -trap 'warning "ccache was used for this failing build. Consider clearing the cache with `ccache --clear`"' ERR npx react-native run-android --mode=developmentDebug --appId=com.expensify.chat.dev --active-arch-only From 15403cc0dd5851eae2d89d2aefeaf5d5e6659530 Mon Sep 17 00:00:00 2001 From: rory Date: Sat, 7 Sep 2024 01:09:57 -0700 Subject: [PATCH 3/3] Move ccache utils to separate file --- scripts/ccache-utils.sh | 60 ++++++++++++++++++++++++++++++++++++++++ scripts/run-android.sh | 61 ++++------------------------------------- 2 files changed, 66 insertions(+), 55 deletions(-) create mode 100755 scripts/ccache-utils.sh diff --git a/scripts/ccache-utils.sh b/scripts/ccache-utils.sh new file mode 100755 index 000000000000..28731061cb79 --- /dev/null +++ b/scripts/ccache-utils.sh @@ -0,0 +1,60 @@ +#!/bin/bash + +SCRIPTS_DIR=$(dirname "${BASH_SOURCE[0]}") + +source "$SCRIPTS_DIR/shellUtils.sh" + +# Ask to install ccache if it isn't installed already +install_ccache() { + if ! which ccache; then + if ask_yes_no "ccache not found. Would you like to install it to speed up your local builds?"; then + brew install ccache + fi + fi +} + +# Coming from https://reactnative.dev/docs/build-speed#local-caches, symlink ccache to C compilers used by React Native. +# Typically these packages exist in /usr/bin. Also typical is that `/usr/local/bin` appears before `/usr/bin` in your $PATH. +# So the way this works is to symlink ccache to the `/usr/local/bin` version of the package so it gets picked up by RN build commands. +packagesToSymlink=( + gcc + g++ + cc + c++ + clang + clang++ +) + +# Directory to store stashed original files in `/usr/local/bin` if they exist +tempDir=$(mktemp -d) + +create_ccache_symlinks() { + info "Stashing local C++ compilers and symlinking them with ccache" + for pkg in "${packagesToSymlink[@]}"; do + # stash the existing binaries if present + if [[ -f "/usr/local/bin/$pkg" ]]; then + sudo mv -v "/usr/local/bin/$pkg" "$tempDir/$pkg" + fi + + # create the symlinks + sudo ln -sv "$(which ccache)" "/usr/local/bin/$pkg" + done +} + +cleanup_ccache_symlinks() { + info "Cleaning up ccache symlinks and restoring stashed packages" + for pkg in "${packagesToSymlink[@]}"; do + # remove symlinks + if [[ -L "/usr/local/bin/$pkg" ]]; then + sudo unlink -v "/usr/local/bin/$pkg" + fi + + # restore stashed binaries + if [[ -f "$tempDir/$pkg" ]]; then + sudo mv -v "$tempDir/$pkg" "/usr/local/bin/$pkg" + fi + done + + # Remove the temporary directory + rmdir "$tempDir" +} diff --git a/scripts/run-android.sh b/scripts/run-android.sh index 34c7d5a6eb31..641c9f458e30 100755 --- a/scripts/run-android.sh +++ b/scripts/run-android.sh @@ -2,70 +2,21 @@ SCRIPTS_DIR=$(dirname "${BASH_SOURCE[0]}") +source "$SCRIPTS_DIR/ccache-utils.sh" source "$SCRIPTS_DIR/shellUtils.sh" "$SCRIPTS_DIR"/set-pusher-suffix.sh # Install ccache to perform cached build -if ! which ccache; then - if ask_yes_no "ccache not found. Would you like to install it to speed up your local builds?"; then - brew install ccache - fi -fi +install_ccache if which ccache; then - # Coming from https://reactnative.dev/docs/build-speed#local-caches, symlink ccache to C compilers used by React Native. - # Typically these packages exist in /usr/bin. Also typical is that `/usr/local/bin` appears before `/usr/bin` in your $PATH. - # So the way this works is to symlink ccache to the `/usr/local/bin` version of the package so it gets picked up by RN build commands. - packagesToSymlink=( - gcc - g++ - cc - c++ - clang - clang++ - ) - - # Directory to store stashed original files in `/usr/local/bin` if they exist - tempDir=$(mktemp -d) - - #if [[ ${#packagesToSymlinkToUsrLocal[@]} -ne 0 && ! -d /usr/local/bin ]]; then - # mkdir -pv /usr/local/bin - #fi - - # But before actually creating the symlinks, prepare a cleanup function to remove them - cleanup() { - info "Cleaning up symlinks and restoring stashed packages" - for pkg in "${packagesToSymlink[@]}"; do - # remove symlinks - if [[ -L "/usr/local/bin/$pkg" ]]; then - sudo unlink -v "/usr/local/bin/$pkg" - fi - - # restore stashed binaries - if [[ -f "$tempDir/$pkg" ]]; then - sudo mv -v "$tempDir/$pkg" "/usr/local/bin/$pkg" - fi - done - - # Remove the temporary directory - rmdir "$tempDir" - } - - # and remove the symlinks before exiting so we don't leave symlinks developers may not be aware of - trap cleanup EXIT - - info "Stashing local C++ compilers and symlinking them with ccache" - for pkg in "${packagesToSymlink[@]}"; do - # stash the existing binaries if present - if [[ -f "/usr/local/bin/$pkg" ]]; then - sudo mv -v "/usr/local/bin/$pkg" "$tempDir/$pkg" - fi + # remove the symlinks before exiting so we don't leave symlinks developers may not be aware of + trap cleanup_ccache_symlinks EXIT - # create the symlinks - sudo ln -sv "$(which ccache)" "/usr/local/bin/$pkg" - done + create_ccache_symlinks + # warn developers to clear cache if build fails trap 'warning "ccache was used for this failing build. Consider clearing the cache with `ccache --clear`"' ERR fi