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