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