Skip to content

Commit

Permalink
Update ruby scripts to install the dependencies with use_frameworks.
Browse files Browse the repository at this point in the history
Summary:
This diff update the Cocoapods scripts to install the proper dependencies and search paths when `use_frameworks!` is declared together with the New Architecture.

Practically, it adds the right search paths to the codegen and the project files and makes sure that third party dependencies that leverage the `install_modules_dependencies` are populated with the right search paths for Frameworks.

It also adds unit tests for the changes and the new methods introduced.

## Changelog:
[iOS][Changed] - Properly install dependencies with `use_frameworks!`

Reviewed By: sammy-SC, dmytrorykun

Differential Revision: D43089869

fbshipit-source-id: 1981b6853f774fdb3dbe8d17ea37fd5154c54b25
  • Loading branch information
cipolleschi authored and facebook-github-bot committed Feb 20, 2023
1 parent b1b2b8b commit 6d34952
Show file tree
Hide file tree
Showing 9 changed files with 211 additions and 28 deletions.
43 changes: 39 additions & 4 deletions scripts/cocoapods/__tests__/codegen_utils-test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,25 @@ def testGetReactCodegenSpec_whenFabricEnabledAndScriptPhases_generatesAPodspec
assert_equal(Pod::UI.collected_messages, ["[Codegen] Adding script_phases to React-Codegen."])
end

def testGetReactCodegenSpec_whenUseFrameworksAndNewArch_generatesAPodspec
# Arrange
ENV["USE_FRAMEWORKS"] = "static"
FileMock.files_to_read('package.json' => '{ "version": "99.98.97"}')

# Act
podspec = CodegenUtils.new().get_react_codegen_spec(
'package.json',
:fabric_enabled => true,
:hermes_enabled => true,
:script_phases => nil,
:file_manager => FileMock
)

# Assert
assert_equal(podspec, get_podspec_when_use_frameworks())
assert_equal(Pod::UI.collected_messages, [])
end

