Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Read the React Native version and set the new arch flag properly #39388

Closed
wants to merge 4 commits into from
Closed
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
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,13 @@
require_relative "./test_utils/InstallerMock.rb"
require_relative "./test_utils/PodMock.rb"
require_relative "./test_utils/SpecMock.rb"
require_relative "./test_utils/FileMock.rb"

class NewArchitectureTests < Test::Unit::TestCase
def teardown
Pod::UI.reset()
FileMock.reset()
ENV["RCT_NEW_ARCH_ENABLED"] = nil
end

# ============================= #
Expand Down Expand Up @@ -181,6 +184,141 @@ def test_installModulesDependencies_whenNewArchDisabledAndSearchPathsAndCompiler
]
)
end

# =============================== #
# Test - Compute New Arch Enabled #
# =============================== #

def test_computeNewArchEnabled_whenOnMainAndFlagTrue_returnTrue
version = '1000.0.0'
new_arch_enabled = true

isEnabled = NewArchitectureHelper.compute_new_arch_enabled(new_arch_enabled, version)

assert_equal("1", isEnabled)
end

def test_computeNewArchEnabled_whenOnMainAndFlagFalse_returnFalse
version = '1000.0.0'
new_arch_enabled = false

isEnabled = NewArchitectureHelper.compute_new_arch_enabled(new_arch_enabled, version)

assert_equal("0", isEnabled)
end

def test_computeNewArchEnabled_whenOnStableAndFlagTrue_returnTrue
version = '0.73.0'
new_arch_enabled = true

isEnabled = NewArchitectureHelper.compute_new_arch_enabled(new_arch_enabled, version)

assert_equal("1", isEnabled)
end

def test_computeNewArchEnabled_whenOnStableAndFlagFalse_returnFalse
version = '0.73.0'
new_arch_enabled = false

isEnabled = NewArchitectureHelper.compute_new_arch_enabled(new_arch_enabled, version)

assert_equal("0", isEnabled)
end

def test_computeNewArchEnabled_whenOn100AndFlagTrue_returnTrue
version = '1.0.0-prealpha.0'
new_arch_enabled = true

isEnabled = NewArchitectureHelper.compute_new_arch_enabled(new_arch_enabled, version)

assert_equal("1", isEnabled)
end

def test_computeNewArchEnabled_whenOn100PrealphaWithDotsAndFlagFalse_returnTrue
version = '1.0.0-prealpha.0'
new_arch_enabled = false

isEnabled = NewArchitectureHelper.compute_new_arch_enabled(new_arch_enabled, version)

assert_equal("1", isEnabled)
end

def test_computeNewArchEnabled_whenOn100PrealphaWithDashAndFlagFalse_returnTrue
version = '1.0.0-prealpha-0'
new_arch_enabled = false

isEnabled = NewArchitectureHelper.compute_new_arch_enabled(new_arch_enabled, version)

assert_equal("1", isEnabled)
end

def test_computeNewArchEnabled_whenOn100PrealphaOnlyWordsAndFlagFalse_returnTrue
version = '1.0.0-prealpha0'
new_arch_enabled = false

isEnabled = NewArchitectureHelper.compute_new_arch_enabled(new_arch_enabled, version)

assert_equal("1", isEnabled)
end

def test_computeNewArchEnabled_whenOnGreaterThan100AndFlagFalse_returnTrue
version = '3.2.1'
new_arch_enabled = false

isEnabled = NewArchitectureHelper.compute_new_arch_enabled(new_arch_enabled, version)

assert_equal("1", isEnabled)
end

# =================================== #
# Test - Extract React Native Version #
# =================================== #
def test_extractReactNativeVersion_whenFileDoesNotExists_raiseError()
react_native_path = './node_modules/react-native/'

exception = assert_raise(RuntimeError) do
NewArchitectureHelper.extract_react_native_version(react_native_path, :file_manager => FileMock)
end

assert_equal("Couldn't find the React Native package.json file at ./node_modules/react-native/package.json", exception.message)
end

def test_extractReactNativeVersion_whenFileExists_returnTheRightVersion()
react_native_path = "./node_modules/react-native/"
full_path = File.join(react_native_path, "package.json")
json = "{\"version\": \"1.0.0-prealpha.0\"}"
FileMock.mocked_existing_files([full_path])
FileMock.files_to_read({
full_path => json
})

version = NewArchitectureHelper.extract_react_native_version(react_native_path, :file_manager => FileMock)

assert_equal("1.0.0-prealpha.0", version)
end

# =============================== #
# Test - New Architecture Enabled #
# =============================== #
def test_newArchEnabled_whenRCTNewArchEnabledIsSetTo1_returnTrue
ENV["RCT_NEW_ARCH_ENABLED"] = "1"
is_enabled = NewArchitectureHelper.new_arch_enabled
assert_true(is_enabled)
end

