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

Workaround React Native 0.71 and XCFramework setup issues #5912

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
59ef300
Point RNReanimated to a custom branch to work around 2.17.0 issue
mokagio Jun 27, 2023
fc838fb
Print message during `pod install` about `REACT_NATIVE_NODE_MODULES_DIR`
mokagio Jun 27, 2023
737d557
Explicitly set `REACT_NATIVE_NODE_MODULES_DIR` in CI
mokagio Jun 27, 2023
90faccd
Setup NVM and node modules for RNReanimated in XCFramework CI step
mokagio Jun 27, 2023
290ed77
Add more logs in CI to understand where code fails
mokagio Jun 27, 2023
d41795c
Use same command as nvm reccomendation
mokagio Jun 27, 2023
5065ba7
Tweak nvm setup
mokagio Jun 27, 2023
ba15315
Try with `--install`
mokagio Jun 27, 2023
1ba6baa
Apply bundle changes
Jun 27, 2023
c18b0fc
Switch to using `use_react_native!` in XCFramework `Podfile`
mokagio Jun 27, 2023
d0804a9
Add React Native `post_install` hook
mokagio Jun 27, 2023
e47fa29
Use `.xcode.env` instead of `.xcode.env.local`
mokagio Jun 28, 2023
6a2b631
Bump XCFramework deployment target to iOS 15.0
mokagio Jun 28, 2023
224e5fc
Use Xcode 14.3.1 in CI, like WordPress iOS does
mokagio Jun 28, 2023
b88e876
Disable Hermes when building XCFramework
mokagio Jun 28, 2023
c2bfebc
Refine messaging when setting `REACT_NATIVE_NODE_MODULES_DIR` env var
mokagio Jun 29, 2023
71004fa
Set `SKIP_INSTALL = NO` at the `xcconfig` level, too
mokagio Jun 29, 2023
4bc661f
Switch an `unless !=` to `if ==`
mokagio Jun 29, 2023
1d87e3b
Add workaround to setup Hermes correctly in XCFramework
mokagio Jun 29, 2023
91bacf5
Enable building XCFramework with Hermes
mokagio Jun 29, 2023
f2d1b71
Merge branch 'upgrade/react-native-0.71-ios' into mokagio/workaround-…
fluiddot Jun 30, 2023
f1ef991
Read iOS deployment version from `xcconfig` in root `podspec`s
mokagio Jul 3, 2023
1b8b462
Remove settings from build.sh already set in `xcconfig`
mokagio Jul 3, 2023
68caf6c
Use A8C CI toolkit version 2.18.0
mokagio Jul 3, 2023
6679c15
HACK – Hack for faster build
mokagio Jul 3, 2023
e18fec1
Build on Xcode 14.3
mokagio Jul 3, 2023
15f0b1a
Try with Hermes disabled
mokagio Jul 3, 2023
8f9f23f
Revert "Build on Xcode 14.3"
mokagio Jul 3, 2023
dbfac03
Revert "Try with Hermes disabled"
mokagio Jul 3, 2023
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
60 changes: 31 additions & 29 deletions .buildkite/pipeline.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,39 +13,40 @@ steps:
- block: "Request trigger Android bundle and builds"
branches: "dependabot/submodules/*"

- label: "Build JS Bundles"
key: "js-bundles"
plugins:
- docker#v3.8.0:
image: "public.ecr.aws/automattic/gb-mobile-image:latest"
environment:
- "CI=true"
# Allow WP-CLI to be run as root, otherwise it throws an exception.
# Reference: https://git.io/J9q2S
- "WP_CLI_ALLOW_ROOT=true"
command: |
source /root/.bashrc
# Debug – Skipping for faster feedback
# - label: "Build JS Bundles"
# key: "js-bundles"
# plugins:
# - docker#v3.8.0:
# image: "public.ecr.aws/automattic/gb-mobile-image:latest"
# environment:
# - "CI=true"
# # Allow WP-CLI to be run as root, otherwise it throws an exception.
# # Reference: https://git.io/J9q2S
# - "WP_CLI_ALLOW_ROOT=true"
# command: |
# source /root/.bashrc