# =============================== #
# Test - GetCodegenConfigFromFile #
# =============================== #
Expand Down Expand Up @@ -503,7 +522,9 @@ def get_podspec_no_fabric_no_script
'ios' => '11.0',
},
'source_files' => "**/*.{h,mm,cpp}",
'pod_target_xcconfig' => { "HEADER_SEARCH_PATHS" =>
'pod_target_xcconfig' => {
"FRAMEWORK_SEARCH_PATHS" => [],
"HEADER_SEARCH_PATHS" =>
[
"\"$(PODS_ROOT)/boost\"",
"\"$(PODS_ROOT)/RCT-Folly\"",
Expand All @@ -514,15 +535,16 @@ def get_podspec_no_fabric_no_script
},
'dependencies': {
"FBReactNativeSpec": [],
"React-jsiexecutor": [],
"RCT-Folly": [],
"RCTRequired": [],
"RCTTypeSafety": [],
"React-Core": [],
"React-jsi": [],
"hermes-engine": [],
"React-jsiexecutor": [],
"React-rncore": [],
"ReactCommon/turbomodule/bridging": [],
"ReactCommon/turbomodule/core": []
"ReactCommon/turbomodule/core": [],
"hermes-engine": [],
}
}
end
Expand All @@ -539,4 +561,17 @@ def get_podspec_fabric_and_script_phases(script_phases)

return specs
end

def get_podspec_when_use_frameworks
specs = get_podspec_no_fabric_no_script()

specs["pod_target_xcconfig"]["FRAMEWORK_SEARCH_PATHS"].concat(["\"${PODS_CONFIGURATION_BUILD_DIR}/React-RCTFabric\""])
specs["pod_target_xcconfig"]["HEADER_SEARCH_PATHS"].concat(" \"$(PODS_ROOT)/DoubleConversion\" \"$(PODS_TARGET_SRCROOT)\" \"$(PODS_CONFIGURATION_BUILD_DIR)/React-Fabric/React_Fabric.framework/Headers\" \"$(PODS_CONFIGURATION_BUILD_DIR)/React-graphics/React_graphics.framework/Headers\" \"$(PODS_CONFIGURATION_BUILD_DIR)/React-graphics/React_graphics.framework/Headers/react/renderer/graphics/platform/ios\" \"$(PODS_CONFIGURATION_BUILD_DIR)/ReactCommon/ReactCommon.framework/Headers\" \"$(PODS_CONFIGURATION_BUILD_DIR)/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core\" \"$(PODS_CONFIGURATION_BUILD_DIR)/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core/platform/ios\"")

specs[:dependencies].merge!({
'React-graphics': [],
})

return specs
end
end
25 changes: 21 additions & 4 deletions scripts/cocoapods/__tests__/fabric-test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,13 @@ def setup

def teardown
podSpy_cleanUp()
ENV['RCT_NEW_ARCH_ENABLED'] = "0"
end

# ================== #
# TEST - setupFabric #
# ================== #
def test_setupFabric_installsPods
def test_setupFabric_whenNewArchDisabled_installsPods
# Arrange
prefix = "../.."

Expand All @@ -32,14 +33,30 @@ def test_setupFabric_installsPods
check_installed_pods(prefix)
end

def check_installed_pods(prefix)
assert_equal($podInvocationCount, 5)
def test_setupFabric_whenNewArchEnabled_installPods
# Arrange
prefix = "../.."
ENV['RCT_NEW_ARCH_ENABLED'] = "1"

# Act
setup_fabric!(:react_native_path => prefix, new_arch_enabled: true)

# Assert
check_installed_pods(prefix, install_rncore: false)
end

def check_installed_pods(prefix, install_rncore: true)
assert_equal($podInvocationCount, install_rncore ? 5 : 4)

check_pod("React-Fabric", :path => "#{prefix}/ReactCommon")
check_pod("React-rncore", :path => "#{prefix}/ReactCommon")
check_pod("React-graphics", :path => "#{prefix}/ReactCommon/react/renderer/graphics")
check_pod("React-RCTFabric", :path => "#{prefix}/React", :modular_headers => true)
check_pod("RCT-Folly/Fabric", :podspec => "#{prefix}/third-party-podspecs/RCT-Folly.podspec")
if install_rncore
check_pod("React-rncore", :path => "#{prefix}/ReactCommon")
else
assert_nil($podInvocation["React-rncore"])
end
end

def check_pod(name, path: nil, modular_headers: nil, podspec: nil)
Expand Down
4 changes: 2 additions & 2 deletions scripts/cocoapods/__tests__/new_architecture-test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ def test_installModulesDependencies_whenNewArchEnabledAndNewArchAndNoSearchPaths

# Assert
assert_equal(spec.compiler_flags, NewArchitectureHelper.folly_compiler_flags)
assert_equal(spec.pod_target_xcconfig["HEADER_SEARCH_PATHS"], "\"$(PODS_ROOT)/boost\"")
assert_equal(spec.pod_target_xcconfig["HEADER_SEARCH_PATHS"], "\"$(PODS_ROOT)/boost\" \"$(PODS_ROOT)/DoubleConversion\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers/react/renderer/graphics/platform/ios\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core\"")
assert_equal(spec.pod_target_xcconfig["CLANG_CXX_LANGUAGE_STANDARD"], "c++17")
assert_equal(spec.pod_target_xcconfig["OTHER_CPLUSPLUSFLAGS"], "$(inherited) -DRCT_NEW_ARCH_ENABLED=1 -DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1")
assert_equal(
Expand Down Expand Up @@ -190,7 +190,7 @@ def test_installModulesDependencies_whenNewArchDisabledAndSearchPathsAndCompiler

# Assert
assert_equal(spec.compiler_flags, "-Wno-nullability-completeness #{NewArchitectureHelper.folly_compiler_flags}")
assert_equal(spec.pod_target_xcconfig["HEADER_SEARCH_PATHS"], "#{other_flags} \"$(PODS_ROOT)/boost\"")
assert_equal(spec.pod_target_xcconfig["HEADER_SEARCH_PATHS"], "#{other_flags} \"$(PODS_ROOT)/boost\" \"$(PODS_ROOT)/DoubleConversion\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers/react/renderer/graphics/platform/ios\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers\" \"${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core\"")
assert_equal(spec.pod_target_xcconfig["CLANG_CXX_LANGUAGE_STANDARD"], "c++17")
assert_equal(
spec.dependencies,
Expand Down
67 changes: 67 additions & 0 deletions scripts/cocoapods/__tests__/utils-test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -533,8 +533,75 @@ def test_detectUseFrameworks_whenEnvNotSetAndDynamicFrameworks_setEnvVarToDynami
assert_equal(Pod::UI.collected_messages, ["Framework build type is dynamic framework"])
assert_equal(ENV['USE_FRAMEWORKS'], 'dynamic')
end

# ============================ #
# Test - Update Search Paths #
# ============================ #
def test_updateSearchPaths_whenUseFrameworks_addsSearchPaths
# Arrange
ENV['USE_FRAMEWORKS'] = 'static'
first_target = prepare_target("FirstTarget")
second_target = prepare_target("SecondTarget")
third_target = prepare_target("ThirdTarget", "com.apple.product-type.bundle")
user_project_mock = UserProjectMock.new("a/path", [
prepare_config("Debug"),
prepare_config("Release"),
],
:native_targets => [
first_target,
second_target
]
)
pods_projects_mock = PodsProjectMock.new([third_target], {"hermes-engine" => {}})
installer = InstallerMock.new(pods_projects_mock, [
AggregatedProjectMock.new(user_project_mock)
])

# Act
ReactNativePodsUtils.update_search_paths(installer)

# Assert
user_project_mock.build_configurations.each do |config|
received_search_path = config.build_settings["HEADER_SEARCH_PATHS"]
expected_search_path = "$(inherited) ${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core/platform/ios ${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core ${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/samples/platform/ios ${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/samples"
assert_equal(expected_search_path, received_search_path)
end
end

def test_updateSearchPaths_whenNotUseFrameworks_addsSearchPaths
# Arrange
first_target = prepare_target("FirstTarget")
second_target = prepare_target("SecondTarget")
third_target = prepare_target("ThirdTarget", "com.apple.product-type.bundle")
user_project_mock = UserProjectMock.new("a/path", [
prepare_config("Debug"),
prepare_config("Release"),
],
:native_targets => [
first_target,
second_target
]
)
pods_projects_mock = PodsProjectMock.new([third_target], {"hermes-engine" => {}})
installer = InstallerMock.new(pods_projects_mock, [
AggregatedProjectMock.new(user_project_mock)
])

# Act
ReactNativePodsUtils.update_search_paths(installer)

# Assert
user_project_mock.build_configurations.each do |config|
assert_nil(config.build_settings["HEADER_SEARCH_PATHS"])
end
end
end


# ===== #
# UTILS #
# ===== #

def prepare_empty_user_project_mock
return UserProjectMock.new("a/path", [
BuildConfigurationMock.new("Debug"),
Expand Down
47 changes: 36 additions & 11 deletions scripts/cocoapods/codegen_utils.rb
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,35 @@ def generate_react_codegen_podspec!(spec, codegen_output_dir, file_manager: File
def get_react_codegen_spec(package_json_file, folly_version: '2021.07.22.00', fabric_enabled: false, hermes_enabled: true, script_phases: nil, file_manager: File)
package = JSON.parse(file_manager.read(package_json_file))
version = package['version']

new_arch_disabled = ENV['RCT_NEW_ARCH_ENABLED'] != "1"
use_frameworks = ENV['USE_FRAMEWORKS'] != nil
folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-comma -Wno-shorten-64-to-32'
boost_compiler_flags = '-Wno-documentation'

header_search_paths = [
"\"$(PODS_ROOT)/boost\"",
"\"$(PODS_ROOT)/RCT-Folly\"",
"\"${PODS_ROOT}/Headers/Public/React-Codegen/react/renderer/components\"",
"\"$(PODS_ROOT)/Headers/Private/React-Fabric\"",
"\"$(PODS_ROOT)/Headers/Private/React-RCTFabric\"",
]
framework_search_paths = []

if use_frameworks
header_search_paths.concat([
"\"$(PODS_ROOT)/DoubleConversion\"",
"\"$(PODS_TARGET_SRCROOT)\"",
"\"$(PODS_CONFIGURATION_BUILD_DIR)/React-Fabric/React_Fabric.framework/Headers\"",
"\"$(PODS_CONFIGURATION_BUILD_DIR)/React-graphics/React_graphics.framework/Headers\"",
"\"$(PODS_CONFIGURATION_BUILD_DIR)/React-graphics/React_graphics.framework/Headers/react/renderer/graphics/platform/ios\"",
"\"$(PODS_CONFIGURATION_BUILD_DIR)/ReactCommon/ReactCommon.framework/Headers\"",
"\"$(PODS_CONFIGURATION_BUILD_DIR)/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core\"",
"\"$(PODS_CONFIGURATION_BUILD_DIR)/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core/platform/ios\""
])

framework_search_paths << "\"${PODS_CONFIGURATION_BUILD_DIR}/React-RCTFabric\""
end

spec = {
'name' => "React-Codegen",
'version' => version,
Expand All @@ -90,17 +115,11 @@ def get_react_codegen_spec(package_json_file, folly_version: '2021.07.22.00', fa
'ios' => '11.0',
},
'source_files' => "**/*.{h,mm,cpp}",
'pod_target_xcconfig' => { "HEADER_SEARCH_PATHS" =>
[
"\"$(PODS_ROOT)/boost\"",
"\"$(PODS_ROOT)/RCT-Folly\"",
"\"${PODS_ROOT}/Headers/Public/React-Codegen/react/renderer/components\"",
"\"$(PODS_ROOT)/Headers/Private/React-Fabric\"",
"\"$(PODS_ROOT)/Headers/Private/React-RCTFabric\"",
].join(' ')
'pod_target_xcconfig' => {
"HEADER_SEARCH_PATHS" => header_search_paths.join(' '),
"FRAMEWORK_SEARCH_PATHS" => framework_search_paths
},
'dependencies': {
"FBReactNativeSpec": [],
"React-jsiexecutor": [],
"RCT-Folly": [],
"RCTRequired": [],
Expand All @@ -115,7 +134,6 @@ def get_react_codegen_spec(package_json_file, folly_version: '2021.07.22.00', fa
if fabric_enabled
spec[:'dependencies'].merge!({
'React-graphics': [],
'React-rncore': [],
});
end

Expand All @@ -129,6 +147,13 @@ def get_react_codegen_spec(package_json_file, folly_version: '2021.07.22.00', fa
});
end

if new_arch_disabled
spec[:dependencies].merge!({
'React-rncore': [],
'FBReactNativeSpec': [],
})
end

if script_phases
Pod::UI.puts "[Codegen] Adding script_phases to React-Codegen."
spec[:'script_phases'] = script_phases
Expand Down
6 changes: 4 additions & 2 deletions scripts/cocoapods/fabric.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@
# It sets up the Fabric dependencies.
#
# @parameter react_native_path: relative path to react-native
def setup_fabric!(react_native_path: "../node_modules/react-native")
def setup_fabric!(react_native_path: "../node_modules/react-native", new_arch_enabled: false)
pod 'React-Fabric', :path => "#{react_native_path}/ReactCommon"
pod 'React-rncore', :path => "#{react_native_path}/ReactCommon"
pod 'React-graphics', :path => "#{react_native_path}/ReactCommon/react/renderer/graphics"
pod 'React-RCTFabric', :path => "#{react_native_path}/React", :modular_headers => true
pod 'RCT-Folly/Fabric', :podspec => "#{react_native_path}/third-party-podspecs/RCT-Folly.podspec"


pod 'React-rncore', :path => "#{react_native_path}/ReactCommon" if !new_arch_enabled
end
16 changes: 13 additions & 3 deletions scripts/cocoapods/new_architecture.rb
Original file line number Diff line number Diff line change
Expand Up @@ -79,10 +79,20 @@ def self.install_modules_dependencies(spec, new_arch_enabled, folly_version)
current_config = hash["pod_target_xcconfig"] != nil ? hash["pod_target_xcconfig"] : {}
current_headers = current_config["HEADER_SEARCH_PATHS"] != nil ? current_config["HEADER_SEARCH_PATHS"] : ""

boost_search_path = "\"$(PODS_ROOT)/boost\""

header_search_paths = ["\"$(PODS_ROOT)/boost\""]
if ENV['USE_FRAMEWORKS']
header_search_paths << "\"$(PODS_ROOT)/DoubleConversion\""
header_search_paths << "\"${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers\""
header_search_paths << "\"${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers/react/renderer/graphics/platform/ios\""
header_search_paths << "\"${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.framework/Headers\""
header_search_paths << "\"${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers\""
header_search_paths << "\"${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core\""
end
header_search_paths_string = header_search_paths.join(" ")
spec.compiler_flags = compiler_flags.empty? ? @@folly_compiler_flags : "#{compiler_flags} #{@@folly_compiler_flags}"
current_config["HEADER_SEARCH_PATHS"] = current_headers.empty? ? boost_search_path : "#{current_headers} #{boost_search_path}"
current_config["HEADER_SEARCH_PATHS"] = current_headers.empty? ?
header_search_paths_string :
"#{current_headers} #{header_search_paths_string}"
current_config["CLANG_CXX_LANGUAGE_STANDARD"] = @@cplusplus_version


Expand Down
26 changes: 26 additions & 0 deletions scripts/cocoapods/utils.rb
Original file line number Diff line number Diff line change
Expand Up @@ -185,4 +185,30 @@ def self.detect_use_frameworks(target_definition)
ENV['USE_FRAMEWORKS'] = nil
end
end

def self.update_search_paths(installer)
return if ENV['USE_FRAMEWORKS'] == nil

projects = installer.aggregate_targets
.map{ |t| t.user_project }
.uniq{ |p| p.path }
.push(installer.pods_project)

projects.each do |project|
project.build_configurations.each do |config|
header_search_paths = config.build_settings["HEADER_SEARCH_PATHS"] ||= "$(inherited)"

if !header_search_paths.include?("${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core/platform/ios")
header_search_paths << " ${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core/platform/ios"
header_search_paths << " ${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core"
header_search_paths << " ${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/samples/platform/ios"
header_search_paths << " ${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/samples"
end

config.build_settings["HEADER_SEARCH_PATHS"] = header_search_paths
end

project.save()
end
end
end
5 changes: 3 additions & 2 deletions scripts/react_native_pods.rb
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ def use_react_native! (

# The Pods which should be included in all projects
pod 'FBLazyVector', :path => "#{prefix}/Libraries/FBLazyVector"
pod 'FBReactNativeSpec', :path => "#{prefix}/React/FBReactNativeSpec"
pod 'FBReactNativeSpec', :path => "#{prefix}/React/FBReactNativeSpec" if !new_arch_enabled
pod 'RCTRequired', :path => "#{prefix}/Libraries/RCTRequired"
pod 'RCTTypeSafety', :path => "#{prefix}/Libraries/TypeSafety", :modular_headers => true
pod 'React', :path => "#{prefix}/"
Expand Down Expand Up @@ -140,7 +140,7 @@ def use_react_native! (

if fabric_enabled
checkAndGenerateEmptyThirdPartyProvider!(prefix, new_arch_enabled, $CODEGEN_OUTPUT_DIR)
setup_fabric!(:react_native_path => prefix)
setup_fabric!(:react_native_path => prefix, new_arch_enabled: new_arch_enabled)
else
relative_installation_root = Pod::Config.instance.installation_root.relative_path_from(Pathname.pwd)
build_codegen!(prefix, relative_installation_root)
Expand Down Expand Up @@ -214,6 +214,7 @@ def react_native_post_install(installer, react_native_path = "../node_modules/re

ReactNativePodsUtils.exclude_i386_architecture_while_using_hermes(installer)
ReactNativePodsUtils.fix_library_search_paths(installer)
ReactNativePodsUtils.update_search_paths(installer)
ReactNativePodsUtils.set_node_modules_user_settings(installer, react_native_path)

NewArchitectureHelper.set_clang_cxx_language_standard_if_needed(installer)
Expand Down

0 comments on commit 6d34952

Please sign in to comment.