Skip to content

Commit

Permalink
Mac Catalyst patches (#34026)
Browse files Browse the repository at this point in the history
Summary:
This PR adds a new method called **__apply_mac_catalyst_patches** to **scripts/react_native_pods.rb**. If it is enabled in the Podfile, it will apply three patches necessary for successful building not only for iOS and tvOS targets, but also for macOS using Apple's Mac Catalyst technology.

These 3 patches are:
- Fixing bundle signing issues by altering CODE_SIGN_IDENTITY
- Explicitly setting dead code stripping flag in project.pbxproj
- Modifying library search paths

The details were discussed here reactwg/react-native-releases#21 (comment)

## Changelog

[iOS] [Added] - Add Mac Catalyst compatibility (can be enabled in Podfile)

Pull Request resolved: #34026

Test Plan:
1. Go to project settings in Xcode, to General tab. Enable "iPad" and "Mac Catalyst" checkboxes
2. Go to "Signing & Capabilities" tab, ensure that a correct bundle id and development team are set
3. Edit Podfile, uncomment **__apply_mac_catalyst_patches(installer)** line
4. Run `pod install` in ios directory
5. Get back to Xcode, select "My Mac (Mac Catalyst)" as a target device
6. Build & run

Reviewed By: cipolleschi

Differential Revision: D37362054

Pulled By: cortinico

fbshipit-source-id: 74636f716f112289ab40968bbc8e52406c1e9579
  • Loading branch information
Arkkeeper authored and facebook-github-bot committed Jun 30, 2022
1 parent bd12e41 commit 2fb6a33
Show file tree
Hide file tree
Showing 6 changed files with 100 additions and 15 deletions.
3 changes: 2 additions & 1 deletion packages/rn-tester/Podfile
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ def pods(options = {}, use_flipper: false)
project 'RNTesterPods.xcodeproj'

fabric_enabled = true

# Hermes is now enabled by default.
# The following line will only disable Hermes if the USE_HERMES envvar is SET to a value other than 1 (e.g. USE_HERMES=0).
hermes_enabled = !ENV.has_key?('USE_HERMES') || ENV['USE_HERMES'] == '1'
Expand Down Expand Up @@ -66,6 +67,6 @@ target 'RNTesterIntegrationTests' do
end

post_install do |installer|
react_native_post_install(installer, @prefix_path)
react_native_post_install(installer, @prefix_path, :mac_catalyst_enabled => false)
__apply_Xcode_12_5_M1_post_install_workaround(installer)
end
6 changes: 5 additions & 1 deletion scripts/cocoapods/__tests__/test_utils/InstallerMock.rb
Original file line number Diff line number Diff line change
Expand Up @@ -138,12 +138,16 @@ def save_as(file_path)
class TargetMock
attr_reader :name
attr_reader :build_configurations
attr_reader :product_type

attr_reader :received_resolved_build_setting_parameters

def initialize(name, build_configurations = [])
def initialize(name, build_configurations = [], product_type = nil)
@name = name
@build_configurations = build_configurations
unless product_type.nil?
@product_type = product_type
end
@received_resolved_build_setting_parameters = []
end

Expand Down
71 changes: 60 additions & 11 deletions scripts/cocoapods/__tests__/utils-test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -266,20 +266,20 @@ def test_fixLibrarySearchPath_whenThereAreSearchPathsAndNoSwift_removesSwift5_5A
# ============================== #

def test_fixLibrarySearchPaths_correctlySetsTheSearchPathsForAllProjects
firstTarget = prepare_target("FirstTarget")
secondTarget = prepare_target("SecondTarget")
thirdTarget = prepare_target("ThirdTarget")
first_target = prepare_target("FirstTarget")
second_target = prepare_target("SecondTarget")
third_target = prepare_target("ThirdTarget")
user_project_mock = UserProjectMock.new("a/path", [
prepare_config("Debug"),
prepare_config("Release"),
],
:native_targets => [
firstTarget,
secondTarget
first_target,
second_target
]
)
pods_projects_mock = PodsProjectMock.new([], {"hermes-engine" => {}}, :native_targets => [
thirdTarget
third_target
])
installer = InstallerMock.new(pods_projects_mock, [
AggregatedProjectMock.new(user_project_mock)
Expand Down Expand Up @@ -315,6 +315,55 @@ def test_fixLibrarySearchPaths_correctlySetsTheSearchPathsForAllProjects
assert_equal(pods_projects_mock.save_invocation_count, 1)
end

# ================================= #
# Test - Apply Mac Catalyst Patches #
# ================================= #

def test_applyMacCatalystPatches_correctlyAppliesNecessaryPatches
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" => {}}, :native_targets => [])
installer = InstallerMock.new(pods_projects_mock, [
AggregatedProjectMock.new(user_project_mock)
])

# Act
ReactNativePodsUtils.apply_mac_catalyst_patches(installer)

# Assert
first_target.build_configurations.each do |config|
assert_nil(config.build_settings["CODE_SIGN_IDENTITY[sdk=macosx*]"])
end

second_target.build_configurations.each do |config|
assert_nil(config.build_settings["CODE_SIGN_IDENTITY[sdk=macosx*]"])
end

third_target.build_configurations.each do |config|
assert_equal(config.build_settings["CODE_SIGN_IDENTITY[sdk=macosx*]"], "-")
end

user_project_mock.native_targets.each do |target|
target.build_configurations.each do |config|
assert_equal(config.build_settings["DEAD_CODE_STRIPPING"], "YES")
assert_equal(config.build_settings["PRESERVE_DEAD_CODE_INITS_AND_TERMS"], "YES")
assert_equal(config.build_settings["LIBRARY_SEARCH_PATHS"], ["$(SDKROOT)/usr/lib/swift", "$(SDKROOT)/System/iOSSupport/usr/lib/swift", "$(inherited)"])
end
end

assert_equal(user_project_mock.save_invocation_count, 1)
end

# ==================================== #
# Test - Set Node_Modules User Setting #
# ==================================== #
Expand Down Expand Up @@ -357,9 +406,9 @@ def prepare_config(config_name)
]})
end

