Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 25 additions & 24 deletions packages/react-native/ReactCommon/React-Fabric.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,27 @@ end

react_native_path = ".."

header_search_path = [
"\"$(PODS_TARGET_SRCROOT)/ReactCommon\"",
"\"$(PODS_ROOT)/Headers/Private/Yoga\"",
"\"$(PODS_TARGET_SRCROOT)\""
]

if ENV['USE_FRAMEWORKS']
header_search_path = header_search_path + [
"\"$(PODS_TARGET_SRCROOT)/react/renderer/textlayoutmanager/platform/ios\"",
"\"$(PODS_TARGET_SRCROOT)/react/renderer/components/scrollview/platform/cxx\"",
"\"$(PODS_TARGET_SRCROOT)/react/renderer/components/scrollview/platform/ios\"",
"\"$(PODS_TARGET_SRCROOT)/react/renderer/components/legacyviewmanagerinterop/platform/ios\"",
"\"$(PODS_TARGET_SRCROOT)/react/renderer/components/text/platform/cxx\"",
"\"$(PODS_TARGET_SRCROOT)/react/renderer/components/textinput/platform/ios\"",
"\"$(PODS_TARGET_SRCROOT)/react/renderer/components/view/platform/cxx\"",
"\"$(PODS_TARGET_SRCROOT)/react/renderer/components/view\"",
"\"$(PODS_TARGET_SRCROOT)/react/renderer/core\"",
"\"$(PODS_TARGET_SRCROOT)/react/renderer/debug\"",
]
end

Pod::Spec.new do |s|
s.name = "React-Fabric"
s.version = version
Expand All @@ -30,7 +51,8 @@ Pod::Spec.new do |s|
s.source_files = podspec_sources("dummyFile.cpp", "")
s.pod_target_xcconfig = { "USE_HEADERMAP" => "YES",
"CLANG_CXX_LANGUAGE_STANDARD" => rct_cxx_language_standard(),
"DEFINES_MODULE" => "YES" }
"DEFINES_MODULE" => "YES",
"HEADER_SEARCH_PATHS" => header_search_path.join(" ") }

resolve_use_frameworks(s, header_mappings_dir: "./", module_name: "React_Fabric")

Expand Down Expand Up @@ -89,32 +111,9 @@ Pod::Spec.new do |s|
end

s.subspec "core" do |ss|
header_search_path = [
"\"$(PODS_TARGET_SRCROOT)/ReactCommon\"",
"\"$(PODS_ROOT)/Headers/Private/Yoga\"",
"\"$(PODS_TARGET_SRCROOT)\""
]

if ENV['USE_FRAMEWORKS']
header_search_path = header_search_path + [
"\"$(PODS_TARGET_SRCROOT)/react/renderer/textlayoutmanager/platform/ios\"",
"\"$(PODS_TARGET_SRCROOT)/react/renderer/components/scrollview/platform/cxx\"",
"\"$(PODS_TARGET_SRCROOT)/react/renderer/components/scrollview/platform/ios\"",
"\"$(PODS_TARGET_SRCROOT)/react/renderer/components/legacyviewmanagerinterop/platform/ios\"",
"\"$(PODS_TARGET_SRCROOT)/react/renderer/components/text/platform/cxx\"",
"\"$(PODS_TARGET_SRCROOT)/react/renderer/components/textinput/platform/ios\"",
"\"$(PODS_TARGET_SRCROOT)/react/renderer/components/view/platform/cxx\"",
"\"$(PODS_TARGET_SRCROOT)/react/renderer/core\"",
"\"$(PODS_TARGET_SRCROOT)/react/renderer/debug\"",
]
end

ss.source_files = podspec_sources("react/renderer/core/**/*.{m,mm,cpp,h}", "react/renderer/core/**/*.{h}")
ss.exclude_files = ["react/renderer/core/tests", "react/renderer/core/React"]
ss.header_dir = "react/renderer/core"
ss.pod_target_xcconfig = {
"HEADER_SEARCH_PATHS" => header_search_path.join(" ")
}
end

s.subspec "coreUmbrella" do |ss|
Expand All @@ -141,6 +140,8 @@ Pod::Spec.new do |s|