echo "--- :node: Setup Node environment"
nvm install && nvm use
# echo "--- :node: Setup Node environment"
# nvm install && nvm use

echo "--- :npm: Install Node dependencies"
npm ci --unsafe-perm --prefer-offline --no-audit --no-progress
# echo "--- :npm: Install Node dependencies"
# npm ci --unsafe-perm --prefer-offline --no-audit --no-progress

echo "--- :package: Run bundle prep work"
npm run prebundle:js
# echo "--- :package: Run bundle prep work"
# npm run prebundle:js

echo "--- :android: Build Android bundle"
npm run bundle:android
# echo "--- :android: Build Android bundle"
# npm run bundle:android

echo "--- :arrow_up: Upload Android bundle artifact"
buildkite-agent artifact upload bundle/android/App.js
# echo "--- :arrow_up: Upload Android bundle artifact"
# buildkite-agent artifact upload bundle/android/App.js

echo "--- :ios: Build iOS bundle"
npm run bundle:ios
# echo "--- :ios: Build iOS bundle"
# npm run bundle:ios

echo "--- :arrow_up: Upload iOS bundle artifact"
buildkite-agent artifact upload bundle/ios/App.js
# echo "--- :arrow_up: Upload iOS bundle artifact"
# buildkite-agent artifact upload bundle/ios/App.js
- label: "Build Android RN Aztec & Publish to S3"
key: "publish-react-native-aztec-android"
plugins:
Expand All @@ -63,15 +64,16 @@ steps:
.buildkite/publish-react-native-bridge-android-artifacts.sh

- label: Build iOS RN XCFramework & Publish to S3
depends_on: js-bundles
# Debug – Skipping build dependency for faster feedback
# depends_on: js-bundles
command: .buildkite/publish-react-native-ios-artifacts.sh
artifact_paths:
- ios-xcframework/build/xcframeworks/*.tar.gz
plugins:
- automattic/a8c-ci-toolkit#2.16.0
- automattic/a8c-ci-toolkit#2.18.0
- peakon/git-shallow-clone#v0.0.1:
depth: 1
agents:
queue: mac
env:
IMAGE_ID: xcode-14.3
IMAGE_ID: xcode-14.3.1
25 changes: 24 additions & 1 deletion .buildkite/publish-react-native-ios-artifacts.sh
Original file line number Diff line number Diff line change
@@ -1,14 +1,37 @@
#!/bin/bash -eu

echo "--- :arrow_down: Download iOS JS bundle"
buildkite-agent artifact download bundle/ios/App.js .
# buildkite-agent artifact download bundle/ios/App.js .
#
# Debug – Bypassing build step and re-using previously built artifact
buildkite-agent artifact download bundle/ios/App.js . \
--build 01891ac3-f25f-403f-9eb6-01347448c3d3 \
--step 01891ac4-37fb-4760-b6bd-90222f1be3c1

echo '--- :node: Setup node_modules for RNReanimated'
echo '--- :node: 1. Install nvm'
brew install nvm

echo '--- :node: 2. Load nvm in the current shell'
export NVM_DIR="$HOME/.nvm"
mkdir -p "$NVM_DIR"
[ -s "$HOMEBREW_PREFIX/opt/nvm/nvm.sh" ] && \. "$HOMEBREW_PREFIX/opt/nvm/nvm.sh" --install

echo '--- :node: 3. Install node version from .nvmrc'
nvm install "$(cat .nvmrc)" && nvm use

echo '--- :node: 4. nmp ci'
npm ci

echo "--- :rubygems: Setting up Gems"
cd ./ios-xcframework

install_gems

echo "--- :cocoapods: Setting up Pods"
# This should already be set by the Podfile and seems to work locally, but somethog does not work in CI.
# See https://buildkite.com/automattic/gutenberg-mobile/builds/6327#0188fad1-932d-4a37-9d84-811937d8af18/435-455
export REACT_NATIVE_NODE_MODULES_DIR="$PWD/../gutenberg/node_modules"
install_cocoapods

echo "--- 🚧 Install xcbeautify formatter while not on the VM image"
Expand Down
5 changes: 4 additions & 1 deletion Gutenberg.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,17 @@ react_native_version = gutenbergPackage['devDependencies']['react-native']
# Extract the tagged version if package.json points to a tag
react_native_version = react_native_version.split("#v").last if react_native_version.include? "#v"

version_xcconfig_path = File.join(File.expand_path(__dir__), 'ios-xcframework','Config', 'Gutenberg-Shared.xcconfig')
app_ios_deployment_target = Gem::Version.new(Xcodeproj::Config.new(version_xcconfig_path).to_hash['IPHONEOS_DEPLOYMENT_TARGET']).to_s

Pod::Spec.new do |s|
s.name = 'Gutenberg'
s.version = gutenbergMobilePackage['version']
s.summary = 'Printing since 1440'
s.homepage = 'https://github.com/wordpress-mobile/gutenberg-mobile'
s.license = gutenbergMobilePackage['license']
s.authors = 'Automattic'
s.platform = :ios, '13.0'
s.platform = :ios, app_ios_deployment_target
s.source = { :git => 'https://github.com/wordpress-mobile/gutenberg-mobile.git', :submodules => true }
s.source_files = 'gutenberg/packages/react-native-bridge/ios/**/*.{h,m,swift}'
s.requires_arc = true
Expand Down
5 changes: 4 additions & 1 deletion RNTAztecView.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ require 'json'