def test_newArchEnabled_whenRCTNewArchEnabledIsSetTo0_returnFalse
ENV["RCT_NEW_ARCH_ENABLED"] = "0"
is_enabled = NewArchitectureHelper.new_arch_enabled
assert_false(is_enabled)
end

def test_newArchEnabled_whenRCTNewArchEnabledIsNotSet_returnFalse
ENV["RCT_NEW_ARCH_ENABLED"] = nil
is_enabled = NewArchitectureHelper.new_arch_enabled
assert_false(is_enabled)
end


end

# ================ #
Expand Down
39 changes: 39 additions & 0 deletions packages/react-native/scripts/cocoapods/new_architecture.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.

require 'json'

class NewArchitectureHelper
@@shared_flags = "-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1"

Expand Down Expand Up @@ -72,6 +74,7 @@ def self.modify_flags_for_new_architecture(installer, is_new_arch_enabled)
# Set "RCT_DYNAMIC_FRAMEWORKS=1" if pod are installed with USE_FRAMEWORKS=dynamic
# This helps with backward compatibility.
if pod_name == 'React-RCTFabric' && ENV['USE_FRAMEWORKS'] == 'dynamic'
Pod::UI.puts "Setting -DRCT_DYNAMIC_FRAMEWORKS=1 to React-RCTFabric".green
rct_dynamic_framework_flag = " -DRCT_DYNAMIC_FRAMEWORKS=1"
target_installation_result.native_target.build_configurations.each do |config|
prev_build_settings = config.build_settings['OTHER_CPLUSPLUSFLAGS'] != nil ? config.build_settings['OTHER_CPLUSPLUSFLAGS'] : "$(inherithed)"
Expand Down Expand Up @@ -158,4 +161,40 @@ def self.install_modules_dependencies(spec, new_arch_enabled, folly_version)
def self.folly_compiler_flags
return @@folly_compiler_flags
end

def self.extract_react_native_version(react_native_path, file_manager: File, json_parser: JSON)
package_json_file = File.join(react_native_path, "package.json")
if !file_manager.exist?(package_json_file)
raise "Couldn't find the React Native package.json file at #{package_json_file}"
end
package = json_parser.parse(file_manager.read(package_json_file))
return package["version"]
end

def self.compute_new_arch_enabled(new_arch_enabled, react_native_version)
# Regex that identify a version with the syntax `<major>.<minor>.<patch>[-<prerelease>[.-]k]
# where
# - major is a number
# - minor is a number
# - patch is a number
# - prerelease is a string (can include numbers)
# - k is a number
version_regex = /^(\d+)\.(\d+)\.(\d+)(?:-(\w+(?:[-.]\d+)?))?$/

if match_data = react_native_version.match(version_regex)

major = match_data[1].to_i

# We want to enforce the new architecture for 1.0.0 and greater,
# but not for 1000 as version 1000 is currently main.
if major > 0 && major < 1000
return "1"
end
end
return new_arch_enabled ? "1" : "0"
end

def self.new_arch_enabled
return ENV["RCT_NEW_ARCH_ENABLED"] == "1"
end
end
3 changes: 3 additions & 0 deletions packages/react-native/scripts/cocoapods/utils.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ def self.warn_if_not_on_arm64
end
end