s.subspec "components" do |ss|
ss.subspec "root" do |sss|
sss.dependency "React-Fabric/coreUmbrella"
sss.dependency "React-Fabric/components/viewUmbrella"
sss.source_files = podspec_sources("react/renderer/components/root/**/*.{m,mm,cpp,h}", "react/renderer/components/root/**/*.{h}")
sss.exclude_files = "react/renderer/components/root/tests"
sss.header_dir = "react/renderer/components/root"
Expand Down
90 changes: 88 additions & 2 deletions packages/react-native/scripts/cocoapods/__tests__/utils-test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -732,7 +732,12 @@ def test_updateSearchPaths_whenUseFrameworks_addsSearchPaths
second_target
]
)
pods_projects_mock = PodsProjectMock.new([third_target], {"hermes-engine" => {}})
pods_projects_mock = PodsProjectMock.new(
[third_target],
{"hermes-engine" => {}},
"test/path-pod.xcodeproj",
[prepare_config("Debug"), prepare_config("Release")]
)
installer = InstallerMock.new(pods_projects_mock, [
AggregatedProjectMock.new(user_project_mock)
])
Expand All @@ -743,10 +748,15 @@ def test_updateSearchPaths_whenUseFrameworks_addsSearchPaths
# 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 ${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core ${PODS_CONFIGURATION_BUILD_DIR}/React-runtimeexecutor/React_runtimeexecutor.framework/Headers ${PODS_CONFIGURATION_BUILD_DIR}/React-runtimeexecutor/React_runtimeexecutor.framework/Headers/platform/ios ${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon-Samples/ReactCommon_Samples.framework/Headers ${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon-Samples/ReactCommon_Samples.framework/Headers/platform/ios ${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.framework/Headers/react/renderer/components/view/platform/cxx ${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.framework/Headers ${PODS_CONFIGURATION_BUILD_DIR}/React-debug/React_debug.framework/Headers ${PODS_CONFIGURATION_BUILD_DIR}/React-rendererdebug/React_rendererdebug.framework/Headers ${PODS_CONFIGURATION_BUILD_DIR}/React-timing/React_timing.framework/Headers ${PODS_CONFIGURATION_BUILD_DIR}/React-utils/React_utils.framework/Headers ${PODS_CONFIGURATION_BUILD_DIR}/React-NativeModulesApple/React_NativeModulesApple.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}/React-featureflags/React_featureflags.framework/Headers ${PODS_CONFIGURATION_BUILD_DIR}/React-renderercss/React_renderercss.framework/Headers ${PODS_CONFIGURATION_BUILD_DIR}/React-cxxstableapi/React_cxxstableapi.framework/Headers"
expected_search_path = "$(inherited) ${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers ${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core ${PODS_CONFIGURATION_BUILD_DIR}/React-runtimeexecutor/React_runtimeexecutor.framework/Headers ${PODS_CONFIGURATION_BUILD_DIR}/React-runtimeexecutor/React_runtimeexecutor.framework/Headers/platform/ios ${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon-Samples/ReactCommon_Samples.framework/Headers ${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon-Samples/ReactCommon_Samples.framework/Headers/platform/ios ${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.framework/Headers/react/renderer/components/view/platform/cxx ${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.framework/Headers/react/renderer/components/scrollview/platform/cxx ${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.framework/Headers/react/renderer/components/scrollview/platform/ios ${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.framework/Headers ${PODS_CONFIGURATION_BUILD_DIR}/React-debug/React_debug.framework/Headers ${PODS_CONFIGURATION_BUILD_DIR}/React-rendererdebug/React_rendererdebug.framework/Headers ${PODS_CONFIGURATION_BUILD_DIR}/React-timing/React_timing.framework/Headers ${PODS_CONFIGURATION_BUILD_DIR}/React-utils/React_utils.framework/Headers ${PODS_CONFIGURATION_BUILD_DIR}/React-FabricComponents/React_FabricComponents.framework/Headers/react/renderer/textlayoutmanager/platform/ios ${PODS_CONFIGURATION_BUILD_DIR}/React-FabricComponents/React_FabricComponents.framework/Headers/react/renderer/components/text/platform/cxx ${PODS_CONFIGURATION_BUILD_DIR}/React-FabricComponents/React_FabricComponents.framework/Headers/react/renderer/components/textinput/platform/ios ${PODS_CONFIGURATION_BUILD_DIR}/React-FabricComponents/React_FabricComponents.framework/Headers/react/renderer/components/switch/iosswitch ${PODS_CONFIGURATION_BUILD_DIR}/React-NativeModulesApple/React_NativeModulesApple.framework/Headers ${PODS_CONFIGURATION_BUILD_DIR}/React-bridging/React_bridging.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}/React-featureflags/React_featureflags.framework/Headers ${PODS_CONFIGURATION_BUILD_DIR}/React-renderercss/React_renderercss.framework/Headers ${PODS_CONFIGURATION_BUILD_DIR}/React-cxxstableapi/React_cxxstableapi.framework/Headers"
assert_equal(expected_search_path, received_search_path)
end

pods_projects_mock.build_configurations.each do |config|
received_search_paths = Shellwords.shellsplit(config.build_settings["HEADER_SEARCH_PATHS"])
assert_false(received_search_paths.include?("${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.framework/Headers"))
end

