diff --git a/.gitignore b/.gitignore index 491d740ad1a070..5f30b988d17c85 100644 --- a/.gitignore +++ b/.gitignore @@ -21,6 +21,7 @@ DerivedData *.xcuserstate project.xcworkspace **/.xcode.env.local +/poackages/react-native/sdks/downloads/ # Gradle /build/ diff --git a/packages/react-native/scripts/cocoapods/__tests__/utils-test.rb b/packages/react-native/scripts/cocoapods/__tests__/utils-test.rb index 44fb7c6c557b38..82209f2dc1d49e 100644 --- a/packages/react-native/scripts/cocoapods/__tests__/utils-test.rb +++ b/packages/react-native/scripts/cocoapods/__tests__/utils-test.rb @@ -178,21 +178,26 @@ def test_hasPod_whenInstallerHasPod_returnTrue # Test - Set GCC Preprocessor Definition for React-hermes # # ======================================================== # - def test_SetGCCPreprocessorDefinitionForReactHermes_itSetsThePreprocessorForDebug + def test_SetGCCPreprocessorDefinitionForHermes_itSetsThePreprocessorForDebug # Arrange react_hermes_name = "React-hermes" react_core_name = "React-Core" - react_hermes_debug_config = BuildConfigurationMock.new("Debug") - react_hermes_release_config = BuildConfigurationMock.new("Release") - react_core_debug_config = BuildConfigurationMock.new("Debug") - react_core_release_config = BuildConfigurationMock.new("Release") - react_hermes_target = TargetMock.new(react_hermes_name, [react_hermes_debug_config, react_hermes_release_config]) - react_core_target = TargetMock.new(react_core_name, [react_core_debug_config, react_core_release_config]) + hermes_engine_name = "hermes-engine" + react_hermes_debug_config = BuildConfigurationMock.new("Debug") + react_hermes_release_config = BuildConfigurationMock.new("Release") + react_core_debug_config = BuildConfigurationMock.new("Debug") + react_core_release_config = BuildConfigurationMock.new("Release") + hermes_engine_debug_config = BuildConfigurationMock.new("Debug") + hermes_engine_release_config = BuildConfigurationMock.new("Release") + react_hermes_target = TargetMock.new(react_hermes_name, [react_hermes_debug_config, react_hermes_release_config]) + react_core_target = TargetMock.new(react_core_name, [react_core_debug_config, react_core_release_config]) + hermes_engine_target = TargetMock.new(hermes_engine_name, [hermes_engine_debug_config, hermes_engine_release_config]) installer = InstallerMock.new( :pod_target_installation_results => { react_hermes_name => TargetInstallationResultMock.new(react_hermes_target, react_hermes_target), react_core_name => TargetInstallationResultMock.new(react_core_target, react_core_target), + hermes_engine_name => TargetInstallationResultMock.new(hermes_engine_target, hermes_engine_target), } ) @@ -201,11 +206,13 @@ def test_SetGCCPreprocessorDefinitionForReactHermes_itSetsThePreprocessorForDebu # Assert build_setting = "GCC_PREPROCESSOR_DEFINITIONS" - expected_value = "HERMES_ENABLE_DEBUGGER=1" + expected_value = "$(inherited) HERMES_ENABLE_DEBUGGER=1" assert_equal(expected_value, react_hermes_debug_config.build_settings[build_setting]) assert_nil(react_hermes_release_config.build_settings[build_setting]) assert_nil(react_core_debug_config.build_settings[build_setting]) assert_nil(react_core_release_config.build_settings[build_setting]) + assert_equal(expected_value, hermes_engine_debug_config.build_settings[build_setting]) + assert_nil(hermes_engine_release_config.build_settings[build_setting]) end # ============================ # diff --git a/packages/react-native/scripts/cocoapods/utils.rb b/packages/react-native/scripts/cocoapods/utils.rb index 91c638f50afb4e..fc823b54e41393 100644 --- a/packages/react-native/scripts/cocoapods/utils.rb +++ b/packages/react-native/scripts/cocoapods/utils.rb @@ -41,6 +41,7 @@ def self.has_pod(installer, name) def self.set_gcc_preprocessor_definition_for_React_hermes(installer) self.add_build_settings_to_pod(installer, "GCC_PREPROCESSOR_DEFINITIONS", "HERMES_ENABLE_DEBUGGER=1", "React-hermes", "Debug") + self.add_build_settings_to_pod(installer, "GCC_PREPROCESSOR_DEFINITIONS", "HERMES_ENABLE_DEBUGGER=1", "hermes-engine", "Debug") end def self.turn_off_resource_bundle_react_core(installer) @@ -153,7 +154,8 @@ def self.add_build_settings_to_pod(installer, settings_name, settings_value, tar if pod_name.to_s == target_pod_name target_installation_result.native_target.build_configurations.each do |config| if configuration == nil || (configuration != nil && configuration == config.name) - config.build_settings[settings_name] = settings_value + config.build_settings[settings_name] ||= '$(inherited) ' + config.build_settings[settings_name] << settings_value end end end diff --git a/packages/react-native/sdks/hermes-engine/hermes-engine.podspec b/packages/react-native/sdks/hermes-engine/hermes-engine.podspec index 5be0a8d49908f8..681cb2c4d234a6 100644 --- a/packages/react-native/sdks/hermes-engine/hermes-engine.podspec +++ b/packages/react-native/sdks/hermes-engine/hermes-engine.podspec @@ -8,9 +8,6 @@ require_relative "./hermes-utils.rb" react_native_path = File.join(__dir__, "..", "..") -# Whether Hermes is built for Release or Debug is determined by the PRODUCTION envvar. -build_type = ENV['PRODUCTION'] == "1" ? :release : :debug - # package.json package = JSON.parse(File.read(File.join(react_native_path, "package.json"))) version = package['version'] @@ -23,7 +20,7 @@ git = "https://github.com/facebook/hermes.git" abort_if_invalid_tarball_provided! -source = compute_hermes_source(build_from_source, hermestag_file, git, version, build_type, react_native_path) +source = compute_hermes_source(build_from_source, hermestag_file, git, version, react_native_path) Pod::Spec.new do |spec| spec.name = "hermes-engine" @@ -42,7 +39,7 @@ Pod::Spec.new do |spec| spec.pod_target_xcconfig = { "CLANG_CXX_LANGUAGE_STANDARD" => "c++17", "CLANG_CXX_LIBRARY" => "compiler-default" - }.merge!(build_type == :debug ? { "GCC_PREPROCESSOR_DEFINITIONS" => "HERMES_ENABLE_DEBUGGER=1" } : {}) + } spec.ios.vendored_frameworks = "destroot/Library/Frameworks/ios/hermes.framework" spec.osx.vendored_frameworks = "destroot/Library/Frameworks/macosx/hermes.framework" @@ -50,7 +47,7 @@ Pod::Spec.new do |spec| if source[:http] then spec.subspec 'Pre-built' do |ss| - ss.preserve_paths = ["destroot/bin/*"].concat(build_type == :debug ? ["**/*.{h,c,cpp}"] : []) + ss.preserve_paths = ["destroot/bin/*"].concat(["**/*.{h,c,cpp}"]) ss.source_files = "destroot/include/**/*.h" ss.exclude_files = ["destroot/include/jsi/jsi/JSIDynamic.{h,cpp}", "destroot/include/jsi/jsi/jsilib-*.{h,cpp}"] ss.header_mappings_dir = "destroot/include" @@ -58,6 +55,24 @@ Pod::Spec.new do |spec| ss.osx.vendored_frameworks = "destroot/Library/Frameworks/macosx/hermes.framework" end + + # Right now, even reinstalling pods with the PRODUCTION flag turned on, does not change the version of hermes that is downloaded + # To remove the PRODUCTION flag, we want to download the right version of hermes on the flight + # we do so in a pre-build script we invoke from the Xcode build pipeline + # We use this only for Apps created using the template. RNTester and Nightlies should not be used to build for Release. + # We ignore this if we provide a specific tarball: the assumption here is that if you are providing a tarball, is because you want to + # test something specific for that tarball. + if source[:http].include?('https://repo1.maven.org/') + spec.script_phase = { + :name => "[Hermes] Replace Hermes for the right configuration, if needed", + :execution_position => :before_compile, + :script => <<-EOS + . "$REACT_NATIVE_PATH/scripts/xcode/with-environment.sh" + "$NODE_BINARY" "$REACT_NATIVE_PATH/sdks/hermes-engine/utils/replace_hermes_version.js" -c "$CONFIGURATION" -r "#{version}" -p "$REACT_NATIVE_PATH" + EOS + } + end + elsif source[:git] then spec.subspec 'Hermes' do |ss| @@ -96,7 +111,7 @@ Pod::Spec.new do |spec| { :name => '[RN] [1] Build Hermesc', :script => <<-EOS - . ${PODS_ROOT}/../.xcode.env + . "${REACT_NATIVE_PATH}/scripts/xcode/with-environment.sh" export CMAKE_BINARY=${CMAKE_BINARY:-#{CMAKE_BINARY}} . ${REACT_NATIVE_PATH}/sdks/hermes-engine/utils/build-hermesc-xcode.sh #{hermesc_path} EOS @@ -104,7 +119,7 @@ Pod::Spec.new do |spec| { :name => '[RN] [2] Build Hermes', :script => <<-EOS - . ${PODS_ROOT}/../.xcode.env + . "${REACT_NATIVE_PATH}/scripts/xcode/with-environment.sh" export CMAKE_BINARY=${CMAKE_BINARY:-#{CMAKE_BINARY}} . ${REACT_NATIVE_PATH}/sdks/hermes-engine/utils/build-hermes-xcode.sh #{version} #{hermesc_path}/ImportHermesc.cmake EOS diff --git a/packages/react-native/sdks/hermes-engine/hermes-utils.rb b/packages/react-native/sdks/hermes-engine/hermes-utils.rb index 26abc7b70761fb..1d3f501d9d3910 100644 --- a/packages/react-native/sdks/hermes-engine/hermes-utils.rb +++ b/packages/react-native/sdks/hermes-engine/hermes-utils.rb @@ -30,7 +30,7 @@ def abort_if_invalid_tarball_provided!() # - react_native_path: path to react native # # Returns: a properly configured source object -def compute_hermes_source(build_from_source, hermestag_file, git, version, build_type, react_native_path) +def compute_hermes_source(build_from_source, hermestag_file, git, version, react_native_path) source = {} if ENV.has_key?('HERMES_ENGINE_TARBALL_PATH') @@ -43,8 +43,10 @@ def compute_hermes_source(build_from_source, hermestag_file, git, version, build else build_hermes_from_source(source, git) end - elsif hermes_artifact_exists(release_tarball_url(version, build_type)) - use_release_tarball(source, version, build_type) + elsif hermes_artifact_exists(release_tarball_url(version, :debug)) + use_release_tarball(source, version, :debug) + download_stable_hermes(react_native_path, version, :debug) + download_stable_hermes(react_native_path, version, :release) elsif hermes_artifact_exists(nightly_tarball_url(version).gsub("\\", "")) use_nightly_tarball(source, react_native_path, version) else @@ -100,6 +102,25 @@ def putsIfPodPresent(message, level = 'warning') end end +def download_stable_hermes(react_native_path, version, configuration) + tarball_url = release_tarball_url(version, configuration) + download_hermes_tarball(react_native_path, tarball_url, version, configuration) +end + +def download_hermes_tarball(react_native_path, tarball_url, version, configuration) + destination_folder = "#{react_native_path}/sdks/downloads" + destination_path = configuration == nil ? + "#{destination_folder}/hermes-ios-#{version}.tar.gz" : + "#{destination_folder}/hermes-ios-#{version}-#{configuration}.tar.gz" + + unless File.exist?(destination_path) + # Download to a temporary file first so we don't cache incomplete downloads. + tmp_file = "#{destination_folder}/hermes-ios.download" + `mkdir -p "#{destination_folder}" && curl "#{tarball_url}" -Lo "#{tmp_file}" && mv "#{tmp_file}" "#{destination_path}"` + end + return destination_path +end + # This function downloads the nightly prebuilt version of Hermes based on the passed version # and save it in the node_module/react_native/sdks/downloads folder # It then returns the path to the hermes tarball @@ -110,16 +131,7 @@ def putsIfPodPresent(message, level = 'warning') # Returns: the path to the downloaded Hermes tarball def download_nightly_hermes(react_native_path, version) tarball_url = nightly_tarball_url(version) - - destination_folder = "#{react_native_path}/sdks/downloads" - destination_path = "#{destination_folder}/hermes-ios-#{version}.tar.gz" - - unless File.exist?(destination_path) - # Download to a temporary file first so we don't cache incomplete downloads. - tmp_file = "#{destination_folder}/hermes-ios.download" - `mkdir -p "#{destination_folder}" && curl "#{tarball_url}" -Lo "#{tmp_file}" && mv "#{tmp_file}" "#{destination_path}"` - end - return destination_path + return download_stable_hermes(react_native_path, tarball_url, version, nil) end def nightly_tarball_url(version) diff --git a/packages/react-native/sdks/hermes-engine/utils/replace_hermes_version.js b/packages/react-native/sdks/hermes-engine/utils/replace_hermes_version.js new file mode 100644 index 00000000000000..1ccc91b85f9e79 --- /dev/null +++ b/packages/react-native/sdks/hermes-engine/utils/replace_hermes_version.js @@ -0,0 +1,104 @@ +/** + * 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. + * + * @format + */ + +'use strict'; + +const yargs = require('yargs'); +const fs = require('fs'); +const {execSync} = require('child_process'); + +const LAST_BUILD_FILENAME = '.last_build_configuration'; + +function validateBuildConfiguration(configuration) { + if (!['Debug', 'Release'].includes(configuration)) { + throw new Error(`Invalid configuration ${configuration}`); + } +} + +function validateVersion(version) { + if (version == null || version === '') { + throw new Error('Version cannot be empty'); + } +} + +function shouldReplaceHermesConfiguration(configuration) { + const fileExists = fs.existsSync(LAST_BUILD_FILENAME); + + if (fileExists) { + console.log(`Found ${LAST_BUILD_FILENAME} file`); + const oldConfiguration = fs.readFileSync(LAST_BUILD_FILENAME).toString(); + if (oldConfiguration === configuration) { + console.log('No need to download a new build of Hermes!'); + return false; + } + } + + // Assumption: if there is no stored last build, we assume that it was build for debug. + if (!fs.existsSync && configuration === 'Debug') { + console.log( + 'File does not exists, but Debug configuration. No need to download a new build of Hermes!', + ); + return false; + } + + return true; +} + +function replaceHermesConfiguration(configuration, version, reactNativePath) { + const tarballURLPath = `${reactNativePath}/sdks/downloads/hermes-ios-${version}-${configuration}.tar.gz`; + + const finalLocation = 'hermes-engine'; + console.log('Preparing the final location'); + fs.rmSync(finalLocation, {force: true, recursive: true}); + fs.mkdirSync(finalLocation, {recursive: true}); + + console.log('Extracting the tarball'); + execSync(`tar -xf ${tarballURLPath} -C ${finalLocation}`); +} + +function updateLastBuildConfiguration(configuration) { + fs.writeFileSync(LAST_BUILD_FILENAME, configuration); +} + +function main(configuration, version, reactNativePath) { + validateBuildConfiguration(configuration); + validateVersion(version); + + if (!shouldReplaceHermesConfiguration(configuration)) { + return; + } + + replaceHermesConfiguration(configuration, version, reactNativePath); + updateLastBuildConfiguration(configuration); + console.log('Done replacing hermes-engine'); +} + +// This script is executed in the Pods folder, which is usually not synched to Github, so it should be ok +const argv = yargs + .option('c', { + alias: 'configuration', + description: + 'Configuration to use to download the right Hermes version. Allowed values are "Debug" and "Release".', + }) + .option('r', { + alias: 'reactNativeVersion', + description: + 'The Version of React Native associated with the Hermes tarball.', + }) + .option('p', { + alias: 'reactNativePath', + description: 'The path to the React Native root folder', + }) + .usage('Usage: $0 -c Debug -r -p ').argv; + +const configuration = argv.configuration; +const version = argv.reactNativeVersion; +const reactNativePath = argv.reactNativePath; + +main(configuration, version, reactNativePath); diff --git a/packages/rn-tester/Podfile.lock b/packages/rn-tester/Podfile.lock index a9132e6b3dd66c..75cf0dff61df6d 100644 --- a/packages/rn-tester/Podfile.lock +++ b/packages/rn-tester/Podfile.lock @@ -1242,8 +1242,8 @@ SPEC CHECKSUMS: boost: 57d2868c099736d80fcd648bf211b4431e51a558 CocoaAsyncSocket: 065fd1e645c7abab64f7a6a2007a48038fdc6a99 DoubleConversion: fea03f2699887d960129cc54bba7e52542b6f953 - FBLazyVector: 9c79ec2238e065a949c9bb7aebdf7cebd6203015 - FBReactNativeSpec: 66b1b6348a3f6c3133e6e437ad50b46f4fef812f + FBLazyVector: ca580232ba491b6601ee57bcdc874fda97a459a5 + FBReactNativeSpec: 4db5acd51db3de49e59e3740f03c94ce1282a31e Flipper: 6edb735e6c3e332975d1b17956bcc584eccf5818 Flipper-Boost-iOSX: fd1e2b8cbef7e662a122412d7ac5f5bea715403c Flipper-DoubleConversion: 2dc99b02f658daf147069aad9dbd29d8feb06d30 @@ -1254,53 +1254,53 @@ SPEC CHECKSUMS: FlipperKit: 2efad7007d6745a3f95e4034d547be637f89d3f6 fmt: ff9d55029c625d3757ed641535fd4a75fedc7ce9 glog: 99bd064df01718db56b8f75e6b5ea3051c7dad0a - hermes-engine: 6085d07261e8a8bfe708e4b0dcd0f3eae72a8e4d + hermes-engine: 4ea4b12e82d2ccfd03b29e3d9191b716b4c8f476 libevent: 4049cae6c81cdb3654a443be001fb9bdceff7913 OCMock: 9491e4bec59e0b267d52a9184ff5605995e74be8 OpenSSL-Universal: ebc357f1e6bc71fa463ccb2fe676756aff50e88c RCT-Folly: b0d1393cb3763d71efca99db314c65f0072eb0fe - RCTRequired: 40ffd795b32a630f147fcc15247920e5161b6a4e - RCTTypeSafety: fd9d941c329580ea280cad3565bb2e1656969f41 - React: 47363de0e2c161a347eef1cb57cba33f1a4b7377 - React-callinvoker: 28e99e6254975d5be67eafeedbcc3a45bb1ace94 + RCTRequired: 5394bb1f71591633e1158bdf0534206cb5ccbeb5 + RCTTypeSafety: ba46a7f654566047a9358f2e74b2eafd97ccba9b + React: 8a004085056a81c7820f65a8bc0a92e1f7ef6878 + React-callinvoker: c2b59f2cbf0d8bcdc18b33f53e097907c12a149c React-Codegen: 9ecf53f804f4d1d2a5d29bb2154e22a30c381f81 - React-Core: f2a04589df942502db2f3ef84ddc83a35a7086d3 - React-CoreModules: 4fe81e5b80d5daa3e81151dfc9e516ae1a0e575f - React-cxxreact: 1235a3b3d8ea0639f95741cc907ddbb41da4bea3 - React-debug: 9c6d0fd7867cc4a8f435d528e2c5fa8465e9c054 - React-Fabric: b429ac248d619825f97ceb607d1a2d556a49c47c - React-FabricImage: 8136841d81a7005ac3c294623f87497f6bbf8f09 - React-graphics: ed6de536e153c7bc852f9c773a3c9b21c2ee22da - React-hermes: b494c9c833faa6217b2f666d13aa52623c34c2e9 - React-ImageManager: 3e990b6ffbc7634556ddf5b90e5bb1025c397a4c - React-jsi: 00d3c30ce021ff1a074315b824b22108db01131f - React-jsiexecutor: 473c386e219c256066689a334663e8813cdc65ef - React-jsinspector: 25164fdf93d5be275ba455d916e96adb49fa407c - React-logger: a2165169d9c1897c1a139c6b158f6f79090ee174 - React-NativeModulesApple: 5ca2a6989b4549ecf557958c72d514bda071922d - React-perflogger: b5ecf879c705577c80e5299ae678b9375fe2f998 - React-RCTActionSheet: 4a241f444d11926261dd904449a31f35157d4eee - React-RCTAnimation: cf7c9f502e597ee97ce18d1bc4eb8a5836ecf21d - React-RCTAppDelegate: da46fbaa608f201a832d1310bd2e8ce4234642b1 - React-RCTBlob: 48eae02e3f75777da97e9282a5861d04471624a9 - React-RCTFabric: 4b122d0e96f6a581046b8cb950e3277036a5d45a - React-RCTImage: 3efab57255aeb986f89ddc8719fbffd4559954ad - React-RCTLinking: 708dbd9b0aa0845c735e5d6b0e9f7f268008a830 - React-RCTNetwork: d88896f8b7adf85ba366168c5bf1e03d7c235493 - React-RCTPushNotification: dbacfd181137a62deebc62fd386419e707cdcf95 - React-RCTSettings: 17cb468bba42b17b7b0e40ea971d6bd8a78baa3f - React-RCTTest: d7142acb2544c01f53deb2b0543d63df6e214ac2 - React-RCTText: 8cb3ebda2675a02de0cb363a765fafb7d6c31cc1 - React-RCTVibration: c40f0f3e0114354bbf4b418e381c2c96d1d22d48 - React-rncore: 11d8412fb1e339cd1be30aa33cb3b265b46a542b - React-runtimeexecutor: c810e5b7d7500a9ad3ed66b834503e412684936d - ReactCommon: a7972e80473d6ba9bcf3ee53bcc310ac6b944a49 - ReactCommon-Samples: 93c677b30087b6aa82bbccb4458a2028cd6ebd10 + React-Core: d730664c1ee918190a0c26bbf5c993f57e46ff5d + React-CoreModules: 390071843c203f516ec8dbc1c9ce1a815d35e908 + React-cxxreact: 39409697255baeb1ac42e436daee59913036109d + React-debug: d69fb5b4e3a47e8d5f8fdb01c1ec8983b7c1afec + React-Fabric: b19750f6cd0fae4e87173b1c2b6f9c94621b6679 + React-FabricImage: dc031099e2ae4734b70f1f66b7edf4f1cc40335a + React-graphics: e2c5d8a680cd5db24ab87756f688ecd24fd4628e + React-hermes: 4e22050b18127c27759488b703c0a9d5e6a341ba + React-ImageManager: f6792f5987f85271cbbc31e99dc16e63fd82fccb + React-jsi: 57f6f99db8d596dd599450f921b77229616e983b + React-jsiexecutor: 05d7b49ae31548ed320bb17d97bf5d648406278b + React-jsinspector: 03d477e4dd236c5411ef9a2f8c52cc2951ab6149 + React-logger: adce225eaf6d94e0e2568ba586c3f6e857fc8862 + React-NativeModulesApple: 67bb14d796e45adad89238b96a26b0f0daa5fa72 + React-perflogger: 8889aa68bda6d4cb649f890677d36c7b1eadfcd9 + React-RCTActionSheet: f5f5aa4079e8316562171fdf6346883d79fc51b1 + React-RCTAnimation: 0a3247bc23fd71f8eff8ccdb1bdeebbcb1de8af3 + React-RCTAppDelegate: 4d24c5365e3581fe22a05f0fadf5595b18d8c456 + React-RCTBlob: 484c22d88cbfc3d3441c1e54686f7793eaf30fa3 + React-RCTFabric: cd58dfa8a168d41363f84e78abe2d71d081581fb + React-RCTImage: 65ef7ecc938dea1decadd876448c47bc71e9d60b + React-RCTLinking: 100b9d0a895d95ea1e59e62375fe9b95d83fe031 + React-RCTNetwork: 710d044df7ddbe7be1ecae2608fc2ae2c5096c9a + React-RCTPushNotification: 502720de4bfd05358169c10e1ab791a794f550b0 + React-RCTSettings: f0f73ba95d32777386c294572c0e7f757bd33e08 + React-RCTTest: 6978788114214cf1f3004c04c5c2b882d9c0c0ea + React-RCTText: a64c63e34beec7c9893042a200d48accde4a406e + React-RCTVibration: e16f969546e42256468f7681d6d6ec3d2cab4524 + React-rncore: 4b86b32071e99b892eefaeee55dcec300e3e9194 + React-runtimeexecutor: 5499cb980788a75a5a474ab07b480e73f87e76b0 + ReactCommon: ed5e5ad966bbc436641a15fedb1b20dd68a2d147 + ReactCommon-Samples: cc63a8216d5e2090cc82c9427cd8d6675bef4d0f ScreenshotManager: d39b964a374e5012e2b8c143e29ead86b1da6a3c SocketRocket: fccef3f9c5cedea1353a9ef6ada904fde10d6608 - Yoga: b82f2e3cbeb3d926329278b24d54d798215d4fa3 + Yoga: 456e136b8de9c5360b609bd3238656cea243958f YogaKit: f782866e155069a2cca2517aafea43200b01fd5a PODFILE CHECKSUM: bdab6add69d555774de227d7119a8f5ae02a670e -COCOAPODS: 1.12.0 +COCOAPODS: 1.12.1