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 } 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 versionedReactNativeDir = path.join(androidDir, 'versioned-react-native'); 21 await Promise.all([ 22 fs.remove(path.join(versionedReactNativeDir, 'ReactAndroid')), 23 fs.remove(path.join(versionedReactNativeDir, 'ReactCommon')), 24 fs.remove(path.join(versionedReactNativeDir, 'codegen')), 25 fs.remove(path.join(versionedReactNativeDir, 'sdks')), 26 ]); 27 28 await fs.mkdirp(path.join(versionedReactNativeDir, 'sdks')); 29 await fs.copy( 30 path.join(REACT_NATIVE_SUBMODULE_DIR, 'sdks/.hermesversion'), 31 path.join(versionedReactNativeDir, 'sdks/.hermesversion') 32 ); 33 34 // Run and version codegen 35 const codegenOutputRoot = path.join(versionedReactNativeDir, 'codegen'); 36 const tmpCodegenOutputRoot = path.join(versionedReactNativeDir, 'codegen-tmp'); 37 try { 38 await runReactNativeCodegenAsync({ 39 reactNativeRoot: REACT_NATIVE_SUBMODULE_DIR, 40 codegenPkgRoot: path.join(REACT_NATIVE_SUBMODULE_DIR, 'packages', 'react-native-codegen'), 41 outputDir: tmpCodegenOutputRoot, 42 name: 'rncore', 43 platform: 'android', 44 type: 'all', 45 jsSrcsDir: path.join(REACT_NATIVE_SUBMODULE_DIR, 'Libraries'), 46 javaPackageName: 'com.facebook.fbreact.specs', 47 }); 48 await versionCodegenDirectoryAsync(tmpCodegenOutputRoot, codegenOutputRoot, abiVersion); 49 } finally { 50 await fs.remove(tmpCodegenOutputRoot); 51 } 52 53 // Copy and version ReactAndroid and ReactCommon 54 await versionReactNativeAsync(versionedReactNativeDir, abiVersion); 55 56 await versionHermesAsync(versionedReactNativeDir, abiVersion); 57} 58 59async function versionHermesAsync(versionedReactNativeDir: string, abiVersion: string) { 60 await spawnAsync('./gradlew', [':ReactAndroid:hermes-engine:unzipHermes'], { 61 shell: true, 62 cwd: versionedReactNativeDir, 63 stdio: 'inherit', 64 }); 65 await transformFileAsync( 66 path.join(versionedReactNativeDir, 'sdks/hermes/API/hermes/CMakeLists.txt'), 67 hermesTransforms(abiVersion) 68 ); 69} 70 71async function versionReactNativeAsync(versionedReactNativeDir: string, abiVersion: string) { 72 const files = await searchFilesAsync(REACT_NATIVE_SUBMODULE_DIR, [ 73 './ReactAndroid/**', 74 './ReactCommon/**', 75 ]); 76 for (const file of files) { 77 if ((file.match(/\/build\//) && !file.match(/src.*\/build\//)) || file.match(/\/\.cxx\//)) { 78 files.delete(file); 79 } 80 } 81 82 const transforms = reactNativeTransforms(versionedReactNativeDir, abiVersion); 83 for (const sourceFile of files) { 84 await copyFileWithTransformsAsync({ 85 sourceFile, 86 targetDirectory: versionedReactNativeDir, 87 sourceDirectory: REACT_NATIVE_SUBMODULE_DIR, 88 transforms, 89 }); 90 } 91} 92 93async function versionCodegenDirectoryAsync( 94 tmpCodegenDir: string, 95 codegenDir: string, 96 abiVersion: string 97) { 98 const files = await searchFilesAsync(tmpCodegenDir, ['**']); 99 const transforms = codegenTransforms(abiVersion); 100 for (const sourceFile of files) { 101 await copyFileWithTransformsAsync({ 102 sourceFile, 103 targetDirectory: codegenDir, 104 sourceDirectory: tmpCodegenDir, 105 transforms, 106 }); 107 } 108} 109