diff --git a/packages/react-native/scripts/codegen/generate-artifacts-executor/generateReactCodegenPodspec.js b/packages/react-native/scripts/codegen/generate-artifacts-executor/generateReactCodegenPodspec.js index 42eeebe7604413..0017bcd41e5f69 100644 --- a/packages/react-native/scripts/codegen/generate-artifacts-executor/generateReactCodegenPodspec.js +++ b/packages/react-native/scripts/codegen/generate-artifacts-executor/generateReactCodegenPodspec.js @@ -76,14 +76,18 @@ function getInputFiles(appPath /*: string */, appPkgJson /*: $FlowFixMe */) { return `[${list}]`; } -function codegenScripts(appPath /*: string */, outputPath /*: string */) { - const relativeAppPath = path.relative(outputPath, appPath); +function codegenScripts(appPath /*: string */, baseOutputPath /*: string */) { + const relativeAppPath = path.relative(baseOutputPath, appPath); + const relativeReactNativeRootFolder = path.relative( + baseOutputPath, + REACT_NATIVE_PACKAGE_ROOT_FOLDER, + ); return `<<-SCRIPT pushd "$PODS_ROOT/../" > /dev/null RCT_SCRIPT_POD_INSTALLATION_ROOT=$(pwd) popd >/dev/null -export RCT_SCRIPT_RN_DIR="$RCT_SCRIPT_POD_INSTALLATION_ROOT/${path.relative(outputPath, REACT_NATIVE_PACKAGE_ROOT_FOLDER)}" +export RCT_SCRIPT_RN_DIR="$RCT_SCRIPT_POD_INSTALLATION_ROOT/${relativeReactNativeRootFolder}" export RCT_SCRIPT_APP_PATH="$RCT_SCRIPT_POD_INSTALLATION_ROOT/${relativeAppPath.length === 0 ? '.' : relativeAppPath}" export RCT_SCRIPT_OUTPUT_DIR="$RCT_SCRIPT_POD_INSTALLATION_ROOT" export RCT_SCRIPT_TYPE="withCodegenDiscovery" diff --git a/packages/react-native/scripts/codegen/generate-artifacts-executor/index.js b/packages/react-native/scripts/codegen/generate-artifacts-executor/index.js index 588c5d2b5fd327..4d41c5c5e88d8d 100644 --- a/packages/react-native/scripts/codegen/generate-artifacts-executor/index.js +++ b/packages/react-native/scripts/codegen/generate-artifacts-executor/index.js @@ -63,7 +63,7 @@ const path = require('path'); function execute( projectRoot /*: string */, targetPlatform /*: string */, - baseOutputPath /*: string */, + optionalBaseOutputPath /*: ?string */, source /*: string */, runReactNativeCodegen /*: boolean */ = true, ) { @@ -88,32 +88,35 @@ function execute( buildCodegenIfNeeded(); } - const reactNativeConfig = readReactNativeConfig( - projectRoot, - // NOTE: Used to load `build/generated/autolinking/autolinking.json` generated by `scripts/cocoapods/autolinking.rb` - // If we have RCT_SCRIPT_OUTPUT_DIR (set in `react_native_pods_utils/script_phases.sh`, it takes precedence, otherwise - // we search for the `autolinking.json` output in the `baseOutputPath` - process.env.RCT_SCRIPT_OUTPUT_DIR != null && - process.env.RCT_SCRIPT_OUTPUT_DIR.length > 0 - ? process.env.RCT_SCRIPT_OUTPUT_DIR - : baseOutputPath, - ); - - const codegenEnabledLibraries = findCodegenEnabledLibraries( - pkgJson, - projectRoot, - baseOutputPath, - reactNativeConfig, - ); - - if (codegenEnabledLibraries.length === 0) { - codegenLog('No codegen-enabled libraries found.', true); - } - - let platforms = + const platforms = targetPlatform === 'all' ? supportedPlatforms : [targetPlatform]; + // NOTE: We cache the external libraries search (which may not run) across platforms to not change previous behaviour + const externalLibrariesCache /*: { current?: ?Array<$FlowFixMe> } */ = {}; + for (const platform of platforms) { + // NOTE: This needs to be computed per-platform since `platform` can alter the path via a `package.json:codegenConfig.outputDir[platform]` override + const baseOutputPath = computeBaseOutputPath( + projectRoot, + optionalBaseOutputPath, + pkgJson, + platform, + ); + const reactNativeConfig = readReactNativeConfig( + projectRoot, + baseOutputPath, + ); + const codegenEnabledLibraries = findCodegenEnabledLibraries( + pkgJson, + projectRoot, + baseOutputPath, + reactNativeConfig, + externalLibrariesCache, + ); + if (codegenEnabledLibraries.length === 0) { + codegenLog('No codegen-enabled libraries found.', true); + } + const disabledLibraries = findDisabledLibrariesByPlatform( reactNativeConfig, platform, @@ -208,22 +211,38 @@ function readOutputDirFromPkgJson( return null; } -function computeOutputPath( +function computeBaseOutputPath( projectRoot /*: string */, - baseOutputPath /*: string */, + optionalBaseOutputPath /*: ?string */, pkgJson /*: $FlowFixMe */, platform /*: string */, ) { - if (baseOutputPath == null) { + if ( + process.env.RCT_SCRIPT_OUTPUT_DIR != null && + process.env.RCT_SCRIPT_OUTPUT_DIR.length > 0 + ) { + return process.env.RCT_SCRIPT_OUTPUT_DIR; + } + let baseOutputPath /*: string */; + if (optionalBaseOutputPath == null) { const outputDirFromPkgJson = readOutputDirFromPkgJson(pkgJson, platform); if (outputDirFromPkgJson != null) { - // $FlowFixMe[reassign-const] baseOutputPath = path.join(projectRoot, outputDirFromPkgJson); } else { - // $FlowFixMe[reassign-const] baseOutputPath = projectRoot; } + } else { + baseOutputPath = optionalBaseOutputPath; } + return baseOutputPath; +} + +function computeOutputPath( + projectRoot /*: string */, + baseOutputPath /*: string */, + pkgJson /*: $FlowFixMe */, + platform /*: string */, +) /*: string */ { if (pkgJsonIncludesGeneratedCode(pkgJson)) { // Don't create nested directories for libraries to make importing generated headers easier. return baseOutputPath; diff --git a/packages/react-native/scripts/codegen/generate-artifacts-executor/utils.js b/packages/react-native/scripts/codegen/generate-artifacts-executor/utils.js index 680f8a6d295dc2..6caeeae4ad3145 100644 --- a/packages/react-native/scripts/codegen/generate-artifacts-executor/utils.js +++ b/packages/react-native/scripts/codegen/generate-artifacts-executor/utils.js @@ -98,9 +98,11 @@ function cleanupEmptyFilesAndFolders(filepath /*: string */) { } function readGeneratedAutolinkingOutput( + projectRoot /*: string */, baseOutputPath /*: string */, ) /*: $FlowFixMe */ { // NOTE: Generated by scripts/cocoapods/autolinking.rb in list_native_modules (called by use_native_modules) + // The `baseOutputPath` is based on a CLI argument and optional const autolinkingGeneratedPath = path.resolve( baseOutputPath, 'build/generated/autolinking/autolinking.json', @@ -120,7 +122,10 @@ function readReactNativeConfig( projectRoot /*: string */, baseOutputPath /*: string */, ) /*: $FlowFixMe */ { - const autolinkingOutput = readGeneratedAutolinkingOutput(baseOutputPath); + const autolinkingOutput = readGeneratedAutolinkingOutput( + projectRoot, + baseOutputPath, + ); const rnConfigFilePath = path.resolve(projectRoot, 'react-native.config.js'); if (autolinkingOutput) { return autolinkingOutput; @@ -141,6 +146,7 @@ function findCodegenEnabledLibraries( projectRoot /*: string */, baseOutputPath /*: string */, reactNativeConfig /*: $FlowFixMe */, + externalLibrariesCache /*: { current?: ?Array<$FlowFixMe> } */ = {}, ) /*: Array<$FlowFixMe> */ { const projectLibraries = findProjectRootLibraries(pkgJson, projectRoot); if (pkgJsonIncludesGeneratedCode(pkgJson)) { @@ -149,8 +155,14 @@ function findCodegenEnabledLibraries( const libraries = [...projectLibraries]; // If we ran autolinking, we shouldn't try to run our own "autolinking-like" // library discovery - if (!readGeneratedAutolinkingOutput(baseOutputPath)) { - libraries.push(...findExternalLibraries(pkgJson, projectRoot)); + if (!readGeneratedAutolinkingOutput(projectRoot, baseOutputPath)) { + const externalLibraries = + externalLibrariesCache.current ?? + (externalLibrariesCache.current = findExternalLibraries( + pkgJson, + projectRoot, + )); + libraries.push(...externalLibraries); } libraries.push( ...findLibrariesFromReactNativeConfig(projectRoot, reactNativeConfig),