installer.target_installation_results.pod_target_installation_results.each do |pod_name, target_installation_result|
if pod_name == "SecondTarget"
target_installation_result.native_target.build_configurations.each do |config|
Expand Down Expand Up @@ -808,6 +818,20 @@ def test_add_search_path_if_not_included_does_not_add_existing_path_to_string
assert_equal("/path/to/headers /another/path", result)
end

def test_add_search_path_if_not_included_adds_path_that_is_prefix_of_existing_path
current_paths = "/path/to/headers/platform/ios"
new_path = "/path/to/headers"
result = ReactNativePodsUtils.add_search_path_if_not_included(current_paths, new_path)
assert_equal("/path/to/headers/platform/ios /path/to/headers", result)
end

def test_add_search_path_if_not_included_does_not_duplicate_quoted_path_with_spaces
current_paths = '"/path/with spaces/headers" /another/path'
new_path = '"/path/with spaces/headers"'
result = ReactNativePodsUtils.add_search_path_if_not_included(current_paths, new_path)
assert_equal(current_paths, result)
end

def test_add_search_path_if_not_included_does_not_add_existing_path_with_leading_space_to_string
current_paths = " /path/with/leading/space /another/path"
new_path = "/path/with/leading/space"
Expand Down Expand Up @@ -943,6 +967,68 @@ def test_createHeaderSearchPathsForStableUmbrellas_whenUsingPrebuiltCore_addsNot
assert_equal([], result)
end

def test_setStableUmbrellaSearchPaths_addsOwningFrameworkPathToDependentTarget
target = prepare_target("Consumer", nil, [DependencyMock.new("React-Fabric")])
target_installation_result = TargetInstallationResultMock.new(target, target)

ReactNativePodsUtils.set_stable_umbrella_search_paths(target_installation_result)

target.build_configurations.each do |config|
assert_equal(
'$(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.framework/Headers"',
config.build_settings["HEADER_SEARCH_PATHS"]
)
end
end

def test_setStableUmbrellaSearchPaths_addsOwningFrameworkPathToTransitivelyDependentTarget
dependency = Struct.new(:name, :target)
fabric_target = prepare_target("React-Fabric")
intermediate_target = prepare_target(
"Intermediate",
nil,
[dependency.new("React-Fabric", fabric_target)]
)
consumer_target = prepare_target(
"Consumer",
nil,
[dependency.new("Intermediate", intermediate_target)]
)
target_installation_result = TargetInstallationResultMock.new(consumer_target, consumer_target)

ReactNativePodsUtils.set_stable_umbrella_search_paths(target_installation_result)

consumer_target.build_configurations.each do |config|
assert_equal(
'$(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.framework/Headers"',
config.build_settings["HEADER_SEARCH_PATHS"]
)
end
end

def test_setStableUmbrellaSearchPaths_doesNotAddOwningFrameworkPathToUnrelatedTarget
target = prepare_target("React-Fabric")
target_installation_result = TargetInstallationResultMock.new(target, target)

ReactNativePodsUtils.set_stable_umbrella_search_paths(target_installation_result)

target.build_configurations.each do |config|
assert_nil(config.build_settings["HEADER_SEARCH_PATHS"])
end
end

def test_setStableUmbrellaSearchPaths_whenUsingPrebuiltCore_addsNothing
ReactNativeCoreUtils.class_variable_set(:@@build_from_source, false)
target = prepare_target("Consumer", nil, [DependencyMock.new("React-Fabric")])
target_installation_result = TargetInstallationResultMock.new(target, target)

ReactNativePodsUtils.set_stable_umbrella_search_paths(target_installation_result)

target.build_configurations.each do |config|
assert_nil(config.build_settings["HEADER_SEARCH_PATHS"])
end
end

# ================================= #
# TEST - Add RN_BUILDING definition #
# ================================= #
Expand Down
65 changes: 57 additions & 8 deletions packages/react-native/scripts/cocoapods/utils.rb
Original file line number Diff line number Diff line change
Expand Up @@ -358,15 +358,19 @@ def self.create_header_search_path_for_frameworks(base_folder, pod_name, framewo
def self.create_header_search_paths_for_stable_umbrellas(base_folder)
return [] unless ReactNativeCoreUtils.build_rncore_from_source()

self.stable_umbrella_frameworks.flat_map { |pod_name, framework_name|
self.create_header_search_path_for_frameworks(base_folder, pod_name, framework_name, [])
}
end

def self.stable_umbrella_frameworks
[
["React-Fabric", "React_Fabric"],
["React-debug", "React_debug"],
["React-rendererdebug", "React_rendererdebug"],
["React-timing", "React_timing"],
["React-utils", "React_utils"],
].flat_map { |pod_name, framework_name|
self.create_header_search_path_for_frameworks(base_folder, pod_name, framework_name, [])
}
]
end

