From 82e9c6ad611f1fb816de056ff031716f8cb24b4e Mon Sep 17 00:00:00 2001 From: Riccardo Cipolleschi Date: Fri, 9 Sep 2022 04:25:56 -0700 Subject: [PATCH] Simplify the dependencies migration for new libraries (#34619) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/34619 When it comes to migrate existing libraries, users needs to update their .podspec files with a bunch [of changes](https://reactnative.dev/docs/0.69/new-architecture-library-ios#add-folly-and-other-dependencies). This diff groups those changes in a single function, so that contributors can just invoke that function to prepare their dependencies. ## Changelog [iOS][Changed] - Add function to simplify podspecs Reviewed By: cortinico Differential Revision: D39312203 fbshipit-source-id: ed631839e07d472a1fdcba33310f9b1d94fe2fd7 --- .../MyNativeView.podspec | 13 ++--- .../ScreenshotManager.podspec | 8 +-- .../__tests__/new_architecture-test.rb | 51 +++++++++++++++++++ .../__tests__/test_utils/SpecMock.rb | 30 +++++++++++ scripts/cocoapods/new_architecture.rb | 37 +++++++++++++- scripts/react_native_pods.rb | 23 +++++++-- 6 files changed, 141 insertions(+), 21 deletions(-) create mode 100644 scripts/cocoapods/__tests__/test_utils/SpecMock.rb diff --git a/packages/rn-tester/NativeComponentExample/MyNativeView.podspec b/packages/rn-tester/NativeComponentExample/MyNativeView.podspec index 45aee537e34..25defc71376 100644 --- a/packages/rn-tester/NativeComponentExample/MyNativeView.podspec +++ b/packages/rn-tester/NativeComponentExample/MyNativeView.podspec @@ -7,8 +7,6 @@ require "json" package = JSON.parse(File.read(File.join(__dir__, "../" "package.json"))) -folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-comma -Wno-shorten-64-to-32' -folly_version = '2021.07.22.00' boost_version = '1.76.0' boost_compiler_flags = '-Wno-documentation' @@ -20,23 +18,18 @@ Pod::Spec.new do |s| s.homepage = "https://github.com/sota000/my-native-view.git" s.license = "MIT" s.platforms = { :ios => "12.4", :tvos => "12.4" } - s.compiler_flags = folly_compiler_flags + ' ' + boost_compiler_flags + ' -Wno-nullability-completeness' + s.compiler_flags = boost_compiler_flags + ' -Wno-nullability-completeness' s.author = "Facebook, Inc. and its affiliates" s.source = { :git => "https://github.com/facebook/my-native-view.git", :tag => "#{s.version}" } s.pod_target_xcconfig = { - "HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/boost\" \"$(PODS_ROOT)/RCT-Folly\" \"$(PODS_ROOT)/boost\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-Codegen/React_Codegen.framework/Headers\"", + "HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/RCT-Folly\" \"$(PODS_ROOT)/boost\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-Codegen/React_Codegen.framework/Headers\"", "CLANG_CXX_LANGUAGE_STANDARD" => "c++17" } s.source_files = "ios/**/*.{h,m,mm,cpp}" s.requires_arc = true - s.dependency "React" - s.dependency "React-RCTFabric" - s.dependency "React-Codegen" - s.dependency "RCTRequired" - s.dependency "RCTTypeSafety" - s.dependency "ReactCommon/turbomodule/core" + install_modules_dependencies(s) # Enable codegen for this library use_react_native_codegen!(s, { diff --git a/packages/rn-tester/NativeModuleExample/ScreenshotManager.podspec b/packages/rn-tester/NativeModuleExample/ScreenshotManager.podspec index 00cde709b2f..49e75393a61 100644 --- a/packages/rn-tester/NativeModuleExample/ScreenshotManager.podspec +++ b/packages/rn-tester/NativeModuleExample/ScreenshotManager.podspec @@ -7,9 +7,6 @@ require "json" package = JSON.parse(File.read(File.join(__dir__, "../package.json"))) -folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-comma -Wno-shorten-64-to-32' -folly_version = '2021.07.22.00' - Pod::Spec.new do |s| s.name = "ScreenshotManager" s.version = package["version"] @@ -18,15 +15,14 @@ Pod::Spec.new do |s| s.homepage = "https://github.com/facebook/react-native.git" s.license = "MIT" s.platforms = { :ios => "12.4", :tvos => "12.4" } - s.compiler_flags = folly_compiler_flags + ' -Wno-nullability-completeness' + s.compiler_flags = '-Wno-nullability-completeness' s.author = "Facebook, Inc. and its affiliates" s.source = { :git => "https://github.com/facebook/react-native.git", :tag => "#{s.version}" } s.source_files = "**/*.{h,m,mm,swift}" s.requires_arc = true - s.dependency "React-Core" - s.dependency "RCT-Folly", folly_version + install_modules_dependencies(s) # s.dependency "..." diff --git a/scripts/cocoapods/__tests__/new_architecture-test.rb b/scripts/cocoapods/__tests__/new_architecture-test.rb index cc6461675ee..a3ee9fd3ff5 100644 --- a/scripts/cocoapods/__tests__/new_architecture-test.rb +++ b/scripts/cocoapods/__tests__/new_architecture-test.rb @@ -7,6 +7,7 @@ require "test/unit" require_relative "../new_architecture.rb" require_relative "./test_utils/InstallerMock.rb" require_relative "./test_utils/PodMock.rb" +require_relative "./test_utils/SpecMock.rb" class NewArchitectureTests < Test::Unit::TestCase def teardown @@ -109,6 +110,56 @@ class NewArchitectureTests < Test::Unit::TestCase assert_equal(yoga_debug_config.build_settings["OTHER_CPLUSPLUSFLAGS"], "$(inherited)") assert_equal(yoga_release_config.build_settings["OTHER_CPLUSPLUSFLAGS"], "$(inherited)") end + + # =================================== # + # Test - install Modules Dependencies # + # =================================== # + def test_installModulesDependencies_whenNewArchEnabledAndNewArchAndNoSearchPathsNorCompilerFlagsArePresent_itInstallDependencies + # Arrange + spec = SpecMock.new + + # Act + NewArchitectureHelper.install_modules_dependencies(spec, true, '2021.07.22.00') + + # 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.dependencies, + [ + { :dependency_name => "React-Core" }, + { :dependency_name => "RCT-Folly", "version"=>"2021.07.22.00" }, + { :dependency_name => "React-RCTFabric" }, + { :dependency_name => "React-Codegen" }, + { :dependency_name => "RCTRequired" }, + { :dependency_name => "RCTTypeSafety" }, + { :dependency_name => "ReactCommon/turbomodule/core" } + ]) + end + + def test_installModulesDependencies_whenNewArchDisabledAndSearchPathsAndCompilerFlagsArePresent_itInstallDependenciesAndPreserveOtherSettings + # Arrange + spec = SpecMock.new + spec.compiler_flags = '-Wno-nullability-completeness' + other_flags = "\"$(PODS_ROOT)/RCT-Folly\" \"$(PODS_ROOT)/boost\" \"${PODS_CONFIGURATION_BUILD_DIR}/React-Codegen/React_Codegen.framework/Headers\"" + spec.pod_target_xcconfig = { + "HEADER_SEARCH_PATHS" => other_flags + } + + # Act + NewArchitectureHelper.install_modules_dependencies(spec, false, '2021.07.22.00') + + # 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.dependencies, + [ + { :dependency_name => "React-Core" }, + { :dependency_name => "RCT-Folly", "version"=>"2021.07.22.00" }, + ] + ) + end end # ================ # diff --git a/scripts/cocoapods/__tests__/test_utils/SpecMock.rb b/scripts/cocoapods/__tests__/test_utils/SpecMock.rb new file mode 100644 index 00000000000..f53e190c2f0 --- /dev/null +++ b/scripts/cocoapods/__tests__/test_utils/SpecMock.rb @@ -0,0 +1,30 @@ +# 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. + +class SpecMock + + attr_accessor :compiler_flags + attr_accessor :pod_target_xcconfig + attr_reader :dependencies + + def initialize + @compiler_flags = "" + @pod_target_xcconfig = Hash.new + @dependencies = [] + end + + def dependency(dependency_name, version = nil) + toPush = {"dependency_name": dependency_name} + toPush["version"] = version if version + @dependencies.push(toPush) + end + + def to_hash + return { + "compiler_flags" => @compiler_flags, + "pod_target_xcconfig" => @pod_target_xcconfig, + } + end +end diff --git a/scripts/cocoapods/new_architecture.rb b/scripts/cocoapods/new_architecture.rb index 166a2ed7879..24a9f076e6c 100644 --- a/scripts/cocoapods/new_architecture.rb +++ b/scripts/cocoapods/new_architecture.rb @@ -4,8 +4,11 @@ # LICENSE file in the root directory of this source tree. class NewArchitectureHelper + @@shared_flags = "-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1" - @@new_arch_cpp_flags = '$(inherited) -DRCT_NEW_ARCH_ENABLED=1 -DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1' + @@folly_compiler_flags = "#{@@shared_flags} -Wno-comma -Wno-shorten-64-to-32" + + @@new_arch_cpp_flags = "$(inherited) -DRCT_NEW_ARCH_ENABLED=1 #{@@shared_flags}" def self.set_clang_cxx_language_standard_if_needed(installer) language_standard = nil @@ -56,4 +59,36 @@ class NewArchitectureHelper end end end + + def self.install_modules_dependencies(spec, new_arch_enabled, folly_version) + # Pod::Specification does not have getters so, we have to read + # the existing values from a hash representation of the object. + hash = spec.to_hash + + compiler_flags = hash["compiler_flags"] ? hash["compiler_flags"] : "" + 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\"" + + 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}" + spec.pod_target_xcconfig = current_config + + spec.dependency "React-Core" + spec.dependency "RCT-Folly", '2021.07.22.00' + + if new_arch_enabled + spec.dependency "React-RCTFabric" # This is for Fabric Component + spec.dependency "React-Codegen" + + spec.dependency "RCTRequired" + spec.dependency "RCTTypeSafety" + spec.dependency "ReactCommon/turbomodule/core" + end + end + + def self.folly_compiler_flags + return @@folly_compiler_flags + end end diff --git a/scripts/react_native_pods.rb b/scripts/react_native_pods.rb index af9593219d4..50a168fceae 100644 --- a/scripts/react_native_pods.rb +++ b/scripts/react_native_pods.rb @@ -19,6 +19,7 @@ require_relative './cocoapods/local_podspec_patch.rb' $CODEGEN_OUTPUT_DIR = 'build/generated/ios' $CODEGEN_COMPONENT_DIR = 'react/renderer/components' $CODEGEN_MODULE_DIR = '.' +$FOLLY_VERSION = '2021.07.22.00' $START_TIME = Time.now.to_i @@ -49,9 +50,6 @@ def use_react_native! ( prefix = path - # The version of folly that must be used - folly_version = '2021.07.22.00' - ReactNativePodsUtils.warn_if_not_on_arm64() # The Pods which should be included in all projects @@ -100,7 +98,7 @@ def use_react_native! ( :fabric_enabled => fabric_enabled, :codegen_output_dir => $CODEGEN_OUTPUT_DIR, :package_json_file => File.join(__dir__, "..", "package.json"), - :folly_version => folly_version + :folly_version => $FOLLY_VERSION ) pod 'React-Codegen', :path => $CODEGEN_OUTPUT_DIR, :modular_headers => true @@ -131,6 +129,23 @@ def use_react_native! ( end end +# Getter to retrieve the folly flags in case contributors need to apply them manually. +# +# Returns: the folly compiler flags +def folly_flags() + return NewArchitectureHelper.folly_compiler_flags +end + +# This function can be used by library developer to prepare their modules for the New Architecture. +# It passes the Folly Flags to the module, it configures the search path and installs some New Architecture specific dependencies. +# +# Parameters: +# - spec: The spec that has to be configured with the New Architecture code +# - new_arch_enabled: Whether the module should install dependencies for the new architecture +def install_modules_dependencies(spec, new_arch_enabled: ENV['RCT_NEW_ARCH_ENABLED'] == "1") + NewArchitectureHelper.install_modules_dependencies(spec, new_arch_enabled, $FOLLY_VERSION) +end + # It returns the default flags. def get_default_flags() return ReactNativePodsUtils.get_default_flags()