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

Change the Gutenberg integration to use XCFramework #20717

Closed
wants to merge 29 commits into from
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
b7fd735
Add a local `podspec` to download Gutenberg XCFramework commit builds
mokagio May 17, 2023
27e6b3f
Add check to fail `pod install` if Gutenberg ZIP doesn't exist at URL
mokagio May 17, 2023
22334c5
Use latest CocoaPods version
mokagio May 17, 2023
aca165e
Switch to tar.gz for the Gutenberg XCFramework archive
mokagio May 17, 2023
211b497
Use same license as the main project for the Gutenberg pod
mokagio May 18, 2023
0aa0487
Work around CP not finding XCFrameworks by downloading manually
mokagio May 22, 2023
dffeb71
Add a couple of newly required `import React`
mokagio May 22, 2023
1acc425
Address new warnings introduced by the Gutenberg via XCFramework
mokagio May 22, 2023
8176593
Update `CopyGutenbergJS` build phase script to account for XCFramework
mokagio May 23, 2023
7d31186
Use relative paths when importing the local Gutenberg podspec
mokagio May 25, 2023
27186a2
Remove `pre_install` download hook in favor of `prepare_command`
mokagio Jun 2, 2023
a4c6070
Use remote spec instead of a local one for Gutenberg via commit
mokagio Jun 5, 2023
11b0d2c
Update Gutenberg `tar.gz` URL after changes in gutenberg-mobile
mokagio Jun 7, 2023
64ac588
Use Xcode 14.3.1
mokagio Jun 8, 2023
ede6c5d
Update Gutenberg CP setup to use XCFrameworks when referenced via tag
mokagio Jun 13, 2023
0806f9b
Switch to Gutenberg v1.98.1 installed as an XCFramework
mokagio Jun 21, 2023
dfae970
Do not `@testable import` Gutenberg in unit tests
mokagio Jun 21, 2023
4726973
DRY logic setting Gutenberg URL when using tag or commit
mokagio Jun 28, 2023
c2c46cc
Simplify `gutenberg_dependencies` with early return
mokagio Jun 28, 2023
59d7b78
Update Gutenberg local setup to work with React Native 0.71.11
mokagio Jul 3, 2023
d03be58
Add calls to RN hooks when using Gutenberg from local path
mokagio Jul 3, 2023
3fcd1b5
Update build script to run locally without a Gutenberg `App.js`
mokagio Jul 4, 2023
b6b8d9c
Shrink inline comment of `gutenberg_post_install` helper
fluiddot Jul 6, 2023
d6dd34e
Update `Podfile.lock` file
fluiddot Jul 6, 2023
d81f466
Add build phase to prevent nested frameworks
mokagio Jul 18, 2023
f875968
Remove outdated Xcode 12.5 mention from nested frameworks linter
mokagio Jul 19, 2023
9192af0
Merge branch 'trunk' into mokagio/gutenberg-xcframework-setup
fluiddot Jul 19, 2023
723f8ed
Reintroduce link to internal doc with "Do Not Embed" explanation
mokagio Jul 19, 2023
e39537b
Add build phase to detect nested frameworks (#21130)
mokagio Jul 20, 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
2 changes: 1 addition & 1 deletion Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

source 'https://rubygems.org'

# 1.12.x and higher, starting from 1.12.1
# 1.12.x and higher, starting from 1.12.1, because that hotfix fixes Xcode 14.3 compatibility
gem 'cocoapods', '~> 1.12', '>= 1.12.1'
gem 'commonmarker'
gem 'danger', '~> 9.3'
Expand Down
4 changes: 1 addition & 3 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,11 @@ GEM
specs:
CFPropertyList (3.0.6)
rexml
activesupport (6.1.7.3)
activesupport (7.0.4.3)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 1.6, < 2)
minitest (>= 5.1)
tzinfo (~> 2.0)
zeitwerk (~> 2.3)
addressable (2.8.4)
public_suffix (>= 2.0.2, < 6.0)
algoliasearch (1.27.5)
Expand Down Expand Up @@ -366,7 +365,6 @@ GEM
rouge (~> 2.0.7)
xcpretty-travis-formatter (1.0.1)
xcpretty (~> 0.2, >= 0.0.7)
zeitwerk (2.6.8)

PLATFORMS
ruby
Expand Down
158 changes: 108 additions & 50 deletions Gutenberg/cocoapods_helpers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,40 +6,14 @@

DEFAULT_GUTENBERG_LOCATION = File.join(__dir__, '..', '..', 'gutenberg-mobile')

LOCAL_GUTENBERG_KEY = 'LOCAL_GUTENBERG'

# 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.
#
# 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 @@ -55,45 +29,129 @@
RNCMaskedView
RNCClipboard
RNFastImage
React-Codegen
React-bridging
React-jsc
].freeze

def gutenberg_pod(config: GUTENBERG_CONFIG)
options = config

local_gutenberg_key = 'LOCAL_GUTENBERG'
local_gutenberg = ENV.fetch(local_gutenberg_key, nil)
if local_gutenberg
options = { path: File.exist?(local_gutenberg) ? local_gutenberg : DEFAULT_GUTENBERG_LOCATION }
# We check local_gutenberg first because it should take precedence, being an override set by the user.
if should_use_local_gutenberg
options = { path: local_gutenberg_path }