def prepare_target(name)
return TargetMock.new(name, [
prepare_config("Debug"),
prepare_config("Release")
])
def prepare_target(name, product_type = nil)
return TargetMock.new(name, [
prepare_config("Debug"),
prepare_config("Release")
], product_type)
end
24 changes: 24 additions & 0 deletions scripts/cocoapods/utils.rb
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,30 @@ def self.fix_library_search_paths(installer)
end
end

def self.apply_mac_catalyst_patches(installer)
# Fix bundle signing issues
installer.pods_project.targets.each do |target|
if target.respond_to?(:product_type) and target.product_type == "com.apple.product-type.bundle"
target.build_configurations.each do |config|
config.build_settings['CODE_SIGN_IDENTITY[sdk=macosx*]'] = '-'
end
end
end

installer.aggregate_targets.each do |aggregate_target|
aggregate_target.user_project.native_targets.each do |target|
target.build_configurations.each do |config|
# Explicitly set dead code stripping flags
config.build_settings['DEAD_CODE_STRIPPING'] = 'YES'
config.build_settings['PRESERVE_DEAD_CODE_INITS_AND_TERMS'] = 'YES'
# Modify library search paths
config.build_settings['LIBRARY_SEARCH_PATHS'] = ['$(SDKROOT)/usr/lib/swift', '$(SDKROOT)/System/iOSSupport/usr/lib/swift', '$(inherited)']
end
end
aggregate_target.user_project.save()
end
end

private

def self.fix_library_search_path(config)
Expand Down
4 changes: 3 additions & 1 deletion scripts/react_native_pods.rb
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,9 @@ def use_flipper!(versions = {}, configurations: ['Debug'])
use_flipper_pods(versions, :configurations => configurations)
end

def react_native_post_install(installer, react_native_path = "../node_modules/react-native")
def react_native_post_install(installer, react_native_path = "../node_modules/react-native", mac_catalyst_enabled: false)
ReactNativePodsUtils.apply_mac_catalyst_patches(installer) if mac_catalyst_enabled

if ReactNativePodsUtils.has_pod(installer, 'Flipper')
flipper_post_install(installer)
end
Expand Down
7 changes: 6 additions & 1 deletion template/ios/Podfile
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,12 @@ target 'HelloWorld' do
end

post_install do |installer|
react_native_post_install(installer)
react_native_post_install(
installer,
# Set `mac_catalyst_enabled` to `true` in order to apply patches
# necessary for Mac Catalyst builds
:mac_catalyst_enabled => false
)
__apply_Xcode_12_5_M1_post_install_workaround(installer)
end
end

0 comments on commit 2fb6a33

Please sign in to comment.