1import spawnAsync from '@expo/spawn-async'; 2import fs from 'fs-extra'; 3import path from 'path'; 4 5import { runReactNativeCodegenAsync } from '../../Codegen'; 6import { REACT_NATIVE_SUBMODULE_DIR, REACT_NATIVE_SUBMODULE_MONOREPO_ROOT } from '../../Constants'; 7import { copyFileWithTransformsAsync, transformFileAsync } from '../../Transforms'; 8import { searchFilesAsync } from '../../Utils'; 9import { 10 codegenTransforms, 11 hermesTransforms, 12 reactNativeTransforms, 13} from './reactNativeTransforms'; 14 15export async function updateVersionedReactNativeAsync( 16 androidDir: string, 17 sdkVersion: string 18): Promise<void> { 19 const abiVersion = `abi${sdkVersion.replace(/\./g, '_')}`; 20 const versionedReactNativeMonorepoRoot = path.join(androidDir, 'versioned-react-native'); 21 const versionedReactNativeRoot = path.join( 22 versionedReactNativeMonorepoRoot, 23 'packages/react-native' 24 ); 25 await Promise.all([fs.remove(path.join(versionedReactNativeMonorepoRoot, 'packages'))]); 26 27 await fs.mkdirp(path.join(versionedReactNativeRoot, 'sdks')); 28 await fs.copy( 29 path.join(REACT_NATIVE_SUBMODULE_DIR, 'sdks/.hermesversion'), 30 path.join(versionedReactNativeRoot, 'sdks/.hermesversion') 31 ); 32 33 // Run and version codegen 34 const codegenOutputRoot = path.join(versionedReactNativeRoot, 'codegen'); 35 const tmpCodegenOutputRoot = path.join(versionedReactNativeMonorepoRoot, 'codegen-tmp'); 36 try { 37 await runReactNativeCodegenAsync({ 38 reactNativeRoot: REACT_NATIVE_SUBMODULE_DIR, 39 codegenPkgRoot: path.join( 40 REACT_NATIVE_SUBMODULE_MONOREPO_ROOT, 41 'packages', 42 'react-native-codegen' 43 ), 44 outputDir: tmpCodegenOutputRoot, 45 name: 'rncore', 46 platform: 'android', 47 type: 'all', 48 jsSrcsDir: path.join(REACT_NATIVE_SUBMODULE_DIR, 'Libraries'), 49 javaPackageName: 'com.facebook.fbreact.specs', 50 }); 51 await versionCodegenDirectoryAsync(tmpCodegenOutputRoot, codegenOutputRoot, abiVersion); 52 } finally { 53 await fs.remove(tmpCodegenOutputRoot); 54 } 55 56 // Copy and version ReactAndroid and ReactCommon 57 await versionReactNativeAsync(versionedReactNativeRoot, abiVersion); 58 59 await versionHermesAsync(versionedReactNativeMonorepoRoot, abiVersion); 60} 61 62async function versionHermesAsync(versionedReactNativeMonorepoRoot: string, abiVersion: string) { 63 await spawnAsync('./gradlew', [':packages:react-native:ReactAndroid:hermes-engine:unzipHermes'], { 64 shell: true, 65 cwd: versionedReactNativeMonorepoRoot, 66 stdio: 'inherit', 67 }); 68 await transformFileAsync( 69 path.join( 70 versionedReactNativeMonorepoRoot, 71 'packages/react-native', 72 'sdks/hermes/API/hermes/CMakeLists.txt' 73 ), 74 hermesTransforms(abiVersion) 75 ); 76} 77 78async function versionReactNativeAsync(versionedReactNativeRoot: string, abiVersion: string) { 79 const files = await searchFilesAsync(REACT_NATIVE_SUBMODULE_DIR, [ 80 './ReactAndroid/**', 81 './ReactCommon/**', 82 ]); 83 for (const file of files) { 84 if ((file.match(/\/build\//) && !file.match(/src.*\/build\//)) || file.match(/\/\.cxx\//)) { 85 files.delete(file); 86 } 87 } 88 89 const transforms = reactNativeTransforms(versionedReactNativeRoot, abiVersion); 90 for (const sourceFile of files) { 91 await copyFileWithTransformsAsync({ 92 sourceFile, 93 targetDirectory: versionedReactNativeRoot, 94 sourceDirectory: REACT_NATIVE_SUBMODULE_DIR, 95 transforms, 96 }); 97 } 98} 99 100async function versionCodegenDirectoryAsync( 101 tmpCodegenDir: string, 102 codegenDir: string, 103 abiVersion: string 104) { 105 const files = await searchFilesAsync(tmpCodegenDir, ['**']); 106 const transforms = codegenTransforms(abiVersion); 107 for (const sourceFile of files) { 108 await copyFileWithTransformsAsync({ 109 sourceFile, 110 targetDirectory: codegenDir, 111 sourceDirectory: tmpCodegenDir, 112 transforms, 113 }); 114 } 115} 116