package = JSON.parse(File.read(File.join(__dir__, 'package.json')))

version_xcconfig_path = File.join(File.expand_path(__dir__), 'ios-xcframework','Config', 'Gutenberg-Shared.xcconfig')
app_ios_deployment_target = Gem::Version.new(Xcodeproj::Config.new(version_xcconfig_path).to_hash['IPHONEOS_DEPLOYMENT_TARGET']).to_s

Pod::Spec.new do |s|
s.name = 'RNTAztecView'
s.version = package['version']
Expand All @@ -13,7 +16,7 @@ Pod::Spec.new do |s|
s.source_files = 'gutenberg/packages/react-native-aztec/ios/RNTAztecView/*.{h,m,swift}'
s.public_header_files = 'gutenberg/packages/react-native-aztec/ios/RNTAztecView/*.h'
s.requires_arc = true
s.platforms = { :ios => "13.0" }
s.platforms = { :ios => app_ios_deployment_target }
s.swift_version = '5.0'
s.xcconfig = {'OTHER_LDFLAGS' => '-lxml2',
'HEADER_SEARCH_PATHS' => '/usr/include/libxml2'}
Expand Down
6 changes: 3 additions & 3 deletions bundle/ios/App.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion bundle/ios/App.js.map

Large diffs are not rendered by default.

7 changes: 7 additions & 0 deletions ios-xcframework/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,10 @@ fastlane/report.xml

# XCFramework build process intermediate and output artifacts
build

# This is generated by the `pod install` process.
# It is required by FBReactNativeSpec to compile in case `command -v node` does not give a result from within Xcode.
.xcode.env
# This file takes precedence over .xcode.env.
# Developers can use it to set a custom value without having to update .xcode.env after every `pod install`
.xcode.env.local
17 changes: 8 additions & 9 deletions ios-xcframework/Config/Gutenberg-Shared.xcconfig
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,10 @@ INSTALL_PATH = $(LOCAL_LIBRARY_DIR)/Frameworks
// Code will load on this and later versions of iOS. Framework APIs that are unavailable
// in earlier versions will be weak-linked; your code should check for null function
// pointers or specific system versions before calling newer APIs.
IPHONEOS_DEPLOYMENT_TARGET = 14.0
//
// At the moment, this needs to be the same value as what's used by the consumer (Jetpack and WordPress iOS)
// See https://github.com/wordpress-mobile/WordPress-iOS/commit/eadad98d81c8970144707d8967f8c9f06a6ada38#commitcomment-119894859
IPHONEOS_DEPLOYMENT_TARGET = 15.0
LD_RUNPATH_SEARCH_PATHS = $(inherited) @executable_path/Frameworks @loader_path/Frameworks
// Marketing Version
//
Expand All @@ -78,7 +81,6 @@ MTL_FAST_MATH = YES
PRODUCT_BUNDLE_IDENTIFIER = org.wordpress.Gutenberg
PRODUCT_NAME = $(TARGET_NAME:c99extidentifier)
SDKROOT = iphoneos
SKIP_INSTALL = YES
SWIFT_EMIT_LOC_STRINGS = YES
// Swift Language Version
//
Expand All @@ -87,12 +89,9 @@ SWIFT_VERSION = 5.0
TARGETED_DEVICE_FAMILY = 1,2
VERSION_INFO_PREFIX =
VERSIONING_SYSTEM = apple-generic
// This should be unnecessary because the script that builds the project should set it.
//
// But I'm getting the following error after switching from Xcode 14.3 to 14.3.1:
// These two settings are to ensure the framework can be used by projects using
// a different compiler version than the one used to build it.
//
// > Failed to build module 'Gutenberg'; this SDK is not supported by the compiler
// > (the SDK is built with 'Apple Swift version 5.8 (swiftlang-5.8.0.124.2 clang-1403.0.22.11.100)',
// > while this compiler is 'Apple Swift version 5.8.1 (swiftlang-5.8.0.124.5 clang-1403.0.22.11.100)').
// > Please select a toolchain which matches the SDK.
// See also https://github.com/facebook/facebook-ios-sdk/issues/2180#issuecomment-1485846511
BUILD_LIBRARY_FOR_DISTRIBUTION = YES
SKIP_INSTALL = NO
114 changes: 77 additions & 37 deletions ios-xcframework/Podfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,40 +2,25 @@

