diff --git a/packages/react-native/scripts/cocoapods/utils.rb b/packages/react-native/scripts/cocoapods/utils.rb index dcb15c397d0196..d93183dbbe478d 100644 --- a/packages/react-native/scripts/cocoapods/utils.rb +++ b/packages/react-native/scripts/cocoapods/utils.rb @@ -86,6 +86,42 @@ def self.set_node_modules_user_settings(installer, react_native_path) end end + def self.set_ccache_compiler_and_linker_build_settings(installer, react_native_path, ccache_enabled) + projects = self.extract_projects(installer) + + ccache_path = `command -v ccache`.strip + ccache_available = !ccache_path.empty? + + message_prefix = "[Ccache]" + + if ccache_available + Pod::UI.puts("#{message_prefix}: Ccache found at #{ccache_path}") + end + + if ccache_available and ccache_enabled + Pod::UI.puts("#{message_prefix}: Setting CC, LD, CXX & LDPLUSPLUS build settings") + # Using scripts wrapping the ccache executable, to allow injection of configurations + ccache_clang_sh = File.join("$(REACT_NATIVE_PATH)", 'scripts', 'xcode', 'ccache-clang.sh') + ccache_clangpp_sh = File.join("$(REACT_NATIVE_PATH)", 'scripts', 'xcode', 'ccache-clang++.sh') + + projects.each do |project| + project.build_configurations.each do |config| + # Using the un-qualified names means you can swap in different implementations, for example ccache + config.build_settings["CC"] = ccache_clang_sh + config.build_settings["LD"] = ccache_clang_sh + config.build_settings["CXX"] = ccache_clangpp_sh + config.build_settings["LDPLUSPLUS"] = ccache_clangpp_sh + end + + project.save() + end + elsif ccache_available and !ccache_enabled + Pod::UI.puts("#{message_prefix}: Pass ':ccache_enabled => true' to 'react_native_post_install' in your Podfile or set environment variable 'USE_CCACHE=1' to increase the speed of subsequent builds") + elsif !ccache_available and ccache_enabled + Pod::UI.warn("#{message_prefix}: Install ccache or ensure your neither passing ':ccache_enabled => true' nor setting environment variable 'USE_CCACHE=1'") + end + end + def self.fix_library_search_paths(installer) projects = self.extract_projects(installer) diff --git a/packages/react-native/scripts/react_native_pods.rb b/packages/react-native/scripts/react_native_pods.rb index 1f6591eb1e361b..f6254dbcfb0b3f 100644 --- a/packages/react-native/scripts/react_native_pods.rb +++ b/packages/react-native/scripts/react_native_pods.rb @@ -259,7 +259,8 @@ def get_default_flags() def react_native_post_install( installer, react_native_path = "../node_modules/react-native", - mac_catalyst_enabled: false + mac_catalyst_enabled: false, + ccache_enabled: ENV['USE_CCACHE'] == '1' ) ReactNativePodsUtils.turn_off_resource_bundle_react_core(installer) @@ -276,6 +277,7 @@ def react_native_post_install( ReactNativePodsUtils.update_search_paths(installer) ReactNativePodsUtils.set_use_hermes_build_setting(installer, hermes_enabled) ReactNativePodsUtils.set_node_modules_user_settings(installer, react_native_path) + ReactNativePodsUtils.set_ccache_compiler_and_linker_build_settings(installer, react_native_path, ccache_enabled) ReactNativePodsUtils.apply_xcode_15_patch(installer) ReactNativePodsUtils.apply_ats_config(installer) ReactNativePodsUtils.updateOSDeploymentTarget(installer) diff --git a/packages/react-native/scripts/xcode/ccache-clang++.sh b/packages/react-native/scripts/xcode/ccache-clang++.sh new file mode 100755 index 00000000000000..f699d9a2442bae --- /dev/null +++ b/packages/react-native/scripts/xcode/ccache-clang++.sh @@ -0,0 +1,14 @@ +#!/bin/sh +# Copyright (c) Meta Platforms, Inc. and affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +# Get the absolute path of this script +SCRIPT_DIR="$(dirname "$(readlink -f "$0")")" + +REACT_NATIVE_CCACHE_CONFIGPATH=$SCRIPT_DIR/ccache.conf +# Provide our config file if none is already provided +export CCACHE_CONFIGPATH="${CCACHE_CONFIGPATH:-$REACT_NATIVE_CCACHE_CONFIGPATH}" + +exec ccache clang++ "$@" diff --git a/packages/react-native/scripts/xcode/ccache-clang.sh b/packages/react-native/scripts/xcode/ccache-clang.sh new file mode 100755 index 00000000000000..5ed8664498ddea --- /dev/null +++ b/packages/react-native/scripts/xcode/ccache-clang.sh @@ -0,0 +1,14 @@ +#!/bin/sh +# Copyright (c) Meta Platforms, Inc. and affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +# Get the absolute path of this script +SCRIPT_DIR="$(dirname "$(readlink -f "$0")")" + +REACT_NATIVE_CCACHE_CONFIGPATH=$SCRIPT_DIR/ccache.conf +# Provide our config file if none is already provided +export CCACHE_CONFIGPATH="${CCACHE_CONFIGPATH:-$REACT_NATIVE_CCACHE_CONFIGPATH}" + +exec ccache clang "$@" diff --git a/packages/react-native/scripts/xcode/ccache.conf b/packages/react-native/scripts/xcode/ccache.conf new file mode 100644 index 00000000000000..4f4b601a12dc13 --- /dev/null +++ b/packages/react-native/scripts/xcode/ccache.conf @@ -0,0 +1,11 @@ +# Copyright (c) Meta Platforms, Inc. and affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +# See https://ccache.dev/manual/4.3.html#_configuration_options for details and available options + +sloppiness = clang_index_store,file_stat_matches,include_file_ctime,include_file_mtime,ivfsoverlay,pch_defines,modules,system_headers,time_macros +file_clone = true +depend_mode = true +inode_cache = true diff --git a/packages/react-native/template/ios/Podfile b/packages/react-native/template/ios/Podfile index 65033592a105a1..6a6cd92f24e24f 100644 --- a/packages/react-native/template/ios/Podfile +++ b/packages/react-native/template/ios/Podfile @@ -33,7 +33,8 @@ target 'HelloWorld' do react_native_post_install( installer, config[:reactNativePath], - :mac_catalyst_enabled => false + :mac_catalyst_enabled => false, + # :ccache_enabled => true ) end end