# Add a new dependency to an existing spec, configuring also the headers search paths
Expand Down Expand Up @@ -399,6 +403,9 @@ def self.update_search_paths(installer)
projects = self.extract_projects(installer)

projects.each do |project|
stable_umbrella_search_paths = project == installer.pods_project ?
[] : ReactNativePodsUtils.create_header_search_paths_for_stable_umbrellas("PODS_CONFIGURATION_BUILD_DIR")

project.build_configurations.each do |config|

header_search_paths = config.build_settings["HEADER_SEARCH_PATHS"] ||= "$(inherited)"
Expand All @@ -411,7 +418,7 @@ def self.update_search_paths(installer)
"react/renderer/components/scrollview/platform/cxx",
"react/renderer/components/scrollview/platform/ios",
], false))
.concat(ReactNativePodsUtils.create_header_search_paths_for_stable_umbrellas("PODS_CONFIGURATION_BUILD_DIR"))
.concat(stable_umbrella_search_paths)
.concat(ReactNativePodsUtils.create_header_search_path_for_frameworks("PODS_CONFIGURATION_BUILD_DIR", "React-FabricComponents", "React_FabricComponents", [
"react/renderer/textlayoutmanager/platform/ios",
"react/renderer/components/text/platform/cxx",
Expand All @@ -436,6 +443,8 @@ def self.update_search_paths(installer)
end

installer.target_installation_results.pod_target_installation_results.each do |pod_name, target_installation_result|
self.set_stable_umbrella_search_paths(target_installation_result)

if self.react_native_pods.include?(pod_name) || pod_name.include?("Pod") || pod_name.include?("Tests")
next
end
Expand Down Expand Up @@ -649,7 +658,9 @@ def self.add_search_path_if_not_included(current_search_paths, new_search_path)

if current_search_paths.is_a?(String)
current_search_paths = current_search_paths.strip
return "#{current_search_paths} #{new_search_path}" unless current_search_paths.include?(new_search_path)
current_paths = Shellwords.shellsplit(current_search_paths)
normalized_new_path = Shellwords.shellsplit(new_search_path).first
return "#{current_search_paths} #{new_search_path}" unless current_paths.include?(normalized_new_path)
end

if current_search_paths.is_a?(Array)
Expand All @@ -660,17 +671,55 @@ def self.add_search_path_if_not_included(current_search_paths, new_search_path)
current_search_paths
end

def self.update_header_paths_if_depends_on(target_installation_result, dependency_name, header_paths)
depends_on_framework = target_installation_result.native_target.dependencies.any? { |d| d.name == dependency_name }
def self.target_depends_on?(target, dependency_name, visited_targets = {})
return false if target == nil

target_identifier = target.respond_to?(:uuid) ? target.uuid : target.object_id
target_identifier ||= target.object_id
return false if visited_targets[target_identifier]

visited_targets[target_identifier] = true
target.dependencies.any? do |dependency|
dependency.name == dependency_name ||
(dependency.respond_to?(:target) && self.target_depends_on?(dependency.target, dependency_name, visited_targets))
end
end

def self.update_header_paths_if_depends_on(target_installation_result, dependency_name, header_paths, include_transitive_dependencies: false)
native_target = target_installation_result.native_target
depends_on_framework = if include_transitive_dependencies
self.target_depends_on?(native_target, dependency_name)
else
native_target.dependencies.any? { |d| d.name == dependency_name }
end
if depends_on_framework
target_installation_result.native_target.build_configurations.each do |config|
native_target.build_configurations.each do |config|
header_search_path = config.build_settings["HEADER_SEARCH_PATHS"] != nil ? config.build_settings["HEADER_SEARCH_PATHS"] : "$(inherited)"
header_paths.each { |header| header_search_path = ReactNativePodsUtils.add_search_path_if_not_included(header_search_path, header) }
config.build_settings["HEADER_SEARCH_PATHS"] = header_search_path
end
end
end

def self.set_stable_umbrella_search_paths(target_installation_result)
return unless ReactNativeCoreUtils.build_rncore_from_source()

ReactNativePodsUtils.stable_umbrella_frameworks.each do |pod_name, framework_name|
header_search_paths = ReactNativePodsUtils.create_header_search_path_for_frameworks(
"PODS_CONFIGURATION_BUILD_DIR",
pod_name,
framework_name,
[]
).map { |search_path| "\"#{search_path}\"" }
ReactNativePodsUtils.update_header_paths_if_depends_on(
target_installation_result,
pod_name,
header_search_paths,
include_transitive_dependencies: true
)
end
end

def self.set_rctfolly_search_paths(target_installation_result)
ReactNativePodsUtils.update_header_paths_if_depends_on(target_installation_result, "RCT-Folly", [
"\"$(PODS_ROOT)/RCT-Folly\"",
Expand Down
Loading