Codegen: Remove generate-specs.sh

Summary:
First part of the codegen script cleanup effort. Everything that was done in generate-specs.sh is now part of the CocoaPods recipe (e.g. codegen method in `react_native_pods.rb`).

Now that `generate-specs.sh` has been removed, the codegen may still be invoked manually for test purposes like so:

```
cd react-native

# Generate Schema - do this whenever your JS specs change
node packages/react-native-codegen/lib/cli/combine/combine-js-to-schema-cli.js <output_file_schema_json> <javascript_sources_dir>

# Generate native interfaces for iOS (use schema.json generated by previous step)
node scripts/generate-specs-cli.js ios <output_file_schema_json> <output_dir> <library_name>
```

Changelog: [Internal]

Reviewed By: fkgozali

Differential Revision: D30648067

fbshipit-source-id: 29688e0aac5496886657db82becb05bc8da076c9
This commit is contained in:
Héctor Ramos 2021-09-10 16:06:43 -07:00 коммит произвёл Facebook GitHub Bot
Родитель 14ecf84a9c
Коммит ef6ad1f2d6
8 изменённых файлов: 182 добавлений и 171 удалений

2
.gitignore поставляемый
Просмотреть файл

@ -105,7 +105,7 @@ package-lock.json
/React/FBReactNativeSpec/FBReactNativeSpec
/packages/react-native-codegen/lib
/ReactCommon/react/renderer/components/rncore/
/packages/rn-tester/NativeModuleExample/ScreenshotManagerSpec
/packages/rn-tester/NativeModuleExample/ScreenshotManagerSpec*
# Visual studio
.vscode

Просмотреть файл

@ -32,7 +32,7 @@ Pod::Spec.new do |s|
s.platforms = { :ios => "11.0" }
s.compiler_flags = folly_compiler_flags + ' -Wno-nullability-completeness'
s.source = source
s.source_files = "**/*.{c,h,m,mm,cpp}"
s.source_files = "**/FBReactNativeSpec*.{h,mm}"
s.header_dir = "FBReactNativeSpec"
s.pod_target_xcconfig = {
@ -52,9 +52,7 @@ Pod::Spec.new do |s|
:react_native_path => react_native_path,
:js_srcs_dir => "#{react_native_path}/Libraries",
:library_name => "FBReactNativeSpec",
:output_dir => "#{react_native_path}/React/FBReactNativeSpec",
:component_library_name => "rncore",
# TODO: component_output_dir should be programmatically specified, and may change with use_frameworks! support.
:component_output_dir => "#{react_native_path}/ReactCommon/react/renderer/components/"
:library_type => "modules",
:output_dir => "#{react_native_path}/React/FBReactNativeSpec/FBReactNativeSpec"
})
end

Просмотреть файл

@ -20,6 +20,7 @@ folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1
folly_version = '2021.06.28.00'
folly_dep_name = 'RCT-Folly/Fabric'
boost_compiler_flags = '-Wno-documentation'
react_native_path = ".."
Pod::Spec.new do |s|
s.name = "React-Fabric"
@ -341,4 +342,12 @@ Pod::Spec.new do |s|
ss.header_dir = "react/utils"
ss.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_TARGET_SRCROOT)/ReactCommon\" \"$(PODS_ROOT)/RCT-Folly\"" }
end
use_react_native_codegen!(s, {
:react_native_path => react_native_path,
:js_srcs_dir => "#{react_native_path}/Libraries",
:library_name => "rncore",
:library_type => "components",
:output_dir => "#{react_native_path}/ReactCommon",
})
end

Просмотреть файл

@ -34,6 +34,7 @@ Pod::Spec.new do |s|
use_react_native_codegen!(s, {
:react_native_path => "../../..",
:js_srcs_dir => "./",
:library_type => "modules",
:output_dir => "./"
})
end

Просмотреть файл