require 'xcodeproj'

REACT_NATIVE_PATH = '../gutenberg/node_modules/react-native'
require_relative File.join(REACT_NATIVE_PATH, 'scripts', 'react_native_pods')

# We are still trying to decide whether to adopt Hermes or not.
#
# This switch allows us to switch between approaches on the go.
HERMES_ENABLED = ENV.fetch('HERMES_ENABLED', true)

puts "[Gutenberg] Installing pods with Hermes #{HERMES_ENABLED ? 'enabled' : 'disabled'}"

# Note that the pods in this array might seem unused if you look for
# `import` statements in this codebase. However, make sure to also check
# whether they are used in the gutenberg-mobile and Gutenberg projects.
#
# Also notice that these are not all the dependencies the project uses.
# Later in the config, we call use_react_native! which fetches more.
#
# See https://github.com/wordpress-mobile/gutenberg-mobile/issues/5025
DEPENDENCIES = %w[
FBLazyVector
React
ReactCommon
RCTRequired
RCTTypeSafety
React-Core
React-CoreModules
React-RCTActionSheet
React-RCTAnimation
React-RCTBlob
React-RCTImage
React-RCTLinking
React-RCTNetwork
React-RCTSettings
React-RCTText
React-RCTVibration
React-callinvoker
React-cxxreact
React-jsinspector
React-jsi
React-jsiexecutor
React-logger
React-perflogger
React-runtimeexecutor
boost
Yoga
RCT-Folly
glog
react-native-safe-area
react-native-safe-area-context
react-native-video
Expand All @@ -51,21 +36,25 @@ DEPENDENCIES = %w[
RNCMaskedView
RNCClipboard
RNFastImage
React-Codegen
React-jsc
React-hermes
].freeze

def gutenberg_dependencies
podspec_prefix = '..'

# FBReactNativeSpec needs special treatment because of react-native-codegen code generation
pod 'FBReactNativeSpec',
podspec: "#{podspec_prefix}/third-party-podspecs/FBReactNativeSpec/FBReactNativeSpec.podspec.json"
computed_dependencies = DEPENDENCIES.dup

# Use a custom RNReanimated version while we coordinate a fix upstream
computed_dependencies.delete('RNReanimated')

computed_dependencies.delete('React-jsc') unless HERMES_ENABLED

DEPENDENCIES.each do |pod_name|
# Use a custom RNReanimated version while we coordinate a fix upstream
computed_dependencies.each do |pod_name|
pod pod_name, podspec: "#{podspec_prefix}/third-party-podspecs/#{pod_name}.podspec.json"
end

pod 'RNReanimated', git: 'https://github.com/wordpress-mobile/react-native-reanimated', branch: 'mokagio/fix-custom-node_modules-bypass-multiple-versions-check-2.17.0'
end

VERSION_XCCONFIG_PATH = File.join(File.expand_path(__dir__), 'Config', 'Gutenberg-Shared.xcconfig')
Expand All @@ -74,25 +63,76 @@ APP_IOS_DEPLOYMENT_TARGET = Gem::Version.new(Xcodeproj::Config.new(VERSION_XCCON

platform :ios, APP_IOS_DEPLOYMENT_TARGET.version

target 'Gutenberg' do
use_frameworks! linkage: :static
# It's important to call use_frameworks! before use_react_native!
#
# See https://github.com/facebook/react-native/issues/36120#issuecomment-1425892304
use_frameworks! linkage: :static
use_react_native! path: REACT_NATIVE_PATH, hermes_enabled: HERMES_ENABLED

target 'Gutenberg' do
pod 'RNTAztecView', path: '..'
gutenberg_dependencies
end

pre_install do
# This is required to workaround an issue with RNReanimated after upgrading to version 2.17.0
rn_node_modules = File.join(Dir.pwd, '..', 'gutenberg', 'node_modules')

raise "Could not find node modules at given path #{rn_node_modules}" unless File.exist? rn_node_modules

ENV['REACT_NATIVE_NODE_MODULES_DIR'] = rn_node_modules

puts "[Gutenberg] Set REACT_NATIVE_NODE_MODULES_DIR env var for RNReanimated to #{rn_node_modules}"
end

post_install do |installer|
react_native_post_install(installer, REACT_NATIVE_PATH)

installer.pods_project.targets.each do |target|
# Work around issue with embedding the Hermes XCFramework
#
# See https://github.com/facebook/react-native/issues/35863
if HERMES_ENABLED && target.name == 'hermes-engine'
installer.pods_project.files.each do |fileref|
next unless fileref.path.end_with? 'hermes.xcframework'

plist_buddy = '/usr/libexec/PlistBuddy'

raise "[Gutenberg] Could not find PlistBuddy at #{plist_buddy}." unless File.exist?(plist_buddy)

hermes_plist_file = "#{fileref.real_path}/Info.plist"

# Patch Hermes to remove the debug symbols entry from the Info.plist (as it's not shipped with it)
# This might be removed once Hermes starts to ship with Debug symbols or we remove our
# direct dependency from the Main iOS target on "hermes.xcframework"
Open3.capture3(plist_buddy, '-c', 'Delete :AvailableLibraries:0:DebugSymbolsPath', hermes_plist_file)
Open3.capture3(plist_buddy, '-c', 'Delete :AvailableLibraries:1:DebugSymbolsPath', hermes_plist_file)
Open3.capture3(plist_buddy, '-c', 'Delete :AvailableLibraries:2:DebugSymbolsPath', hermes_plist_file)

puts '[Gutenberg] Removed Hermes dSYMs references from its XCFramework'
end
end

# Let Pods targets inherit deployment target from the app
# See https://github.com/CocoaPods/CocoaPods/issues/4859
#
# Exclude RCT-Folly as it requires explicit deployment target
# See https://git.io/JPb73
next unless target.name != 'RCT-Folly'
next if target.name == 'RCT-Folly'

target.build_configurations.each do |configuration|
pod_ios_deployment_target = Gem::Version.new(configuration.build_settings[IOS_VERSION_KEY])
configuration.build_settings.delete(IOS_VERSION_KEY) if pod_ios_deployment_target <= APP_IOS_DEPLOYMENT_TARGET
end
end

# This is to work around FBReactNativeSpec not finding Node.
#
# gutenberg-mobile/ios-xcframework/Pods/../../gutenberg/node_modules/react-native/React/FBReactNativeSpec/../../scripts/xcode/with-environment.sh: line 35: .xcode.env: command not found
# [...]
# [Warning] You need to configure your node path in the environment. You can set it up quickly by running: echo 'export NODE_BINARY=' > .xcode.env in the ios folder. This is needed by React Native to work correctly. [...]
#
node_path = `command -v node`.strip
`echo 'export NODE_BINARY=#{node_path}' > .xcode.env`
puts "[Gutenberg] Generated .xcode.env file with NODE_BINARY=#{node_path}. You can override that value by creating a .xcode.env.local version."
end
Loading