# deprecated. These checks are duplicated in the react_native_pods function
# and we don't really need them. Removing this function will make it easy to
# move forward.
def self.get_default_flags
flags = {
:fabric_enabled => false,
Expand Down
27 changes: 16 additions & 11 deletions packages/react-native/scripts/react_native_pods.rb
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ def prepare_react_native_project!
def use_react_native! (
path: "../node_modules/react-native",
fabric_enabled: false,
new_arch_enabled: ENV['RCT_NEW_ARCH_ENABLED'] == '1',
new_arch_enabled: NewArchitectureHelper.new_arch_enabled,
production: false, # deprecated
hermes_enabled: ENV['USE_HERMES'] && ENV['USE_HERMES'] == '0' ? false : true,
flipper_configuration: FlipperConfiguration.disabled,
Expand All @@ -93,8 +93,11 @@ def use_react_native! (

# We are relying on this flag also in third parties libraries to proper install dependencies.
# Better to rely and enable this environment flag if the new architecture is turned on using flags.
ENV['RCT_NEW_ARCH_ENABLED'] = new_arch_enabled ? "1" : "0"
fabric_enabled = fabric_enabled || new_arch_enabled
relative_path_from_current = Pod::Config.instance.installation_root.relative_path_from(Pathname.pwd)
react_native_version = NewArchitectureHelper.extract_react_native_version(File.join(relative_path_from_current, path))
ENV['RCT_NEW_ARCH_ENABLED'] = NewArchitectureHelper.compute_new_arch_enabled(new_arch_enabled, react_native_version)

fabric_enabled = fabric_enabled || NewArchitectureHelper.new_arch_enabled
ENV['RCT_FABRIC_ENABLED'] = fabric_enabled ? "1" : "0"
ENV['USE_HERMES'] = hermes_enabled ? "1" : "0"

Expand All @@ -104,7 +107,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" if !new_arch_enabled
pod 'FBReactNativeSpec', :path => "#{prefix}/React/FBReactNativeSpec" if !NewArchitectureHelper.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 @@ -156,7 +159,7 @@ def use_react_native! (
run_codegen!(
app_path,
config_file_dir,
:new_arch_enabled => new_arch_enabled,
:new_arch_enabled => NewArchitectureHelper.new_arch_enabled,
:disable_codegen => ENV['DISABLE_CODEGEN'] == '1',
:react_native_path => prefix,
:fabric_enabled => fabric_enabled,
Expand All @@ -172,14 +175,14 @@ def use_react_native! (
# If the New Arch is turned off, we will use the Old Renderer, though.
# RNTester always installed Fabric, this change is required to make the template work.
setup_fabric!(:react_native_path => prefix)
checkAndGenerateEmptyThirdPartyProvider!(prefix, new_arch_enabled)
checkAndGenerateEmptyThirdPartyProvider!(prefix, NewArchitectureHelper.new_arch_enabled)

if !fabric_enabled
relative_installation_root = Pod::Config.instance.installation_root.relative_path_from(Pathname.pwd)
build_codegen!(prefix, relative_installation_root)
end

if new_arch_enabled
if NewArchitectureHelper.new_arch_enabled
setup_bridgeless!(:react_native_path => prefix, :use_hermes => hermes_enabled)
end

Expand Down Expand Up @@ -212,12 +215,15 @@ def folly_flags()
# 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")
def install_modules_dependencies(spec, new_arch_enabled: NewArchitectureHelper.new_arch_enabled)
NewArchitectureHelper.install_modules_dependencies(spec, new_arch_enabled, $FOLLY_VERSION)
end

# It returns the default flags.
# deprecated.
def get_default_flags()
warn 'get_default_flags is deprecated. Please remove the keys from the `use_react_native!` function'
warn 'if you are using the default already and pass the value you need in case you don\'t want the default'
return ReactNativePodsUtils.get_default_flags()
end

Expand Down Expand Up @@ -268,8 +274,7 @@ def react_native_post_install(
ReactNativePodsUtils.apply_ats_config(installer)

NewArchitectureHelper.set_clang_cxx_language_standard_if_needed(installer)
is_new_arch_enabled = ENV['RCT_NEW_ARCH_ENABLED'] == "1"
NewArchitectureHelper.modify_flags_for_new_architecture(installer, is_new_arch_enabled)
NewArchitectureHelper.modify_flags_for_new_architecture(installer, NewArchitectureHelper.new_arch_enabled)

Pod::UI.puts "Pod install took #{Time.now.to_i - $START_TIME} [s] to run".green
end
Expand All @@ -278,7 +283,7 @@ def react_native_post_install(
# We need to keep this while we continue to support the old architecture.
# =====================
def use_react_native_codegen!(spec, options={})
return if ENV['RCT_NEW_ARCH_ENABLED'] == "1"
return if NewArchitectureHelper.new_arch_enabled
# TODO: Once the new codegen approach is ready for use, we should output a warning here to let folks know to migrate.

# The prefix to react-native
Expand Down
6 changes: 0 additions & 6 deletions packages/react-native/template/ios/Podfile
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,8 @@ end
target 'HelloWorld' do
config = use_native_modules!

# Flags change depending on the env values.
flags = get_default_flags()

use_react_native!(
:path => config[:reactNativePath],
# Hermes is now enabled by default. Disable by setting this flag to false.
:hermes_enabled => flags[:hermes_enabled],
:fabric_enabled => flags[:fabric_enabled],
# Enables Flipper.
#
# Note that if you have use_frameworks! enabled, Flipper will not work and
Expand Down
7 changes: 2 additions & 5 deletions packages/rn-tester/Podfile
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,6 @@ def pods(target_name, options = {}, use_flipper: $shouldUseFlipper)
hermes_enabled = !ENV.has_key?('USE_HERMES') || ENV['USE_HERMES'] == '1'
puts "Configuring #{target_name} with Fabric #{fabric_enabled ? "enabled" : "disabled"}.#{hermes_enabled ? " Using Hermes engine." : ""}"

if ENV['RCT_NEW_ARCH_ENABLED'] == '1'
# Custom fabric component is only supported when using codegen discovery.
pod 'MyNativeView', :path => "NativeComponentExample"
end

use_react_native!(
path: @prefix_path,
fabric_enabled: fabric_enabled,
Expand All @@ -68,7 +63,9 @@ def pods(target_name, options = {}, use_flipper: $shouldUseFlipper)

# RNTester native modules and components
pod 'ScreenshotManager', :path => "NativeModuleExample"

if ENV['RCT_NEW_ARCH_ENABLED'] == '1'
pod 'MyNativeView', :path => "NativeComponentExample"
pod 'NativeCxxModuleExample', :path => "NativeCxxModuleExample"
end
end
Expand Down