1class KotlinExpoModulesCorePlugin implements Plugin<Project> { 2 void apply(Project project) { 3 project.buildscript { 4 project.ext.kotlinVersion = { 5 project.rootProject.ext.has("kotlinVersion") 6 ? project.rootProject.ext.get("kotlinVersion") 7 : "1.8.10" 8 } 9 10 project.ext.kspVersion = { 11 def kspVersionsMap = [ 12 "1.6.10": "1.6.10-1.0.4", 13 "1.6.21": "1.6.21-1.0.6", 14 "1.7.22": "1.7.22-1.0.8", 15 "1.8.0": "1.8.0-1.0.9", 16 "1.8.10": "1.8.10-1.0.9" 17 ] 18 19 project.rootProject.ext.has("kspVersion") 20 ? project.rootProject.ext.get("kspVersion") 21 : kspVersionsMap.containsKey(project.ext.kotlinVersion()) 22 ? kspVersionsMap.get(project.ext.kotlinVersion()) 23 : "1.8.10-1.0.9" 24 } 25 } 26 } 27} 28 29ext.applyKotlinExpoModulesCorePlugin = { 30 apply plugin: KotlinExpoModulesCorePlugin 31} 32 33// [BEGIN] Remove when we drop SDK 47 34abstract class ExtractReactNativeAARTask extends DefaultTask { 35 @Input 36 abstract Property<String> getBuildType() 37 38 @Input 39 abstract Property<String> getReactNativeDir() 40 41 @TaskAction 42 def taskAction() { 43 def suffix = buildType.get() == 'Debug' ? '-debug' : '-release' 44 def rnAARs = project.fileTree("${reactNativeDir.get()}/android").matching { include "**/react-native/**/*${suffix}.aar" } 45 if (rnAARs.isEmpty()) { 46 rnAARs = project.fileTree("${reactNativeDir.get()}/android").matching { include "**/react-native/**/*.aar" } 47 } 48 if (rnAARs.any()) { 49 // node_modules/react-native has a .aar, extract headers 50 if (rnAARs.size() > 1) { 51 logger.error("More than one React Native AAR file has been found:") 52 rnAARs.each {println(it) } 53 throw new GradleException("Multiple React Native AARs found:\n${rnAARs.join("\n")}" + 54 "\nRemove the old ones and try again") 55 } 56 } 57 def rnAAR = rnAARs.singleFile 58 def file = rnAAR.absoluteFile 59 def packageName = file.name.tokenize('-')[0] 60 project.copy { 61 from project.zipTree(file) 62 into "${project.buildDir}/${packageName}" 63 include "jni/**/*" 64 } 65 } 66} 67 68class LegacyReactNativeLibsExtractionPlugin implements Plugin<Project> { 69 void nativeBuildDependsOn(project, dependsOnTask, buildTypesIncludes) { 70 def buildTasks = project.tasks.findAll { task -> 71 def taskName = task.name 72 if (taskName.contains("Clean")) { return false } 73 if (taskName.contains("externalNative") || taskName.contains("CMake") || taskName.contains("generateJsonModel")) { 74 if (buildTypesIncludes == null) { return true } 75 for (buildType in buildTypesIncludes) { 76 if (taskName.contains(buildType)) { return true } 77 } 78 } 79 return false 80 } 81 buildTasks.forEach { task -> task.dependsOn(dependsOnTask) } 82 } 83 84 void apply(Project project) { 85 def REACT_NATIVE_BUILD_FROM_SOURCE = project.findProject(":ReactAndroid") != null 86 def REACT_NATIVE_DIR = REACT_NATIVE_BUILD_FROM_SOURCE 87 ? project.findProject(":ReactAndroid").getProjectDir().parent 88 : new File(["node", "--print", "require.resolve('react-native/package.json')"].execute(null, project.rootDir).text.trim()).parent 89 90 def reactProperties = new Properties() 91 new File("$REACT_NATIVE_DIR/ReactAndroid/gradle.properties").withInputStream { reactProperties.load(it) } 92 def FOLLY_VERSION = reactProperties.getProperty("FOLLY_VERSION") 93 def DOUBLE_CONVERSION_VERSION = reactProperties.getProperty("DOUBLE_CONVERSION_VERSION") 94 def REACT_NATIVE_VERSION = System.getenv("REACT_NATIVE_OVERRIDE_VERSION") ?: reactProperties.getProperty("VERSION_NAME") 95 def REACT_NATIVE_TARGET_VERSION = REACT_NATIVE_VERSION.split("\\.")[1].toInteger() 96 97 def isNewArchitectureEnabled = project.findProperty("newArchEnabled") == "true" 98 def customDownloadsDir = System.getenv("REACT_NATIVE_DOWNLOADS_DIR") 99 def downloadsDir = customDownloadsDir ? new File(customDownloadsDir) : new File("${project.buildDir}/downloads") 100 def thirdPartyNdkDir = new File("${project.buildDir}/third-party-ndk") 101 def reactNativeThirdParty = new File("$REACT_NATIVE_DIR/ReactAndroid/src/main/jni/third-party") 102 103 def createNativeDepsDirectories = project.tasks.findByName('createNativeDepsDirectories') ?: project.tasks.register('createNativeDepsDirectories') { 104 downloadsDir.mkdirs() 105 thirdPartyNdkDir.mkdirs() 106 } 107 108 def extractReactNativeAARRelease = project.tasks.register('extractReactNativeAARRelease', ExtractReactNativeAARTask) { 109 reactNativeDir = REACT_NATIVE_DIR 110 buildType = 'Release' 111 } 112 def extractReactNativeAARDebug = project.tasks.register('extractReactNativeAARDebug', ExtractReactNativeAARTask) { 113 reactNativeDir = REACT_NATIVE_DIR 114 buildType = 'Debug' 115 } 116 117 def packageReactNdkDebugLibs = project.tasks.register("packageReactNdkDebugLibs", Copy) { 118 dependsOn(":ReactAndroid:packageReactNdkDebugLibsForBuck") 119 from("$REACT_NATIVE_DIR/ReactAndroid/src/main/jni/prebuilt/lib") 120 into("${project.buildDir}/react-ndk/exported") 121 } 122 def packageReactNdkReleaseLibs = project.tasks.register("packageReactNdkReleaseLibs", Copy) { 123 dependsOn(":ReactAndroid:packageReactNdkReleaseLibsForBuck") 124 from("$REACT_NATIVE_DIR/ReactAndroid/src/main/jni/prebuilt/lib") 125 into("${project.buildDir}/react-ndk/exported") 126 } 127 128 // [BEGIN] Extra libs 129 def downloadDoubleConversion = project.tasks.create('downloadDoubleConversion', project.Download) { 130 dependsOn(createNativeDepsDirectories) 131 src("https://github.com/google/double-conversion/archive/v${DOUBLE_CONVERSION_VERSION}.tar.gz") 132 onlyIfNewer(true) 133 overwrite(false) 134 dest(new File(downloadsDir, "double-conversion-${DOUBLE_CONVERSION_VERSION}.tar.gz")) 135 } 136 137 def prepareDoubleConversion = project.tasks.register('prepareDoubleConversion', Copy) { 138 dependsOn(downloadDoubleConversion) 139 from(project.tarTree(downloadDoubleConversion.dest)) 140 from("$reactNativeThirdParty/double-conversion/Android.mk") 141 include("double-conversion-${DOUBLE_CONVERSION_VERSION}/src/**/*", "Android.mk") 142 filesMatching("*/src/**/*", { fname -> fname.path = "double-conversion/${fname.name}" }) 143 includeEmptyDirs = false 144 into("$thirdPartyNdkDir/double-conversion") 145 } 146 147 def downloadFolly = project.tasks.create('downloadFolly', project.Download) { 148 dependsOn(createNativeDepsDirectories) 149 src("https://github.com/facebook/folly/archive/v${FOLLY_VERSION}.tar.gz") 150 onlyIfNewer(true) 151 overwrite(false) 152 dest(new File(downloadsDir, "folly-${FOLLY_VERSION}.tar.gz")) 153 } 154 155 def prepareFolly = project.tasks.register('prepareFolly', Copy) { 156 dependsOn(downloadFolly) 157 from(project.tarTree(downloadFolly.dest)) 158 from("$reactNativeThirdParty/folly/Android.mk") 159 include("folly-${FOLLY_VERSION}/folly/**/*", "Android.mk") 160 eachFile { fname -> fname.path = (fname.path - "folly-${FOLLY_VERSION}/") } 161 // Fixes problem with Folly failing to build on certain systems. See 162 // https://github.com/software-mansion/react-native-reanimated/issues/1024 163 def follyReplaceContent = ''' 164 ssize_t r; 165 do { 166 r = open(name, flags, mode); 167 } while (r == -1 && errno == EINTR); 168 return r; 169 ''' 170 filter { line -> line.replaceAll("return int\\(wrapNoInt\\(open, name, flags, mode\\)\\);", follyReplaceContent) } 171 includeEmptyDirs = false 172 into("$thirdPartyNdkDir/folly") 173 } 174 // [END] Extra libs 175 176 project.afterEvaluate { 177 if (REACT_NATIVE_BUILD_FROM_SOURCE) { 178 nativeBuildDependsOn(project, ":ReactAndroid:copyReleaseJniLibsProjectOnly", ["Release", "RelWithDebInfo"]) 179 nativeBuildDependsOn(project, ":ReactAndroid:copyDebugJniLibsProjectOnly", ["Debug"]) 180 } else { 181 nativeBuildDependsOn(project, extractReactNativeAARRelease, ["Release", "RelWithDebInfo"]) 182 nativeBuildDependsOn(project, extractReactNativeAARDebug, ["Debug"]) 183 } 184 185 def extraLibs = project.extensions.extraProperties.has('extraLegacyReactNativeLibs') 186 ? project.extensions.extraProperties.get('extraLegacyReactNativeLibs') 187 : [] 188 extraLibs.each { 189 nativeBuildDependsOn(project, project.tasks.named(it), null) 190 } 191 192 if (isNewArchitectureEnabled) { 193 def preDebugBuild = project.tasks.named('preDebugBuild') 194 def preReleaseBuild = project.tasks.named('preReleaseBuild') 195 preDebugBuild.configure { 196 dependsOn(packageReactNdkDebugLibs) 197 } 198 preReleaseBuild.configure { 199 dependsOn(packageReactNdkReleaseLibs) 200 } 201 202 // Due to a bug inside AGP, we have to explicitly set a dependency 203 // between configureCMake* tasks and the preBuild tasks. 204 // This can be removed once this is solved: https://issuetracker.google.com/issues/207403732 205 project.tasks.named('configureCMakeDebug').configure { 206 dependsOn(preDebugBuild) 207 } 208 project.tasks.named('configureCMakeRelWithDebInfo').configure { 209 dependsOn(preReleaseBuild) 210 } 211 def reactNativeArchitectures = project.getProperties().get("reactNativeArchitectures")?.split(",") ?: ["armeabi-v7a", "x86", "x86_64", "arm64-v8a"] 212 213 reactNativeArchitectures.each { architecture -> 214 project.tasks.named("configureCMakeDebug[${architecture}]")?.configure { 215 dependsOn("preDebugBuild") 216 } 217 project.tasks.named("configureCMakeRelWithDebInfo[${architecture}]")?.configure { 218 dependsOn("preReleaseBuild") 219 } 220 } 221 } 222 } 223 } 224} 225 226ext.applyLegacyReactNativeLibsExtractionPlugin = { 227 apply plugin: LegacyReactNativeLibsExtractionPlugin 228} 229 230// [END] Remove when we drop SDK 47 231