raise "Could not find Gutenberg pod at #{options[:path]}. You can configure the path using the #{LOCAL_GUTENBERG_KEY} environment variable." unless File.exist?(options[:path])

puts "[Gutenberg] Installing pods using local Gutenberg version from #{local_gutenberg_path}"

react_native_path = require_react_native_helpers!(gutenberg_path: local_gutenberg_path)

use_react_native! path: react_native_path

pod 'Gutenberg', options
pod 'RNTAztecView', options

raise "Could not find Gutenberg pod at #{options[:path]}. You can configure the path using the #{local_gutenberg_key} environment variable." unless File.exist?(options[:path])
gutenberg_dependencies(options: options)
else
options[:git] = "https://github.com/#{GITHUB_ORG}/#{REPO_NAME}.git"
options[:submodules] = true
end
id = options[:tag] || options[:commit]

pod 'Gutenberg', options
pod 'RNTAztecView', options
# Notice there's no period at the end of the message as CocoaPods will add it.
raise 'Neither tag nor commit to use for Gutenberg found' unless id

gutenberg_dependencies(options: options)
pod 'Gutenberg', podspec: "https://cdn.a8c-ci.services/gutenberg-mobile/Gutenberg-#{id}.podspec"
end
end

def gutenberg_dependencies(options:)
if options[:path]
podspec_prefix = options[:path]
else
tag_or_commit = options[:tag] || options[:commit]
podspec_prefix = "https://raw.githubusercontent.com/#{GITHUB_ORG}/#{REPO_NAME}/#{tag_or_commit}"
end
# When referencing via a tag or commit, we download pre-built frameworks.
return if options.key?(:tag) || options.key?(:commit)

podspec_prefix = options[:path]

raise "Unexpected Gutenberg dependencies configuration '#{options}'" if podspec_prefix.nil?

podspec_prefix += '/third-party-podspecs'
podspec_extension = 'podspec.json'

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

DEPENDENCIES.each do |pod_name|
# Use a custom RNReanimated version while we coordinate a fix upstream
computed_dependencies.delete('RNReanimated')
pod 'RNReanimated', git: 'https://github.com/wordpress-mobile/react-native-reanimated', branch: 'mokagio/fix-custom-node_modules-bypass-multiple-versions-check-2.17.0'

computed_dependencies.each do |pod_name|
pod pod_name, podspec: "#{podspec_prefix}/#{pod_name}.#{podspec_extension}"
end
end

def gutenberg_pre_install
return unless should_use_local_gutenberg

raise "[Gutenberg] Could not find local Gutenberg at given path #{local_gutenberg_path}" unless File.exist?(local_gutenberg_path)

# This is required to workaround an issue with RNReanimated after upgrading to version 2.17.0
rn_node_modules = File.join(local_gutenberg_path, '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

def gutenberg_post_install(installer:)
return unless should_use_local_gutenberg

raise "[Gutenberg] Could not find local Gutenberg at given path #{local_gutenberg_path}" unless File.exist?(local_gutenberg_path)

react_native_path = require_react_native_helpers!(gutenberg_path: local_gutenberg_path)

puts "[Gutenberg] Running Gunberg post install hook (RN path: #{react_native_path})"

# It seems like React Native prepends $PWD to the path internally in the post install hook.
# When using an absolute path, we get this error, notice the duplicated "/Users/gio/Developer/a8c/wpios":
#
# [!] An error occurred while processing the post-install hook of the Podfile.
#
# No such file or directory @ rb_sysopen - <GUTENBERG_MOBILE_PROJECT_PATH>/gutenberg/node_modules/react-native/package.json
#
# To workaround, we make sure the path is relative to Dir.pwd
react_native_path = Pathname.new(react_native_path).relative_path_from(Dir.pwd)

react_native_post_install(installer, react_native_path)
end

private

def should_use_local_gutenberg
value = ENV.fetch(LOCAL_GUTENBERG_KEY, nil)

return false if value.nil?

value
end

def local_gutenberg_path
local_gutenberg = ENV.fetch(LOCAL_GUTENBERG_KEY, nil)

return nil if local_gutenberg.nil?

return local_gutenberg if File.exist?(local_gutenberg)

DEFAULT_GUTENBERG_LOCATION
end

def require_react_native_helpers!(gutenberg_path:)
react_native_path = react_native_path!(gutenberg_path: gutenberg_path)

require_relative File.join(react_native_path, 'scripts', 'react_native_pods')

react_native_path
end

def react_native_path!(gutenberg_path:)
react_native_path = File.join(gutenberg_path, 'gutenberg', 'node_modules', 'react-native')

raise "[Gutenberg] Could not find React Native at given path #{react_native_path}" unless File.exist?(react_native_path)

react_native_path
end
5 changes: 5 additions & 0 deletions Podfile
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,9 @@ end
# A future version of CocoaPods may make this easier to do. See https://github.com/CocoaPods/CocoaPods/issues/7428
shared_targets = ['WordPressFlux']
pre_install do |installer|
# Note that this call is unrelated to the static vs dynamic framework shenanigan below
gutenberg_pre_install

static = []
dynamic = []
installer.pod_targets.each do |pod|
Expand All @@ -340,6 +343,8 @@ pre_install do |installer|
end

post_install do |installer|
gutenberg_post_install(installer: installer)

project_root = File.dirname(__FILE__)

## Convert the 3rd-party license acknowledgements markdown into html for use in the app
Expand Down
Loading