Skip to content

Commit

Permalink
Integrate Native Module codegen into Xcode build pipeline (#30449)
Browse files Browse the repository at this point in the history
Summary:
Move the codegen invocation out of Podfiles and into the FBReactNativeSpec Pod itself. With this change, developers do not need to modify their existing project's Podfiles, and yet the codegen will be integrated into their projects automatically by way of the FBReactNativeSpec Pod.

This is accomplished in part by injecting a script build phase into the Pods Xcode project that is generated by CocoaPods. The build phase will save the output of the codegen script to a log in the derived files directory. The codegen will be executed if the codegen log file is not present, or if the contents of the Libraries directory has changed.

The codegen will thus be invoked in these situations:

**RNTester:**
* When `packages/rn-tester/RNTesterPods.xcworkspace` is built, if the codegen output logfile is not present or if the input files have changed.

**OSS React Native apps:**
* When `ios/AwesomeProject.xcworkspace` is built, if the codegen output file is not present or if the input files have changed. Normally, this should not happen, as we do not expect folks to update the contents of `node_modules/react-native/Libraries`.

Pull Request resolved: #30449

Changelog: [Internal] - Moved codegen invocation out of Podfile and into FBReactNativeSpec Pod

Reviewed By: fkgozali

Differential Revision: D25138896

fbshipit-source-id: 4779f822459cea2c30fd544eee19a49e8d80153d
  • Loading branch information
hramos authored and facebook-github-bot committed Dec 2, 2020
1 parent a4a517a commit c901c1f
Show file tree
Hide file tree
Showing 8 changed files with 84 additions and 64 deletions.
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,6 @@ package-lock.json
/Libraries/FBReactNativeSpec/FBReactNativeSpec
/packages/react-native-codegen/lib
/ReactCommon/fabric/components/rncore/
/schema-native-modules.json
/schema-rncore.json

# Visual studio
Expand Down
18 changes: 18 additions & 0 deletions Libraries/FBReactNativeSpec/FBReactNativeSpec.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,22 @@ package = JSON.parse(File.read(File.join(__dir__, "..", "..", "package.json")))
version = package['version']

source = { :git => 'https://github.com/facebook/react-native.git' }
codegen_path_prefix = ".."
if version == '1000.0.0'
# This is an unpublished version, use the latest commit hash of the react-native repo, which we’re presumably in.
source[:commit] = `git rev-parse HEAD`.strip
codegen_path_prefix = "packages"
else
source[:tag] = "v#{version}"
end

react_native_path = File.join(__dir__, "..", "..")
srcs_dir = File.join(__dir__, "..")
codegen_script_path = File.join(react_native_path, "scripts", "generate-native-modules-specs.sh")
codegen_path = File.join(react_native_path, codegen_path_prefix, "react-native-codegen")
generated_files = [File.join(__dir__, "FBReactNativeSpec", "FBReactNativeSpec.h"), File.join(__dir__, "FBReactNativeSpec", "FBReactNativeSpec-generated.mm")]
codegen_command = "CODEGEN_PATH=#{codegen_path} sh '#{codegen_script_path}' | tee \"${SCRIPT_OUTPUT_FILE_0}\""

folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-comma -Wno-shorten-64-to-32'
folly_version = '2020.01.13.00'

Expand Down Expand Up @@ -44,4 +53,13 @@ Pod::Spec.new do |s|
s.dependency "React-Core", version
s.dependency "React-jsi", version
s.dependency "ReactCommon/turbomodule/core", version

s.prepare_command = "touch #{generated_files.reduce() { |str, file| str + " " + file }}"
s.script_phase = {
:name => 'Generate Native Modules Code',
:input_files => [srcs_dir],
:output_files => ["$(DERIVED_FILE_DIR)/FBReactNativeSpec-codegen.log"],
:script => codegen_command,
:execution_position => :before_compile
}
end
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
"README.md",
"rn-get-polyfills.js",
"scripts/compose-source-maps.js",
"scripts/generate-native-modules-specs.sh",
"scripts/generate-native-modules-specs-cli.js",
"scripts/ios-configure-glog.sh",
"scripts/launchPackager.bat",
Expand Down
10 changes: 0 additions & 10 deletions packages/rn-tester/Podfile
Original file line number Diff line number Diff line change
Expand Up @@ -60,16 +60,6 @@ def frameworks_pre_install(installer)
end
end

pre_install do |installer|
frameworks_pre_install(installer) if ENV['USE_FRAMEWORKS'] == '1'
if ENV['USE_CODEGEN'] != '0'
prefix_path = "../.."
codegen_path = "../../packages/react-native-codegen"
system("./#{codegen_path}/scripts/oss/build.sh") or raise "Could not build react-native-codegen package"
codegen_pre_install(installer, {path:prefix_path, codegen_path:codegen_path})
end
end

post_install do |installer|
flipper_post_install(installer)
end
18 changes: 9 additions & 9 deletions packages/rn-tester/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@ PODS:
- Flipper-Folly (~> 2.2)
- Flipper-RSocket (~> 1.1)
- Flipper-DoubleConversion (1.1.7)
- Flipper-Folly (2.2.0):
- Flipper-Folly (2.3.0):
- boost-for-react-native
- CocoaLibEvent (~> 1.0)
- Flipper-DoubleConversion
- Flipper-Glog
- OpenSSL-Universal (= 1.0.2.19)
- OpenSSL-Universal (= 1.0.2.20)
- Flipper-Glog (0.3.6)
- Flipper-PeerTalk (0.0.4)
- Flipper-RSocket (1.1.0):
Expand Down Expand Up @@ -58,9 +58,9 @@ PODS:
- FlipperKit/Core
- FlipperKit/FlipperKitNetworkPlugin
- glog (0.3.5)
- OpenSSL-Universal (1.0.2.19):
- OpenSSL-Universal/Static (= 1.0.2.19)
- OpenSSL-Universal/Static (1.0.2.19)
- OpenSSL-Universal (1.0.2.20):
- OpenSSL-Universal/Static (= 1.0.2.20)
- OpenSSL-Universal/Static (1.0.2.20)
- RCT-Folly (2020.01.13.00):
- boost-for-react-native
- DoubleConversion
Expand Down Expand Up @@ -490,16 +490,16 @@ SPEC CHECKSUMS:
CocoaLibEvent: 2fab71b8bd46dd33ddb959f7928ec5909f838e3f
DoubleConversion: cde416483dac037923206447da6e1454df403714
FBLazyVector: fe973c09b2299b5e8154186ecf1f6554b4f70987
FBReactNativeSpec: 20a9345af9157362b51ab0258d842cb7bb347d19
FBReactNativeSpec: 4b0a53603445208c324b4a23d77590c399894efc
Flipper: be611d4b742d8c87fbae2ca5f44603a02539e365
Flipper-DoubleConversion: 38631e41ef4f9b12861c67d17cb5518d06badc41
Flipper-Folly: c12092ea368353b58e992843a990a3225d4533c3
Flipper-Folly: e4493b013c02d9347d5e0cb4d128680239f6c78a
Flipper-Glog: 1dfd6abf1e922806c52ceb8701a3599a79a200a6
Flipper-PeerTalk: 116d8f857dc6ef55c7a5a75ea3ceaafe878aadc9
Flipper-RSocket: 64e7431a55835eb953b0bf984ef3b90ae9fdddd7
FlipperKit: ab353d41aea8aae2ea6daaf813e67496642f3d7d
glog: 40a13f7840415b9a77023fbcae0f1e6f43192af3
OpenSSL-Universal: 8b48cc0d10c1b2923617dfe5c178aa9ed2689355
OpenSSL-Universal: ff34003318d5e1163e9529b08470708e389ffcdd
RCT-Folly: b39288cedafe50da43317ec7d91bcc8cc0abbf33
RCTRequired: d3d4ce60e1e2282864d7560340690a3c8c646de1
RCTTypeSafety: 4da4f9f218727257c50fd3bf2683a06cdb4fede3
Expand Down Expand Up @@ -528,6 +528,6 @@ SPEC CHECKSUMS:
Yoga: 69ef0b2bba5387523f793957a9f80dbd61e89631
YogaKit: f782866e155069a2cca2517aafea43200b01fd5a

PODFILE CHECKSUM: cd671238f92c51cd349a1c778fd089994174b101
PODFILE CHECKSUM: 3adfe268d800503789170d1862bde422ee204fe8

COCOAPODS: 1.10.0
78 changes: 56 additions & 22 deletions scripts/generate-native-modules-specs.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,54 +4,88 @@
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.

# This script collects the JavaScript spec definitions for native
# modules, then uses react-native-codegen to generate native code.
# The script will copy the generated code to the final location by
# default. Optionally, call the script with a path to the desired
# output location.
# This script collects the JavaScript spec definitions for core
# native modules, then uses react-native-codegen to generate
# native code.
# The script will use the local react-native-codegen package by
# default. Optionally, set the CODEGEN_PATH to point to the
# desired codegen library (e.g. when using react-native-codegen
# from npm).
#
# Usage:
# ./scripts/generate-native-modules-specs.sh [output-dir]
# ./scripts/generate-native-modules-specs.sh
#
# Example:
# ./scripts/generate-native-modules-specs.sh ./codegen-out
# CODEGEN_PATH=.. ./scripts/generate-native-modules-specs.sh

# shellcheck disable=SC2038

set -e

THIS_DIR=$(cd -P "$(dirname "$(readlink "${BASH_SOURCE[0]}" || echo "${BASH_SOURCE[0]}")")" && pwd)
TEMP_DIR=$(mktemp -d /tmp/react-native-codegen-XXXXXXXX)
RN_DIR=$(cd "$THIS_DIR/.." && pwd)
CODEGEN_DIR=$(cd "$RN_DIR/packages/react-native-codegen" && pwd)
OUTPUT_DIR="${1:-$RN_DIR/Libraries/FBReactNativeSpec/FBReactNativeSpec}"
SCHEMA_FILE="$RN_DIR/schema-native-modules.json"
CODEGEN_PATH="${CODEGEN_PATH:-$(cd "$RN_DIR/packages" && pwd)}"
CODEGEN_DIR="$CODEGEN_PATH/react-native-codegen"

YARN_BINARY="${YARN_BINARY:-$(command -v yarn)}"

cleanup () {
set +e
rm -rf "$TEMP_DIR"
set -e
}

describe () {
printf "\\n\\n>>>>> %s\\n\\n\\n" "$1"
}

step_build_codegen () {
describe "Building react-native-codegen package"
pushd "$CODEGEN_DIR" >/dev/null || exit
"$YARN_BINARY"
"$YARN_BINARY" build
popd >/dev/null || exit
if [ ! -d "$CODEGEN_DIR/lib" ]; then
describe "Building react-native-codegen package"
pushd "$CODEGEN_DIR" >/dev/null || exit
"$YARN_BINARY"
"$YARN_BINARY" build
popd >/dev/null || exit
fi
}

step_gen_schema () {
run_codegen () {
SRCS_DIR=$1
LIBRARY_NAME=$2
OUTPUT_DIR=$3

SCHEMA_FILE="$TEMP_DIR/schema-$LIBRARY_NAME.json"

if [ ! -d "$CODEGEN_DIR/lib" ]; then
describe "Building react-native-codegen package"
pushd "$CODEGEN_DIR" >/dev/null || exit
"$YARN_BINARY"
"$YARN_BINARY" build
popd >/dev/null || exit
fi

describe "Generating schema from flow types"
SRCS_DIR=$(cd "$RN_DIR/Libraries" && pwd)
"$YARN_BINARY" node "$CODEGEN_DIR/lib/cli/combine/combine-js-to-schema-cli.js" "$SCHEMA_FILE" "$SRCS_DIR"
}

step_gen_specs () {
describe "Generating native code from schema (iOS)"
pushd "$RN_DIR" >/dev/null || exit
"$YARN_BINARY" --silent node scripts/generate-native-modules-specs-cli.js ios "$SCHEMA_FILE" "$OUTPUT_DIR"
popd >/dev/null || exit
}

step_build_codegen
step_gen_schema
step_gen_specs
# Handle Core Modules
run_codegen_core_modules () {
LIBRARY_NAME="FBReactNativeSpec"
SRCS_DIR=$(cd "$RN_DIR/Libraries" && pwd)
OUTPUT_DIR="$SRCS_DIR/$LIBRARY_NAME/$LIBRARY_NAME"

run_codegen "$SRCS_DIR" "$LIBRARY_NAME" "$OUTPUT_DIR"
}

main() {
run_codegen_core_modules
}

trap cleanup EXIT
main "$@"
18 changes: 0 additions & 18 deletions scripts/react_native_pods.rb
Original file line number Diff line number Diff line change
Expand Up @@ -108,21 +108,3 @@ def flipper_post_install(installer)
end
end
end

# Pre Install processing for Native Modules
def codegen_pre_install(installer, options={})
# Path to React Native
prefix = options[:path] ||= "../node_modules/react-native"

# Path to react-native-codegen
codegen_path = options[:codegen_path] ||= "#{prefix}/../react-native-codegen"

# Handle Core Modules
Dir.mktmpdir do |dir|
native_module_spec_name = "FBReactNativeSpec"
schema_file = dir + "/schema-#{native_module_spec_name}.json"
srcs_dir = "#{prefix}/Libraries"
schema_generated = system("node #{codegen_path}/lib/cli/combine/combine-js-to-schema-cli.js #{schema_file} #{srcs_dir}") or raise "Could not generate Native Module schema"
specs_generated = system("node #{prefix}/scripts/generate-native-modules-specs-cli.js ios #{schema_file} #{srcs_dir}/#{native_module_spec_name}/#{native_module_spec_name}") or raise "Could not generate code for #{native_module_spec_name}"
end
end
4 changes: 0 additions & 4 deletions template/ios/Podfile
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,6 @@ target 'HelloWorld' do
# Pods for testing
end

pre_install do |installer|
codegen_pre_install(installer)
end

# Enables Flipper.
#
# Note that if you have use_frameworks! enabled, Flipper will not work and
Expand Down

0 comments on commit c901c1f

Please sign in to comment.