diff --git a/packages/rn-tester/Podfile.lock b/packages/rn-tester/Podfile.lock index d04d379762b..898d8d5b859 100644 --- a/packages/rn-tester/Podfile.lock +++ b/packages/rn-tester/Podfile.lock @@ -881,7 +881,7 @@ SPEC CHECKSUMS: CocoaAsyncSocket: 065fd1e645c7abab64f7a6a2007a48038fdc6a99 DoubleConversion: 831926d9b8bf8166fd87886c4abab286c2422662 FBLazyVector: b81a2b70c72d8b0aefb652cea22c11e9ffd02949 - FBReactNativeSpec: 755b7fee1b08aefd74fb2fa9f7312b253719d536 + FBReactNativeSpec: 02b0c2bc3cf30c9ab1d5af08c22b5573bc6af06c Flipper: 30e8eeeed6abdc98edaf32af0cda2f198be4b733 Flipper-Boost-iOSX: fd1e2b8cbef7e662a122412d7ac5f5bea715403c Flipper-DoubleConversion: 57ffbe81ef95306cc9e69c4aa3aeeeeb58a6a28c @@ -923,13 +923,13 @@ SPEC CHECKSUMS: React-RCTTest: 12bbd7fc2e72bd9920dc7286c5b8ef96639582b6 React-RCTText: e9146b2c0550a83d1335bfe2553760070a2d75c7 React-RCTVibration: 50be9c390f2da76045ef0dfdefa18b9cf9f35cfa - React-rncore: d09af3a25cbff0b484776785676c28f3729e07f5 + React-rncore: 5293698ae0222ddbaf47ce6193591b5fe3cb826c React-runtimeexecutor: 4b0c6eb341c7d3ceb5e2385cb0fdb9bf701024f3 ReactCommon: 7a2714d1128f965392b6f99a8b390e3aa38c9569 - ScreenshotManager: e8a3fc9b2e24b81127b36cb4ebe0eed65090c949 + ScreenshotManager: 99830e1bd3d2b595ef092bb20fe9bb644deb9082 Yoga: c0d06f5380d34e939f55420669a60fe08b79bd75 YogaKit: f782866e155069a2cca2517aafea43200b01fd5a -PODFILE CHECKSUM: 6810c1f54b7ab3da57902075dc52d71735447464 +PODFILE CHECKSUM: 064c91fbb8ac895e453a791ebaaae5cfe9c8557d COCOAPODS: 1.11.2 diff --git a/scripts/react_native_pods.rb b/scripts/react_native_pods.rb index 77e045f286e..4d91bfa1c80 100644 --- a/scripts/react_native_pods.rb +++ b/scripts/react_native_pods.rb @@ -8,6 +8,8 @@ require 'pathname' $CODEGEN_OUTPUT_DIR = 'build/generated/ios' $CODEGEN_COMPONENT_DIR = 'react/renderer/components' $CODEGEN_MODULE_DIR = '.' +$REACT_CODEGEN_PODSPEC_GENERATED = false +$REACT_CODEGEN_DISCOVERY_DONE = false def use_react_native! (options={}) # The prefix to react-native @@ -69,8 +71,6 @@ def use_react_native! (options={}) pod 'RCT-Folly', :podspec => "#{prefix}/third-party-podspecs/RCT-Folly.podspec" if ENV['USE_CODEGEN_DISCOVERY'] == '1' - Pod::UI.puts "[Codegen] Building target with codegen library discovery enabled." - # TODO: Make sure this is run only once per execution. app_path = options[:app_path] config_file_dir = options[:config_file_dir] use_react_native_codegen_discovery!({ @@ -79,11 +79,14 @@ def use_react_native! (options={}) fabric_enabled: fabric_enabled, config_file_dir: config_file_dir, }) + else + # Generate a podspec file for generated files. + # This gets generated in use_react_native_codegen_discovery when codegen discovery is enabled. + react_codegen_spec = get_react_codegen_spec(fabric_enabled: fabric_enabled) + generate_react_codegen_podspec!(react_codegen_spec) end - # Generate a podspec file for generated files. - temp_podinfo = generate_temp_pod_spec_for_codegen!(fabric_enabled) - pod temp_podinfo['spec']['name'], :path => temp_podinfo['path'] + pod 'React-Codegen', :path => $CODEGEN_OUTPUT_DIR if fabric_enabled checkAndGenerateEmptyThirdPartyProvider!(prefix) @@ -267,10 +270,9 @@ def checkAndGenerateEmptyThirdPartyProvider!(react_native_path) end end -def generate_temp_pod_spec_for_codegen!(fabric_enabled) - relative_installation_root = Pod::Config.instance.installation_root.relative_path_from(Pathname.pwd) - output_dir = "#{relative_installation_root}/#{$CODEGEN_OUTPUT_DIR}" - Pod::Executable.execute_command("mkdir", ["-p", output_dir]); +def get_react_codegen_spec(options={}) + fabric_enabled = options[:fabric_enabled] ||= false + script_phases = options[:script_phases] ||= nil package = JSON.parse(File.read(File.join(__dir__, "..", "package.json"))) version = package['version'] @@ -283,7 +285,6 @@ def generate_temp_pod_spec_for_codegen!(fabric_enabled) source[:tag] = "v#{version}" end - folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-comma -Wno-shorten-64-to-32' folly_version = '2021.06.28.00-v2' boost_version = '1.76.0' @@ -331,6 +332,161 @@ def generate_temp_pod_spec_for_codegen!(fabric_enabled) }); end + if script_phases + Pod::UI.puts "[Codegen] Adding script_phases to React-Codegen." + spec[:'script_phases'] = script_phases + end + + return spec +end + +def get_react_codegen_script_phases(options={}) + app_path = options[:app_path] ||= '' + if !app_path + Pod::UI.warn '[Codegen] error: app_path is requried to use codegen discovery.' + exit 1 + end + + # We need to convert paths to relative path from installation_root for the script phase for CI. + relative_app_root = Pathname.new(app_path).relative_path_from(Pod::Config.instance.installation_root) + + config_file_dir = options[:config_file_dir] ||= '' + relative_config_file_dir = '' + if config_file_dir + relative_config_file_dir = Pathname.new(config_file_dir).relative_path_from(Pod::Config.instance.installation_root) + end + + fabric_enabled = options[:fabric_enabled] ||= false + + # react_native_path should be relative already. + react_native_path = options[:react_native_path] ||= "../node_modules/react-native" + + # Add a script phase to trigger generate artifact. + # Some code is duplicated so that it's easier to delete the old way and switch over to this once it's stabilized. + return { + 'name': 'Generate Specs', + 'execution_position': :before_compile, + 'input_files' => ['${DERIVED_FILE_DIR}/.tmpfile'], + 'show_env_vars_in_log': true, + 'output_files': ["${DERIVED_FILE_DIR}/react-codegen.log"], + 'script': %{set -o pipefail +set -e + +# A known hack to run this script every time. +# TODO: Further improvement will be to specify actual input files +# so that it doesn't have to rebuild libraries every time. +touch "${SCRIPT_INPUT_FILE_0}" + +pushd "${PODS_ROOT}/../" > /dev/null +POD_INSTALLATION_ROOT=$(pwd) +popd >/dev/null +RN_DIR=$(cd "$POD_INSTALLATION_ROOT/#{react_native_path}" && pwd) + +GENERATED_SRCS_DIR="$\{DERIVED_FILE_DIR\}/generated/source/codegen-discovery" +TEMP_OUTPUT_DIR="$GENERATED_SRCS_DIR/out" + +APP_PATH="$POD_INSTALLATION_ROOT/#{$relative_app_root}" +CONFIG_FILE_DIR="#{relative_config_file_dir ? "$POD_INSTALLATION_ROOT/#{relative_config_file_dir}" : ''}" +OUTPUT_DIR="$POD_INSTALLATION_ROOT" +FABRIC_ENABLED="#{fabric_enabled}" + +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 +} + +generateArtifacts () { + describe "Generating codegen artifacts" + pushd "$RN_DIR" >/dev/null || exit 1 +CONFIG_FILE_DIR="$POD_INSTALLATION_ROOT/#{$relative_config_file_dir}" + "$NODE_BINARY" "scripts/generate-artifacts.js" --path "$APP_PATH" --outputPath "$OUTPUT_DIR" --fabricEnabled "$FABRIC_ENABLED" --configFileDir "$CONFIG_FILE_DIR" + 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 "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 + generateArtifacts + moveOutputs +} + +main "$@" +echo 'Done.' >> "${SCRIPT_OUTPUT_FILE_0}" 2>&1 + }, + } + +end + +def set_react_codegen_podspec_generated(value) + $REACT_CODEGEN_PODSPEC_GENERATED = value +end + +def has_react_codegen_podspec_generated() + return $REACT_CODEGEN_PODSPEC_GENERATED +end + +def generate_react_codegen_podspec!(spec) + # This podspec file should only be create once in the session/pod install. + # This happens when multiple targets are calling use_react_native!. + if has_react_codegen_podspec_generated() + Pod::UI.puts "[Codegen] Skipping React-Codegen podspec generation." + return + end + relative_installation_root = Pod::Config.instance.installation_root.relative_path_from(Pathname.pwd) + output_dir = "#{relative_installation_root}/#{$CODEGEN_OUTPUT_DIR}" + Pod::Executable.execute_command("mkdir", ["-p", output_dir]); + podspec_path = File.join(output_dir, 'React-Codegen.podspec.json') Pod::UI.puts "[Codegen] Generating #{podspec_path}" @@ -339,6 +495,8 @@ def generate_temp_pod_spec_for_codegen!(fabric_enabled) f.fsync end + set_react_codegen_podspec_generated(true) + return { "spec" => spec, "path" => $CODEGEN_OUTPUT_DIR, # Path needs to be relative to `Podfile` @@ -349,27 +507,40 @@ end def use_react_native_codegen_discovery!(options={}) return if ENV['DISABLE_CODEGEN'] == '1' + if $REACT_CODEGEN_DISCOVERY_DONE + Pod::UI.puts "[Codegen] Skipping use_react_native_codegen_discovery." + return + end + Pod::UI.warn '[Codegen] warn: using experimental new codegen integration' react_native_path = options[:react_native_path] ||= "../node_modules/react-native" app_path = options[:app_path] fabric_enabled = options[:fabric_enabled] ||= false config_file_dir = options[:config_file_dir] ||= '' - if app_path - out = Pod::Executable.execute_command( - 'node', - [ - "#{react_native_path}/scripts/generate-artifacts.js", - "-p", "#{app_path}", - "-o", Pod::Config.instance.installation_root, - "-e", "#{fabric_enabled}", - "-c", "#{config_file_dir}", - ]) - Pod::UI.puts out; - else - Pod::UI.warn '[Codegen] error: no app_path was provided' + + if !app_path + Pod::UI.warn '[Codegen] Error: app_path is required for use_react_native_codegen_discovery.' Pod::UI.warn '[Codegen] If you are calling use_react_native_codegen_discovery! in your Podfile, please remove the call and pass `app_path` and/or `config_file_dir` to `use_react_native!`.' exit 1 end + + # Generate React-Codegen podspec here to add the script phases. + script_phases = get_react_codegen_script_phases(options) + react_codegen_spec = get_react_codegen_spec(fabric_enabled: fabric_enabled, script_phases: script_phases) + generate_react_codegen_podspec!(react_codegen_spec) + + out = Pod::Executable.execute_command( + 'node', + [ + "#{react_native_path}/scripts/generate-artifacts.js", + "-p", "#{app_path}", + "-o", Pod::Config.instance.installation_root, + "-e", "#{fabric_enabled}", + "-c", "#{config_file_dir}", + ]) + Pod::UI.puts out; + + $REACT_CODEGEN_DISCOVERY_DONE = true end def use_react_native_codegen!(spec, options={}) @@ -453,7 +624,7 @@ def use_react_native_codegen!(spec, options={}) set -e pushd "${PODS_ROOT}/../" > /dev/null -PROJECT_DIR=$(pwd) +POD_INSTALLATION_ROOT=$(pwd) popd >/dev/null RN_DIR=$(cd "$\{PODS_TARGET_SRCROOT\}/#{prefix}" && pwd) @@ -462,7 +633,7 @@ GENERATED_SCHEMA_FILE="$GENERATED_SRCS_DIR/schema.json" TEMP_OUTPUT_DIR="$GENERATED_SRCS_DIR/out" LIBRARY_NAME="#{library_name}" -OUTPUT_DIR="$PROJECT_DIR/#{$CODEGEN_OUTPUT_DIR}" +OUTPUT_DIR="$POD_INSTALLATION_ROOT/#{$CODEGEN_OUTPUT_DIR}" CODEGEN_REPO_PATH="$RN_DIR/packages/react-native-codegen" CODEGEN_NPM_PATH="$RN_DIR/../react-native-codegen"