@ -872,7 +872,7 @@ SPEC CHECKSUMS:
CocoaAsyncSocket: 065fd1e645c7abab64f7a6a2007a48038fdc6a99
DoubleConversion: 831926d9b8bf8166fd87886c4abab286c2422662
FBLazyVector: b81a2b70c72d8b0aefb652cea22c11e9ffd02949
FBReactNativeSpec: ce190a91d6e289e5fb1fb2414c90d16cb8567ab8
FBReactNativeSpec: 55e1b4e2c593197159844fc5c7f88e68e8cb9980
Flipper: 30e8eeeed6abdc98edaf32af0cda2f198be4b733
Flipper-Boost-iOSX: fd1e2b8cbef7e662a122412d7ac5f5bea715403c
Flipper-DoubleConversion: 57ffbe81ef95306cc9e69c4aa3aeeeeb58a6a28c

Просмотреть файл

@ -79,6 +79,24 @@ function generateSpec(
fs.renameSync(`${outputDirectory}/${f}`, `${jniOutputDirectory}/${f}`);
});
}
if (platform === 'ios') {
const files = fs.readdirSync(outputDirectory);
const componentsOutputDirectory = `${outputDirectory}/react/renderer/components/${libraryName}`;
mkdirp.sync(componentsOutputDirectory);
files
.filter(
f =>
(f.endsWith('.h') && !f.startsWith(libraryName)) ||
f.endsWith('.cpp'),
)
.forEach(f => {
fs.renameSync(
`${outputDirectory}/${f}`,
`${componentsOutputDirectory}/${f}`,
);
});
}
}
function main() {

Просмотреть файл

@ -1,132 +0,0 @@
#!/bin/bash
# Copyright (c) Facebook, Inc. and its affiliates.
#
# 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 and components, then uses react-native-codegen
# to generate native code.
#
# Usage:
# ./scripts/generate-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)
# Find path to Node
# shellcheck source=/dev/null
source "$RN_DIR/scripts/find-node.sh"
NODE_BINARY="${NODE_BINARY:-$(command -v node || true)}"
cleanup () {
set +e
rm -rf "$TEMP_DIR"
set -e
}
describe () {
printf "\\n\\n>>>>> %s\\n\\n\\n" "$1" >&2
}
print_usage () {
printf "\\nNAME\\n\\t%s -- generate specs\\n" "$1" >&2
printf "\\nSYNOPSIS\\n" >&2
printf "\\t%s javascript_sources_directory specs_library_name output_directory\\n" "$1" >&2
printf "\\t%s javascript_sources_directory specs_library_name output_directory component_library_name [component_output_directory]\\n" "$1" >&2
printf "\\n\\nDESCRIPTION\\n\\tIn the first synopsis form, this script collects native module and native component JavaScript spec definitions in javascript_sources_directory, then uses react-native-codegen to generate the native interface code into a library named specs_library_name, which is copied to the destination output_directory.\\n" >&2
printf "\\n\\tIn the second synopsis form, the component_library_name will be used as the name of the component native interface code library. If provided, the component output will be copied to the component_output_directory, otherwise it will be copied to the output_directory.\\n" >&2
}
main() {
MIN_ARG_NUM=3
if [ "$#" -eq 0 ]; then
print_usage "$0"
exit 1
fi
if [ -z "$NODE_BINARY" ]; then
echo "Error: Could not find node. Make sure it is in bash PATH or set the NODE_BINARY environment variable." 1>&2
exit 1
fi
if [ "$#" -lt "$MIN_ARG_NUM" ]; then
echo "Error: Expected $MIN_ARG_NUM arguments, got $# instead. Run $0 with no arguments to learn more." 1>&2
exit 1
fi
SRCS_DIR=$1
LIBRARY_NAME=$2
OUTPUT_DIR=$3
COMPONENT_LIBRARY_NAME_OVERRIDE=$4
COMPONENT_OUTPUT_DIR_OVERRIDE=$5
PLATFORM="ios"
TEMP_OUTPUT_DIR="$TEMP_DIR/out"
SCHEMA_FILE="$TEMP_DIR/schema.json"
CODEGEN_REPO_PATH="$RN_DIR/packages/react-native-codegen"
CODEGEN_NPM_PATH="$RN_DIR/../react-native-codegen"
if [ -d "$CODEGEN_REPO_PATH" ]; then
CODEGEN_PATH=$(cd "$CODEGEN_REPO_PATH" && pwd)
elif [ -d "$CODEGEN_NPM_PATH" ]; then
CODEGEN_PATH=$(cd "$CODEGEN_NPM_PATH" && pwd)
else
echo "Error: Could not determine react-native-codegen location. Try running 'yarn install' or 'npm install' in your project root." 1>&2
exit 1
fi
if [ ! -d "$CODEGEN_PATH/lib" ]; then
describe "Building react-native-codegen package"
bash "$CODEGEN_PATH/scripts/oss/build.sh"
fi
describe "Generating schema from Flow types"
"$NODE_BINARY" "$CODEGEN_PATH/lib/cli/combine/combine-js-to-schema-cli.js" "$SCHEMA_FILE" "$SRCS_DIR"
describe "Generating native code from schema ($PLATFORM)"
pushd "$RN_DIR" >/dev/null
"$NODE_BINARY" scripts/generate-specs-cli.js "$PLATFORM" "$SCHEMA_FILE" "$TEMP_OUTPUT_DIR" "$LIBRARY_NAME"
popd >/dev/null
mkdir -p "$OUTPUT_DIR"
if [ -z "$COMPONENT_LIBRARY_NAME_OVERRIDE" ]; then
# Copy all output to output_dir
cp -R "$TEMP_OUTPUT_DIR/" "$OUTPUT_DIR"
echo >&2 "$LIBRARY_NAME output has been written to $OUTPUT_DIR:"
ls -1 "$OUTPUT_DIR" 2>&1
else
# Copy modules output to output_dir
cp "$TEMP_OUTPUT_DIR/$LIBRARY_NAME.h" "$TEMP_OUTPUT_DIR/$LIBRARY_NAME-generated.mm" "$OUTPUT_DIR"
echo >&2 "$LIBRARY_NAME output has been written to $OUTPUT_DIR:"
ls -1 "$OUTPUT_DIR" 2>&1
# Rename library name used in components output files
find "$TEMP_OUTPUT_DIR" -type f | xargs sed -i.bak "s/$LIBRARY_NAME/$COMPONENT_LIBRARY_NAME_OVERRIDE/g"
if [ -n "$COMPONENT_OUTPUT_DIR_OVERRIDE" ]; then
# Components codegen output to be moved to separate directory
mkdir -p "$COMPONENT_OUTPUT_DIR_OVERRIDE"
OUTPUT_DIR="$COMPONENT_OUTPUT_DIR_OVERRIDE"
fi
find "$TEMP_OUTPUT_DIR" -type f -not -iname "$LIBRARY_NAME.h" -not -iname "$LIBRARY_NAME-generated.mm" -not -iname "*.bak" -exec cp '{}' "$OUTPUT_DIR/" ';'
echo >&2 "$COMPONENT_LIBRARY_NAME_OVERRIDE output has been written to $OUTPUT_DIR:"
ls -1 "$OUTPUT_DIR" 2>&1
fi
echo >&2 'Done.'
}
trap cleanup EXIT
main "$@"

Просмотреть файл

@ -159,56 +159,173 @@ def use_react_native_codegen!(spec, options={})
# The prefix to react-native
prefix = options[:react_native_path] ||= "../.."
# The path to JavaScript files
js_srcs = options[:js_srcs_dir] ||= "#{prefix}/Libraries"
# Library name (e.g. FBReactNativeSpec)
library_name = options[:library_name] ||= "#{spec.name}Spec"
# Output dir, relative to podspec that invoked this method
output_dir = options[:output_dir] ||= "#{prefix}/React/#{library_name}"
output_dir = options[:output_dir] ||= "#{library_name}"
components_output_dir = "#{output_dir}/react/renderer/components/#{library_name}"
generated_dirs = [ "#{output_dir}/#{library_name}" ]
generated_filenames = [ "#{library_name}.h", "#{library_name}-generated.mm" ]
generated_files = generated_filenames.map { |filename| "#{output_dir}/#{library_name}/#{filename}" }
codegen_config = {
"modules" => {
:js_srcs_pattern => "Native*.js",
:generated_dir => output_dir,
:generated_files => [
"#{library_name}.h",
"#{library_name}-generated.mm"
]
},
"components" => {
:js_srcs_pattern => "*NativeComponent.js",
:generated_dir => components_output_dir,
:generated_files => [
"ComponentDescriptors.h",
"EventEmitters.cpp",
"EventEmitters.h",
"Props.cpp",
"Props.h",
"RCTComponentViewHelpers.h",
"ShadowNodes.cpp",
"ShadowNodes.h"
]
}
}
# Run the codegen as part of the Xcode build pipeline.
codegen_script_args = [ "'${PODS_TARGET_SRCROOT}/#{js_srcs}'" ]
codegen_script_args.push "'#{library_name}'"
codegen_script_args.push "'${PODS_TARGET_SRCROOT}/#{output_dir}/#{library_name}'"
# The path to JavaScript files
js_srcs_dir = options[:js_srcs_dir] ||= "./"
library_type = options[:library_type]
# We use a different library name for components, as well as an additional set of files.
# Eventually, we want these to be part of the same library as #{library_name} above.
component_library_name = options[:component_library_name] ||= library_name
component_output_dir = options[:component_output_dir] ||= output_dir
generated_dirs.push "#{component_output_dir}/#{component_library_name}"
codegen_script_args.push "'#{component_library_name}'"
codegen_script_args.push "'${PODS_TARGET_SRCROOT}/#{component_output_dir}/#{component_library_name}'"
components_generated_filenames = [
"ComponentDescriptors.h",
"EventEmitters.cpp",
"EventEmitters.h",
"Props.cpp",
"Props.h",
"RCTComponentViewHelpers.h",
"ShadowNodes.cpp",
"ShadowNodes.h"
]
generated_files = generated_files.concat(components_generated_filenames.map { |filename| "#{component_output_dir}/#{component_library_name}/#{filename}" })
if library_type
js_srcs_pattern = codegen_config[library_type][:js_srcs_pattern]
end
if library_type
generated_dirs = [ codegen_config[library_type][:generated_dir] ]
generated_files = codegen_config[library_type][:generated_files].map { |filename| "#{codegen_config[library_type][:generated_dir]}/#{filename}" }
else
generated_dirs = [ codegen_config["modules"][:generated_dir], codegen_config["components"][:generated_dir] ]
generated_files = codegen_config["modules"][:generated_files].map { |filename| "#{codegen_config["modules"][:generated_dir]}/#{filename}" }
generated_files = generated_files.concat(codegen_config["components"][:generated_files].map { |filename| "#{codegen_config["components"][:generated_dir]}/#{filename}" })
end
if js_srcs_pattern
file_list = `find #{js_srcs_dir} -type f -name #{js_srcs_pattern}`.split("\n").sort
input_files = file_list.map { |filename| "${PODS_TARGET_SRCROOT}/#{filename}" }
else
input_files = [ js_srcs_dir ]
end
# Prepare filesystem by creating empty files that will be picked up as references by CocoaPods.
prepare_command = "mkdir -p #{generated_dirs.join(" ")} && touch -a #{generated_files.join(" ")}"
system(prepare_command) # Always run prepare_command when a podspec uses the codegen, as CocoaPods may skip invoking this command in certain scenarios
system(prepare_command) # Always run prepare_command when a podspec uses the codegen, as CocoaPods may skip invoking this command in certain scenarios. Replace with pre_integrate_hook after updating to CocoaPods 1.11
spec.prepare_command = prepare_command
spec.script_phase = {
:name => 'Generate Specs',
:input_files => [ "${PODS_TARGET_SRCROOT}/#{js_srcs}" ], # This also needs to be relative to Xcode
:input_files => input_files, # This also needs to be relative to Xcode
:output_files => ["${DERIVED_FILE_DIR}/codegen-#{library_name}.log"].concat(generated_files.map { |filename| " ${PODS_TARGET_SRCROOT}/#{filename}"} ),
# The final generated files will be created when this script is invoked at Xcode build time.
:script => %{set -o pipefail
set -e
bash -l -c '$\{PODS_TARGET_SRCROOT\}/#{prefix}/scripts/generate-specs.sh #{codegen_script_args.join(" ")}' 2>&1 | tee "${SCRIPT_OUTPUT_FILE_0}"
RN_DIR=$(cd "$\{PODS_TARGET_SRCROOT\}/#{prefix}" && pwd)
GENERATED_SRCS_DIR="$\{DERIVED_FILE_DIR\}/generated/source/codegen"
GENERATED_SCHEMA_FILE="$GENERATED_SRCS_DIR/schema.json"
TEMP_OUTPUT_DIR="$GENERATED_SRCS_DIR/out"
LIBRARY_NAME="#{library_name}"
OUTPUT_DIR="$\{PODS_TARGET_SRCROOT\}/#{output_dir}"
CODEGEN_REPO_PATH="$RN_DIR/packages/react-native-codegen"
CODEGEN_NPM_PATH="$RN_DIR/../react-native-codegen"
CODEGEN_CLI_PATH=""
# Determine path to react-native-codegen
if [ -d "$CODEGEN_REPO_PATH" ]; then
CODEGEN_CLI_PATH=$(cd "$CODEGEN_REPO_PATH" && pwd)
elif [ -d "$CODEGEN_NPM_PATH" ]; then
CODEGEN_CLI_PATH=$(cd "$CODEGEN_NPM_PATH" && pwd)
else
echo "error: Could not determine react-native-codegen location. Try running 'yarn install' or 'npm install' in your project root." >> "${SCRIPT_OUTPUT_FILE_0}" 2>&1
exit 1
fi
find_node () {
source "$RN_DIR/scripts/find-node.sh"
NODE_BINARY="${NODE_BINARY:-$(command -v node || true)}"
if [ -z "$NODE_BINARY" ]; then
echo "error: Could not find node. Make sure it is in bash PATH or set the NODE_BINARY environment variable." >> "${SCRIPT_OUTPUT_FILE_0}" 2>&1
exit 1
fi
}
setup_dirs () {
set +e
rm -rf "$GENERATED_SRCS_DIR"
set -e
mkdir -p "$GENERATED_SRCS_DIR" "$TEMP_OUTPUT_DIR"
# Clear output files
> "${SCRIPT_OUTPUT_FILE_0}"
}
describe () {
printf "\\n\\n>>>>> %s\\n\\n\\n" "$1" >> "${SCRIPT_OUTPUT_FILE_0}" 2>&1
}
buildCodegenCLI () {
if [ ! -d "$CODEGEN_CLI_PATH/lib" ]; then
describe "Building react-native-codegen package"
bash "$CODEGEN_CLI_PATH/scripts/oss/build.sh"
fi
}
generateCodegenSchemaFromJavaScript () {
describe "Generating codegen schema from JavaScript"
SRCS_PATTERN="#{js_srcs_pattern}"
SRCS_DIR="#{js_srcs_dir}"
if [ $SRCS_PATTERN ]; then
JS_SRCS=$(find "$\{PODS_TARGET_SRCROOT\}"/$SRCS_DIR -type f -name "$SRCS_PATTERN" -print0 | xargs -0)
echo "#{file_list}" >> "${SCRIPT_OUTPUT_FILE_0}" 2>&1
else
JS_SRCS="$\{PODS_TARGET_SRCROOT\}/$SRCS_DIR"
echo "#{js_srcs_dir}" >> "${SCRIPT_OUTPUT_FILE_0}" 2>&1
fi
"$NODE_BINARY" "$CODEGEN_CLI_PATH/lib/cli/combine/combine-js-to-schema-cli.js" "$GENERATED_SCHEMA_FILE" $JS_SRCS
}
generateCodegenArtifactsFromSchema () {
describe "Generating codegen artifacts from schema"
pushd "$RN_DIR" >/dev/null || exit 1
"$NODE_BINARY" "scripts/generate-specs-cli.js" ios "$GENERATED_SCHEMA_FILE" "$TEMP_OUTPUT_DIR" "$LIBRARY_NAME"
popd >/dev/null || exit 1
}
moveOutputs () {
mkdir -p "$OUTPUT_DIR"
# Copy all output to output_dir
cp -R "$TEMP_OUTPUT_DIR/" "$OUTPUT_DIR" || exit 1
echo "$LIBRARY_NAME output has been written to $OUTPUT_DIR:" >> "${SCRIPT_OUTPUT_FILE_0}" 2>&1
ls -1 "$OUTPUT_DIR" >> "${SCRIPT_OUTPUT_FILE_0}" 2>&1
}
main () {
setup_dirs
find_node
buildCodegenCLI
generateCodegenSchemaFromJavaScript
generateCodegenArtifactsFromSchema
moveOutputs
}
main "$@"
echo 'Done.' >> "${SCRIPT_OUTPUT_FILE_0}" 2>&1
},
:execution_position => :before_compile,
:show_env_vars_in_log => true