@callstack/react-native-brownfield 3.11.0 → 3.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +26 -0
- package/gradle-plugin/brownfield/build.gradle.kts +134 -0
- package/gradle-plugin/brownfield/config/detekt/detekt.yml +936 -0
- package/gradle-plugin/brownfield/gradle/libs.versions.toml +19 -0
- package/gradle-plugin/brownfield/gradle/wrapper/gradle-wrapper.jar +0 -0
- package/gradle-plugin/brownfield/gradle/wrapper/gradle-wrapper.properties +7 -0
- package/gradle-plugin/brownfield/gradle.properties +14 -0
- package/gradle-plugin/brownfield/gradlew +249 -0
- package/gradle-plugin/brownfield/gradlew.bat +92 -0
- package/gradle-plugin/brownfield/settings.gradle +7 -0
- package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/artifacts/ArtifactsResolver.kt +132 -0
- package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/exceptions/NameSpaceNotFound.kt +4 -0
- package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/exceptions/TaskNotFound.kt +4 -0
- package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/expo/ExpoPublishingHelper.kt +432 -0
- package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/expo/utils/BrownfieldPrimitives.kt +31 -0
- package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/expo/utils/ExpoProjectionPrimitives.kt +22 -0
- package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/expo/utils/LocalMavenUtils.kt +83 -0
- package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/expo/utils/ReflectionUtils.kt +79 -0
- package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/expo/utils/VersionMediatingDependencySet.kt +100 -0
- package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/CustomDependencyResolver.kt +50 -0
- package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/ProjectConfigurations.kt +107 -0
- package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/RClassTransformer.kt +131 -0
- package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/RNBrownfieldPlugin.kt +171 -0
- package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/RNSourceSets.kt +149 -0
- package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/AssetTaskProcessor.kt +29 -0
- package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/ExplodeTaskProvider.kt +63 -0
- package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/JNILibsProcessor.kt +165 -0
- package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/ManifestTaskProcessor.kt +74 -0
- package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/MergeProcessor.kt +55 -0
- package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/ProguardProcessor.kt +61 -0
- package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/ResourceTaskProcessor.kt +26 -0
- package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/VariantHelper.kt +61 -0
- package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/VariantPackagesProperty.kt +21 -0
- package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/VariantTaskProvider.kt +103 -0
- package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/BaseProject.kt +17 -0
- package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/BundleTaskProvider.kt +46 -0
- package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/Constants.kt +58 -0
- package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/ExplodeAarTask.kt +72 -0
- package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/GradleILogger.kt +59 -0
- package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/Logging.kt +24 -0
- package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/ModuleInfo.kt +22 -0
- package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/utils/AndroidArchiveLibrary.kt +77 -0
- package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/utils/DirectoryManager.kt +20 -0
- package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/utils/Extension.kt +44 -0
- package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/utils/StringExtensions.kt +5 -0
- package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/utils/StringMatcher.kt +21 -0
- package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/utils/Utils.kt +59 -0
- package/ios/Expo/ExpoHostRuntime.swift +3 -2
- package/ios/ReactNativeBrownfield.swift +1 -1
- package/ios/Vanilla/ReactNativeHostRuntime.swift +5 -2
- package/ios/swiftpm/Sources/BrownfieldBundleSupport/BrownfieldBundleURLResolver.swift +11 -5
- package/ios/swiftpm/Tests/BrownfieldBundleSupportTests/BrownfieldBundleURLResolverTests.swift +17 -5
- package/lib/commonjs/expo-config-plugin/android/utils/constants.js +1 -1
- package/lib/commonjs/expo-config-plugin/android/utils/constants.js.map +1 -1
- package/lib/commonjs/expo-config-plugin/ios/xcodeHelpers.js +2 -1
- package/lib/commonjs/expo-config-plugin/ios/xcodeHelpers.js.map +1 -1
- package/lib/commonjs/index.js.map +1 -1
- package/lib/module/expo-config-plugin/android/utils/constants.js +1 -1
- package/lib/module/expo-config-plugin/android/utils/constants.js.map +1 -1
- package/lib/module/expo-config-plugin/ios/xcodeHelpers.js +2 -1
- package/lib/module/expo-config-plugin/ios/xcodeHelpers.js.map +1 -1
- package/lib/module/index.js.map +1 -1
- package/lib/typescript/commonjs/src/expo-config-plugin/android/utils/constants.d.ts +2 -2
- package/lib/typescript/commonjs/src/expo-config-plugin/android/utils/constants.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/expo-config-plugin/ios/xcodeHelpers.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/index.d.ts +1 -0
- package/lib/typescript/commonjs/src/index.d.ts.map +1 -1
- package/lib/typescript/module/src/expo-config-plugin/android/utils/constants.d.ts +2 -2
- package/lib/typescript/module/src/expo-config-plugin/android/utils/constants.d.ts.map +1 -1
- package/lib/typescript/module/src/expo-config-plugin/ios/xcodeHelpers.d.ts.map +1 -1
- package/lib/typescript/module/src/index.d.ts +1 -0
- package/lib/typescript/module/src/index.d.ts.map +1 -1
- package/package.json +6 -4
- package/scripts/sync-gradle-plugin-source.js +58 -0
- package/src/expo-config-plugin/android/utils/constants.ts +1 -1
- package/src/expo-config-plugin/ios/xcodeHelpers.ts +14 -0
- package/src/index.ts +2 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
package com.callstack.react.brownfield.processors
|
|
2
|
+
|
|
3
|
+
import org.gradle.api.Project
|
|
4
|
+
import org.gradle.api.provider.MapProperty
|
|
5
|
+
|
|
6
|
+
object VariantPackagesProperty {
|
|
7
|
+
private lateinit var properties: MapProperty<String, List<String>>
|
|
8
|
+
|
|
9
|
+
fun getVariantPackagesProperty(): MapProperty<String, List<String>> {
|
|
10
|
+
return properties
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
fun setVariantPackagesProperty(project: Project) {
|
|
14
|
+
@Suppress("UNCHECKED_CAST")
|
|
15
|
+
properties =
|
|
16
|
+
project.objects.mapProperty(
|
|
17
|
+
String::class.java,
|
|
18
|
+
List::class.java as Class<List<String>>,
|
|
19
|
+
)
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
package com.callstack.react.brownfield.processors
|
|
2
|
+
|
|
3
|
+
import com.android.build.gradle.internal.tasks.factory.dependsOn
|
|
4
|
+
import com.callstack.react.brownfield.exceptions.TaskNotFound
|
|
5
|
+
import com.callstack.react.brownfield.shared.ExplodeAarTask
|
|
6
|
+
import com.callstack.react.brownfield.utils.AndroidArchiveLibrary
|
|
7
|
+
import com.callstack.react.brownfield.utils.DirectoryManager
|
|
8
|
+
import com.callstack.react.brownfield.utils.Extension
|
|
9
|
+
import com.callstack.react.brownfield.utils.Utils
|
|
10
|
+
import com.callstack.react.brownfield.utils.capitalized
|
|
11
|
+
import org.gradle.api.Project
|
|
12
|
+
import org.gradle.api.Task
|
|
13
|
+
import org.gradle.api.UnknownTaskException
|
|
14
|
+
import org.gradle.api.tasks.TaskProvider
|
|
15
|
+
import java.io.File
|
|
16
|
+
|
|
17
|
+
class VariantTaskProvider(val project: Project) {
|
|
18
|
+
fun bundleTaskProvider(
|
|
19
|
+
project: Project,
|
|
20
|
+
variantName: String,
|
|
21
|
+
): TaskProvider<Task> {
|
|
22
|
+
var bundleTaskPath = "bundle${variantName.capitalized()}"
|
|
23
|
+
return try {
|
|
24
|
+
project.tasks.named(bundleTaskPath)
|
|
25
|
+
} catch (_: UnknownTaskException) {
|
|
26
|
+
bundleTaskPath += "Aar"
|
|
27
|
+
project.tasks.named(bundleTaskPath)
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
fun processDataBinding(
|
|
32
|
+
bundleTask: TaskProvider<Task>,
|
|
33
|
+
aarLibraries: Collection<AndroidArchiveLibrary>,
|
|
34
|
+
variantName: String,
|
|
35
|
+
) {
|
|
36
|
+
bundleTask.configure { task ->
|
|
37
|
+
task.doLast {
|
|
38
|
+
aarLibraries.forEach {
|
|
39
|
+
val dataBindingFolder = it.getDataBindingFolder()
|
|
40
|
+
if (dataBindingFolder.exists()) {
|
|
41
|
+
val filePath = getReBundleFilePath(dataBindingFolder.name, variantName)
|
|
42
|
+
File(filePath).mkdirs()
|
|
43
|
+
project.copy { copyTask ->
|
|
44
|
+
copyTask.from(dataBindingFolder)
|
|
45
|
+
copyTask.into(filePath)
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
val dataBindingLogFolder = it.getDataBindingLogFolder()
|
|
50
|
+
if (dataBindingLogFolder.exists()) {
|
|
51
|
+
val filePath = getReBundleFilePath(dataBindingLogFolder.name, variantName)
|
|
52
|
+
File(filePath).mkdirs()
|
|
53
|
+
project.copy { copyTask ->
|
|
54
|
+
copyTask.from(dataBindingLogFolder)
|
|
55
|
+
copyTask.into(filePath)
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
private fun getReBundleFilePath(
|
|
64
|
+
folderName: String,
|
|
65
|
+
variantName: String,
|
|
66
|
+
) = "${DirectoryManager.getReBundleDirectory(
|
|
67
|
+
variantName,
|
|
68
|
+
).path}/$folderName"
|
|
69
|
+
|
|
70
|
+
fun preBuildTaskByVariant(
|
|
71
|
+
variantName: String,
|
|
72
|
+
buildTypeName: String,
|
|
73
|
+
isVariantDebuggable: Boolean,
|
|
74
|
+
explodeAarTask: TaskProvider<ExplodeAarTask>,
|
|
75
|
+
) {
|
|
76
|
+
val preBuildTaskPath = "pre${variantName.capitalized()}Build"
|
|
77
|
+
val preBuildTask = project.tasks.named(preBuildTaskPath)
|
|
78
|
+
|
|
79
|
+
if (!preBuildTask.isPresent) {
|
|
80
|
+
throw TaskNotFound("Can not find $preBuildTaskPath task")
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
preBuildTask.dependsOn(explodeAarTask)
|
|
84
|
+
|
|
85
|
+
val bundledAssetsVariantName =
|
|
86
|
+
Utils.getBundledAssetsVariantName(
|
|
87
|
+
variantName = variantName,
|
|
88
|
+
buildTypeName = buildTypeName,
|
|
89
|
+
isDebuggable = isVariantDebuggable,
|
|
90
|
+
)
|
|
91
|
+
val capitalizedBundledAssetsVariantName = bundledAssetsVariantName.capitalized()
|
|
92
|
+
|
|
93
|
+
val projectExt = project.extensions.getByType(Extension::class.java)
|
|
94
|
+
val appProject = project.rootProject.project(projectExt.appProjectName)
|
|
95
|
+
preBuildTask.dependsOn("${appProject.path}:createBundle${capitalizedBundledAssetsVariantName}JsAndAssets")
|
|
96
|
+
|
|
97
|
+
if (Utils.isExpoProject(project)) {
|
|
98
|
+
preBuildTask.dependsOn(
|
|
99
|
+
"${appProject.path}:create${capitalizedBundledAssetsVariantName}UpdatesResources",
|
|
100
|
+
)
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
package com.callstack.react.brownfield.shared
|
|
2
|
+
|
|
3
|
+
import org.gradle.api.Project
|
|
4
|
+
import org.gradle.api.file.Directory
|
|
5
|
+
|
|
6
|
+
open class BaseProject {
|
|
7
|
+
private var _project: Project? = null
|
|
8
|
+
|
|
9
|
+
var project: Project
|
|
10
|
+
get() = checkNotNull(_project) { "Project has not been initialized" }
|
|
11
|
+
set(value) {
|
|
12
|
+
_project = value
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
val buildDir: Directory
|
|
16
|
+
get() = project.layout.buildDirectory.get()
|
|
17
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
@file:Suppress("DEPRECATION")
|
|
2
|
+
|
|
3
|
+
package com.callstack.react.brownfield.shared
|
|
4
|
+
|
|
5
|
+
import com.android.build.gradle.LibraryExtension
|
|
6
|
+
import com.android.build.gradle.api.LibraryVariant
|
|
7
|
+
import com.callstack.react.brownfield.processors.VariantTaskProvider
|
|
8
|
+
import org.gradle.api.Project
|
|
9
|
+
import org.gradle.api.Task
|
|
10
|
+
import org.gradle.api.tasks.TaskProvider
|
|
11
|
+
|
|
12
|
+
class BundleTaskProvider(private val variantTaskProvider: VariantTaskProvider) {
|
|
13
|
+
fun getBundleTask(
|
|
14
|
+
project: Project,
|
|
15
|
+
variant: LibraryVariant,
|
|
16
|
+
): TaskProvider<Task>? {
|
|
17
|
+
val androidExtension = project.extensions.getByType(LibraryExtension::class.java)
|
|
18
|
+
|
|
19
|
+
// Find the first variant in the library that matches our criteria
|
|
20
|
+
val matchedVariant =
|
|
21
|
+
androidExtension.libraryVariants.find { libraryVariant ->
|
|
22
|
+
// 1. Try Simple Match
|
|
23
|
+
if (libraryVariant.name == variant.name || libraryVariant.name == variant.buildType.name) {
|
|
24
|
+
return@find true
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// 2. Try Dimension Strategy Match
|
|
28
|
+
val flavor = variant.productFlavors.firstOrNull() ?: variant.mergedFlavor
|
|
29
|
+
val strategies =
|
|
30
|
+
runCatching {
|
|
31
|
+
androidExtension.productFlavors.getByName(flavor.name).missingDimensionStrategies
|
|
32
|
+
}.getOrNull() ?: return@find false
|
|
33
|
+
|
|
34
|
+
strategies.any { (dimension, strategy) ->
|
|
35
|
+
val fallbacks = listOf(strategy.requested) + strategy.fallbacks
|
|
36
|
+
val libFlavor = libraryVariant.productFlavors.firstOrNull() ?: libraryVariant.mergedFlavor
|
|
37
|
+
|
|
38
|
+
dimension == libFlavor.dimension &&
|
|
39
|
+
fallbacks.contains(libFlavor.name) &&
|
|
40
|
+
variant.buildType.name == libraryVariant.buildType.name
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return matchedVariant?.let { variantTaskProvider.bundleTaskProvider(project, it.name) }
|
|
45
|
+
}
|
|
46
|
+
}
|
package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/Constants.kt
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
package com.callstack.react.brownfield.shared
|
|
2
|
+
|
|
3
|
+
import com.callstack.react.brownfield.expo.utils.DependencyInfo
|
|
4
|
+
import com.callstack.react.brownfield.utils.StringMatcher
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* A condition that checks if a certain Expo version meets specific criteria
|
|
8
|
+
* and returns a set of DependencyInfo objects if applicable.
|
|
9
|
+
*/
|
|
10
|
+
fun interface ExpoVersionConditionalDepSet {
|
|
11
|
+
/**
|
|
12
|
+
* Gets the dependency set if it is applicable for the given Expo version.
|
|
13
|
+
* @param expoVersion The Expo version to check.
|
|
14
|
+
* @return A set of DependencyInfo objects if the condition is met; otherwise, null.
|
|
15
|
+
*/
|
|
16
|
+
fun getIfApplicable(expoVersion: String): Set<DependencyInfo>?
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
data class ArtifactMatcher(
|
|
20
|
+
val groupId: StringMatcher? = null,
|
|
21
|
+
val artifactId: StringMatcher? = null,
|
|
22
|
+
) {
|
|
23
|
+
fun matches(
|
|
24
|
+
groupId: String,
|
|
25
|
+
artifactId: String,
|
|
26
|
+
): Boolean {
|
|
27
|
+
val groupMatches = groupIdMatcher()?.matches(groupId) ?: true
|
|
28
|
+
val artifactMatches = artifactIdMatcher()?.matches(artifactId) ?: true
|
|
29
|
+
return groupMatches && artifactMatches
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
private fun groupIdMatcher(): StringMatcher? = groupId
|
|
33
|
+
|
|
34
|
+
private fun artifactIdMatcher(): StringMatcher? = artifactId
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
object Constants {
|
|
38
|
+
const val PROJECT_ID = "com.callstack.react.brownfield"
|
|
39
|
+
const val PLUGIN_NAME = "react-brownfield"
|
|
40
|
+
|
|
41
|
+
const val RE_BUNDLE_FOLDER = "aar_rebundle"
|
|
42
|
+
const val INTERMEDIATES_TEMP_DIR = PLUGIN_NAME
|
|
43
|
+
|
|
44
|
+
val BROWNFIELD_EXPO_TRANSITIVE_DEPS_WHITELISTED_MODULES_FOR_DISCOVERY =
|
|
45
|
+
setOf("expo-modules-core", "expo-constants", "expo", "expo-updates")
|
|
46
|
+
val BROWNFIELD_EXPO_TRANSITIVE_DEPS_ARTIFACTS_BLACKLIST =
|
|
47
|
+
setOf(
|
|
48
|
+
// below: groupIds of Expo components in node_modules
|
|
49
|
+
ArtifactMatcher(groupId = StringMatcher.literal("host.exp.exponent")),
|
|
50
|
+
ArtifactMatcher(groupId = StringMatcher.literal("BareExpo")),
|
|
51
|
+
ArtifactMatcher(groupId = StringMatcher.regex("expo.*")),
|
|
52
|
+
// below: a broken transitive dependency that has no version specified and thus breaks the build
|
|
53
|
+
ArtifactMatcher(
|
|
54
|
+
groupId = StringMatcher.literal("org.jetbrains.kotlin"),
|
|
55
|
+
artifactId = StringMatcher.literal("kotlin-build-tools-impl"),
|
|
56
|
+
),
|
|
57
|
+
)
|
|
58
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
package com.callstack.react.brownfield.shared
|
|
2
|
+
|
|
3
|
+
import com.callstack.react.brownfield.processors.VariantHelper
|
|
4
|
+
import com.callstack.react.brownfield.utils.AndroidArchiveLibrary
|
|
5
|
+
import com.callstack.react.brownfield.utils.DirectoryManager
|
|
6
|
+
import org.gradle.api.DefaultTask
|
|
7
|
+
import org.gradle.api.provider.ListProperty
|
|
8
|
+
import org.gradle.api.provider.Property
|
|
9
|
+
import org.gradle.api.tasks.Input
|
|
10
|
+
import org.gradle.api.tasks.Internal
|
|
11
|
+
import org.gradle.api.tasks.TaskAction
|
|
12
|
+
|
|
13
|
+
abstract class ExplodeAarTask : DefaultTask() {
|
|
14
|
+
@get:Internal
|
|
15
|
+
abstract val inputArtifacts: ListProperty<UnresolvedArtifactInfo>
|
|
16
|
+
|
|
17
|
+
@get:Input
|
|
18
|
+
abstract val variantName: Property<String>
|
|
19
|
+
|
|
20
|
+
@get:Input
|
|
21
|
+
abstract val minifyEnabled: Property<Boolean>
|
|
22
|
+
|
|
23
|
+
@TaskAction
|
|
24
|
+
fun run() {
|
|
25
|
+
val artifacts = inputArtifacts.get()
|
|
26
|
+
val resolvedVariantName = variantName.get()
|
|
27
|
+
|
|
28
|
+
val variantHelper = VariantHelper()
|
|
29
|
+
variantHelper.project = project
|
|
30
|
+
|
|
31
|
+
// classes-merge
|
|
32
|
+
variantHelper.classesMergeTaskDoFirst(
|
|
33
|
+
DirectoryManager.getMergeClassDirectory(
|
|
34
|
+
resolvedVariantName,
|
|
35
|
+
),
|
|
36
|
+
resolvedVariantName,
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
val aarLibraries = mutableListOf<AndroidArchiveLibrary>()
|
|
40
|
+
artifacts.forEach { art ->
|
|
41
|
+
val artifactFile =
|
|
42
|
+
requireNotNull(art.file) {
|
|
43
|
+
"Missing AAR file for artifact ${art.moduleGroup}:${art.moduleName}:${art.moduleVersion} " +
|
|
44
|
+
"while exploding variant $resolvedVariantName. Ensure the artifact is resolved " +
|
|
45
|
+
"or the dependency is configured to produce an AAR before running this task."
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
val archiveLibrary =
|
|
49
|
+
AndroidArchiveLibrary(
|
|
50
|
+
this.project,
|
|
51
|
+
art,
|
|
52
|
+
resolvedVariantName,
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
aarLibraries.add(archiveLibrary)
|
|
56
|
+
|
|
57
|
+
// explode-aar
|
|
58
|
+
val zipFolder = archiveLibrary.getExplodedAarRootDir()
|
|
59
|
+
zipFolder.mkdirs()
|
|
60
|
+
|
|
61
|
+
project.copy {
|
|
62
|
+
zipFolder.deleteRecursively()
|
|
63
|
+
it.from(project.zipTree(artifactFile))
|
|
64
|
+
it.into(zipFolder)
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// classes-merge
|
|
69
|
+
val mergeClassesOutputDir = DirectoryManager.getMergeClassDirectory(resolvedVariantName)
|
|
70
|
+
variantHelper.classesMergeTaskDoLast(mergeClassesOutputDir, aarLibraries, mutableListOf(), resolvedVariantName, minifyEnabled.get())
|
|
71
|
+
}
|
|
72
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
package com.callstack.react.brownfield.shared
|
|
2
|
+
|
|
3
|
+
import com.android.utils.ILogger
|
|
4
|
+
import org.gradle.api.logging.Logger
|
|
5
|
+
import java.util.IllegalFormatException
|
|
6
|
+
|
|
7
|
+
class GradleILogger(
|
|
8
|
+
private val logger: Logger,
|
|
9
|
+
) : ILogger {
|
|
10
|
+
override fun error(
|
|
11
|
+
throwable: Throwable?,
|
|
12
|
+
msgFormat: String?,
|
|
13
|
+
vararg args: Any?,
|
|
14
|
+
) {
|
|
15
|
+
val message = formatMessage(msgFormat, args)
|
|
16
|
+
logger.error(message, throwable)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
override fun warning(
|
|
20
|
+
msgFormat: String?,
|
|
21
|
+
vararg args: Any?,
|
|
22
|
+
) {
|
|
23
|
+
logger.warn(formatMessage(msgFormat, args))
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
override fun info(
|
|
27
|
+
msgFormat: String?,
|
|
28
|
+
vararg args: Any?,
|
|
29
|
+
) {
|
|
30
|
+
logger.info(formatMessage(msgFormat, args))
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
override fun verbose(
|
|
34
|
+
msgFormat: String?,
|
|
35
|
+
vararg args: Any?,
|
|
36
|
+
) {
|
|
37
|
+
logger.debug(formatMessage(msgFormat, args))
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
@Suppress("SpreadOperator") // Required for Java vararg interop with String.format.
|
|
41
|
+
private fun formatMessage(
|
|
42
|
+
msgFormat: String?,
|
|
43
|
+
args: Array<out Any?>,
|
|
44
|
+
): String {
|
|
45
|
+
if (msgFormat == null) {
|
|
46
|
+
return ""
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return try {
|
|
50
|
+
if (args.isEmpty()) {
|
|
51
|
+
msgFormat
|
|
52
|
+
} else {
|
|
53
|
+
String.format(msgFormat, *args)
|
|
54
|
+
}
|
|
55
|
+
} catch (_: IllegalFormatException) {
|
|
56
|
+
msgFormat
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/Logging.kt
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
package com.callstack.react.brownfield.shared
|
|
2
|
+
|
|
3
|
+
import com.callstack.react.brownfield.shared.Constants.PLUGIN_NAME
|
|
4
|
+
|
|
5
|
+
object Logging : BaseProject() {
|
|
6
|
+
fun error(
|
|
7
|
+
message: Any,
|
|
8
|
+
error: Throwable,
|
|
9
|
+
) {
|
|
10
|
+
project.logger.error(getFormattedMessage(message), error)
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
fun info(message: Any) {
|
|
14
|
+
project.logger.info(getFormattedMessage(message))
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
fun log(message: Any) {
|
|
18
|
+
println(getFormattedMessage(message))
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
private fun getFormattedMessage(message: Any): String {
|
|
22
|
+
return " $PLUGIN_NAME :: $message"
|
|
23
|
+
}
|
|
24
|
+
}
|
package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/ModuleInfo.kt
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
package com.callstack.react.brownfield.shared
|
|
2
|
+
|
|
3
|
+
interface ModuleInfo {
|
|
4
|
+
val moduleGroup: String
|
|
5
|
+
val moduleName: String
|
|
6
|
+
val moduleVersion: String
|
|
7
|
+
|
|
8
|
+
val file: String?
|
|
9
|
+
|
|
10
|
+
val type: String
|
|
11
|
+
get() = "aar"
|
|
12
|
+
|
|
13
|
+
val isExpoPublishDependency: Boolean?
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
data class UnresolvedArtifactInfo(
|
|
17
|
+
override val moduleGroup: String,
|
|
18
|
+
override val moduleName: String,
|
|
19
|
+
override val moduleVersion: String,
|
|
20
|
+
override val file: String?,
|
|
21
|
+
override val isExpoPublishDependency: Boolean?,
|
|
22
|
+
) : ModuleInfo
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
package com.callstack.react.brownfield.utils
|
|
2
|
+
|
|
3
|
+
import com.callstack.react.brownfield.shared.UnresolvedArtifactInfo
|
|
4
|
+
import org.gradle.api.Project
|
|
5
|
+
import java.io.File
|
|
6
|
+
|
|
7
|
+
class AndroidArchiveLibrary(
|
|
8
|
+
private val project: Project,
|
|
9
|
+
artifact: UnresolvedArtifactInfo,
|
|
10
|
+
private val variantName: String,
|
|
11
|
+
) {
|
|
12
|
+
private var packageName: String? = null
|
|
13
|
+
private val artifact: UnresolvedArtifactInfo =
|
|
14
|
+
requireNotNull(artifact.takeIf { it.type == "aar" }) {
|
|
15
|
+
"Only Aar is accepted as an artifact"
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
fun getExplodedAarRootDir(): File {
|
|
19
|
+
val explodedRootDir = File("${project.layout.buildDirectory.get()}/intermediates/exploded-aar")
|
|
20
|
+
return File(explodedRootDir, "${artifact.moduleGroup}/${artifact.moduleName}/${artifact.moduleVersion}/$variantName")
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
@Synchronized
|
|
24
|
+
fun getPackageName(): String {
|
|
25
|
+
if (packageName != null) return packageName!!
|
|
26
|
+
|
|
27
|
+
packageName = getNameSpaceFromBuildGradle()
|
|
28
|
+
return packageName!!
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
private fun getNameSpaceFromBuildGradle(): String {
|
|
32
|
+
if (artifact.isExpoPublishDependency == true) {
|
|
33
|
+
return artifact.moduleGroup
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
val subProj = project.rootProject.project(":${artifact.moduleName}")
|
|
37
|
+
val buildFile = subProj.buildFile // points to build.gradle or build.gradle.kts
|
|
38
|
+
|
|
39
|
+
if (!buildFile.exists()) {
|
|
40
|
+
error("build.gradle file does not exist for ${artifact.moduleName}")
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
val text = buildFile.readText()
|
|
44
|
+
|
|
45
|
+
// Regex to match: namespace = "com.example.rnscreens"
|
|
46
|
+
val regex = Regex("""namespace\s*=?\s*["']([^"']+)["']""")
|
|
47
|
+
val match = regex.find(text)
|
|
48
|
+
|
|
49
|
+
val namespace =
|
|
50
|
+
match?.groupValues?.get(1)
|
|
51
|
+
?: error("No namespace found in ${buildFile.path}")
|
|
52
|
+
|
|
53
|
+
return namespace
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
fun getManifestFile() = File(getExplodedAarRootDir(), "AndroidManifest.xml")
|
|
57
|
+
|
|
58
|
+
fun getAssetsDir(): File = File(getExplodedAarRootDir(), "assets")
|
|
59
|
+
|
|
60
|
+
fun getJniDir(): File = File(getExplodedAarRootDir(), "jni")
|
|
61
|
+
|
|
62
|
+
fun getLibsDir(): File = File(getExplodedAarRootDir(), "libs")
|
|
63
|
+
|
|
64
|
+
fun getClassesJarFile(): File = File(getExplodedAarRootDir(), "classes.jar")
|
|
65
|
+
|
|
66
|
+
fun getLocalJars(): Collection<File> {
|
|
67
|
+
return getLibsDir().listFiles()?.filter { it.isFile && it.name.endsWith(".jar") } ?: emptyList()
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
fun getResDir(): File = File(getExplodedAarRootDir(), "res")
|
|
71
|
+
|
|
72
|
+
fun getProguardRules(): File = File(getExplodedAarRootDir(), "proguard.txt")
|
|
73
|
+
|
|
74
|
+
fun getDataBindingFolder(): File = File(getExplodedAarRootDir(), "data-binding")
|
|
75
|
+
|
|
76
|
+
fun getDataBindingLogFolder(): File = File(getExplodedAarRootDir(), "data-binding-base-class-log")
|
|
77
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
package com.callstack.react.brownfield.utils
|
|
2
|
+
|
|
3
|
+
import com.callstack.react.brownfield.shared.BaseProject
|
|
4
|
+
import com.callstack.react.brownfield.shared.Constants.INTERMEDIATES_TEMP_DIR
|
|
5
|
+
import com.callstack.react.brownfield.shared.Constants.RE_BUNDLE_FOLDER
|
|
6
|
+
import java.io.File
|
|
7
|
+
|
|
8
|
+
object DirectoryManager : BaseProject() {
|
|
9
|
+
fun getMergeClassDirectory(variantName: String): File {
|
|
10
|
+
return project.file("$buildDir/intermediates/$INTERMEDIATES_TEMP_DIR/merge_classes/$variantName")
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
fun getKotlinMetaDirectory(variantName: String): File {
|
|
14
|
+
return project.file("$buildDir/tmp/kotlin-classes/$variantName/META-INF")
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
fun getReBundleDirectory(variantName: String): File {
|
|
18
|
+
return project.file("$buildDir/outputs/$RE_BUNDLE_FOLDER/$variantName")
|
|
19
|
+
}
|
|
20
|
+
}
|
package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/utils/Extension.kt
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
package com.callstack.react.brownfield.utils
|
|
2
|
+
|
|
3
|
+
open class Extension {
|
|
4
|
+
companion object {
|
|
5
|
+
const val NAME = "reactBrownfield"
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Name of the module using `com.android.application`
|
|
10
|
+
* For eg, app
|
|
11
|
+
*
|
|
12
|
+
* Default value is `app`
|
|
13
|
+
*/
|
|
14
|
+
var appProjectName = "app"
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* List of dynamic libs (.so) files that you wish to bundle with
|
|
18
|
+
* the aar.
|
|
19
|
+
*
|
|
20
|
+
* By default, only `libappmodules.so` and `libreact_codegen_*.so` are
|
|
21
|
+
* bundled.
|
|
22
|
+
*/
|
|
23
|
+
var dynamicLibs = listOf<String>()
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Whether to use stripped .so files.
|
|
27
|
+
*
|
|
28
|
+
* Default is `true`.
|
|
29
|
+
*/
|
|
30
|
+
var useStrippedSoFiles = true
|
|
31
|
+
|
|
32
|
+
@Deprecated(
|
|
33
|
+
message =
|
|
34
|
+
"This property is deprecated and will be removed in a future release." +
|
|
35
|
+
"The successor is useStrippedSoFiles, which is by default true.",
|
|
36
|
+
replaceWith = ReplaceWith("useStrippedSoFiles"),
|
|
37
|
+
level = DeprecationLevel.WARNING,
|
|
38
|
+
)
|
|
39
|
+
var experimentalUseStrippedSoFiles
|
|
40
|
+
get() = useStrippedSoFiles
|
|
41
|
+
set(value) {
|
|
42
|
+
useStrippedSoFiles = value
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
package com.callstack.react.brownfield.utils
|
|
2
|
+
|
|
3
|
+
sealed class StringMatcher {
|
|
4
|
+
abstract fun matches(input: String): Boolean
|
|
5
|
+
|
|
6
|
+
data class Literal(private val value: String) : StringMatcher() {
|
|
7
|
+
override fun matches(input: String): Boolean = input == value
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
data class Pattern(private val regex: Regex) : StringMatcher() {
|
|
11
|
+
override fun matches(input: String): Boolean = regex.matches(input)
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
companion object {
|
|
15
|
+
fun literal(value: String): StringMatcher = Literal(value)
|
|
16
|
+
|
|
17
|
+
fun regex(pattern: String): StringMatcher = Pattern(Regex(pattern))
|
|
18
|
+
|
|
19
|
+
fun regex(regex: Regex): StringMatcher = Pattern(regex)
|
|
20
|
+
}
|
|
21
|
+
}
|
package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/utils/Utils.kt
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
package com.callstack.react.brownfield.utils
|
|
2
|
+
|
|
3
|
+
import com.callstack.react.brownfield.plugin.RNBrownfieldPlugin.Companion.EXPO_PROJECT_LOCATOR
|
|
4
|
+
import org.gradle.api.Project
|
|
5
|
+
import java.io.File
|
|
6
|
+
|
|
7
|
+
object Utils {
|
|
8
|
+
fun mergeFiles(
|
|
9
|
+
inputFiles: Collection<File>?,
|
|
10
|
+
output: File,
|
|
11
|
+
) {
|
|
12
|
+
if (inputFiles.isNullOrEmpty()) return
|
|
13
|
+
|
|
14
|
+
val existingFiles = inputFiles.filter { it.exists() }
|
|
15
|
+
|
|
16
|
+
if (existingFiles.isEmpty()) return
|
|
17
|
+
|
|
18
|
+
if (!output.exists()) {
|
|
19
|
+
output.createNewFile()
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
existingFiles.forEach { file ->
|
|
23
|
+
output.appendText("\n${file.readText(Charsets.UTF_8)}\n")
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
fun isExpoProject(project: Project): Boolean {
|
|
28
|
+
return project.findProject(EXPO_PROJECT_LOCATOR) != null
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
fun getBundledAssetsVariantName(
|
|
32
|
+
variantName: String?,
|
|
33
|
+
buildTypeName: String?,
|
|
34
|
+
isDebuggable: Boolean,
|
|
35
|
+
): String {
|
|
36
|
+
require(!variantName.isNullOrEmpty()) {
|
|
37
|
+
"getBundledAssetsVariantName: Variant name cannot be empty"
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
require(!buildTypeName.isNullOrEmpty()) {
|
|
41
|
+
"getBundledAssetsVariantName: Build Type cannot be empty"
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (!isDebuggable) {
|
|
45
|
+
return variantName
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (variantName == buildTypeName) {
|
|
49
|
+
return "release"
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
val capitalizedBuildTypeName = buildTypeName.capitalized()
|
|
53
|
+
return if (variantName.endsWith(capitalizedBuildTypeName)) {
|
|
54
|
+
"${variantName.removeSuffix(capitalizedBuildTypeName)}Release"
|
|
55
|
+
} else {
|
|
56
|
+
"release"
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
@@ -102,7 +102,7 @@ final class ExpoHostRuntime {
|
|
|
102
102
|
}
|
|
103
103
|
|
|
104
104
|
/**
|
|
105
|
-
*
|
|
105
|
+
* Use the embedded JavaScript bundle as a Debug fallback when Metro is unavailable.
|
|
106
106
|
* Default value: false
|
|
107
107
|
*/
|
|
108
108
|
public var preferEmbeddedBundleInDebug: Bool = false {
|
|
@@ -232,7 +232,8 @@ class ExpoHostRuntimeDelegate: ExpoReactNativeFactoryDelegate {
|
|
|
232
232
|
bundleURLOverride: nil,
|
|
233
233
|
metroURL: {
|
|
234
234
|
RCTBundleURLProvider.sharedSettings().jsBundleURL(
|
|
235
|
-
forBundleRoot: entryFile
|
|
235
|
+
forBundleRoot: entryFile,
|
|
236
|
+
fallbackURLProvider: { nil }
|
|
236
237
|
)
|
|
237
238
|
}
|
|
238
239
|
)
|