@callstack/react-native-brownfield 6.0.0 → 6.1.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 +52 -0
- package/gradle-plugin/brownfield/build.gradle.kts +4 -0
- package/gradle-plugin/brownfield/gradle/libs.versions.toml +2 -0
- package/gradle-plugin/brownfield/gradle.properties +1 -1
- package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/RNBrownfieldPlugin.kt +24 -7
- package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/RNSourceSets.kt +4 -37
- package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/JNILibsProcessor.kt +206 -104
- package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/ResourceTaskProcessor.kt +201 -4
- package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/VariantHelper.kt +7 -0
- package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/VariantTaskProvider.kt +4 -0
- package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/GradleExclude.kt +31 -0
- package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/MergeClassesTask.kt +2 -0
- package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/PublishingMetadataInjector.kt +28 -3
- package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/utils/AndroidArchiveLibrary.kt +41 -4
- package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/utils/Extension.kt +14 -1
- package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/utils/TaskOutputs.kt +40 -0
- package/gradle-plugin/brownfield/src/test/kotlin/com/callstack/react/brownfield/plugin/AgpCompatibilityMatrixTest.kt +14 -6
- package/gradle-plugin/brownfield/src/test/kotlin/com/callstack/react/brownfield/plugin/HardExcludePredicateTest.kt +28 -0
- package/gradle-plugin/brownfield/src/test/kotlin/com/callstack/react/brownfield/processors/ConfigureProcessJniTaskTest.kt +60 -0
- package/gradle-plugin/brownfield/src/test/kotlin/com/callstack/react/brownfield/processors/CopyExplodedResTaskTest.kt +368 -0
- package/gradle-plugin/brownfield/src/test/kotlin/com/callstack/react/brownfield/processors/JniLibsPlanTest.kt +252 -0
- package/gradle-plugin/brownfield/src/test/kotlin/com/callstack/react/brownfield/processors/MergeClassesLocalJarsTest.kt +73 -0
- package/gradle-plugin/brownfield/src/test/kotlin/com/callstack/react/brownfield/processors/MetroResDirWiringTest.kt +39 -0
- package/gradle-plugin/brownfield/src/test/kotlin/com/callstack/react/brownfield/processors/ProcessAndCopyJniLibsTaskTest.kt +136 -0
- package/gradle-plugin/brownfield/src/test/kotlin/com/callstack/react/brownfield/shared/GradleExcludesTest.kt +81 -0
- package/gradle-plugin/brownfield/src/test/kotlin/com/callstack/react/brownfield/shared/PublishingMetadataInjectorTest.kt +56 -0
- package/gradle-plugin/brownfield/src/test/kotlin/com/callstack/react/brownfield/utils/AndroidArchiveLibraryNamespaceFallbackTest.kt +137 -0
- package/gradle-plugin/brownfield/src/test/kotlin/com/callstack/react/brownfield/utils/ExtensionTest.kt +5 -0
- package/ios/Expo/ExpoHostRuntime.swift +3 -1
- package/ios/Expo/ExpoUpdatesStartup.swift +2 -1
- package/lib/commonjs/expo-config-plugin/android/utils/constants.js +1 -1
- package/lib/commonjs/expo-config-plugin/android/withAndroidModuleFiles.js +1 -1
- package/lib/commonjs/expo-config-plugin/android/withAndroidModuleFiles.js.map +1 -1
- package/lib/commonjs/expo-config-plugin/ios/podfileHelpers.js +2 -2
- package/lib/commonjs/expo-config-plugin/ios/podfileHelpers.js.map +1 -1
- package/lib/commonjs/expo-config-plugin/ios/withIosFrameworkFiles.js +1 -1
- package/lib/commonjs/expo-config-plugin/ios/withIosFrameworkFiles.js.map +1 -1
- package/lib/commonjs/expo-config-plugin/ios/xcodeHelpers.js +2 -2
- package/lib/commonjs/expo-config-plugin/ios/xcodeHelpers.js.map +1 -1
- package/lib/commonjs/expo-config-plugin/template/android/ReactNativeHostManager.vanilla.kt +5 -7
- package/lib/commonjs/expo-config-plugin/template/android/build.gradle.kts +1 -1
- package/lib/commonjs/expo-config-plugin/template/ios/ExpoModulesProviderExtension.swift +7 -0
- package/lib/commonjs/index.js +1 -1
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/scaffold/index.js +1 -1
- package/lib/commonjs/scaffold/index.js.map +1 -1
- package/lib/commonjs/scaffold/projectFiles.js +1 -1
- package/lib/commonjs/scaffold/projectFiles.js.map +1 -1
- package/lib/module/expo-config-plugin/android/utils/constants.js +1 -1
- package/lib/module/expo-config-plugin/android/withAndroidModuleFiles.js +1 -1
- package/lib/module/expo-config-plugin/android/withAndroidModuleFiles.js.map +1 -1
- package/lib/module/expo-config-plugin/ios/podfileHelpers.js +2 -2
- package/lib/module/expo-config-plugin/ios/podfileHelpers.js.map +1 -1
- package/lib/module/expo-config-plugin/ios/withIosFrameworkFiles.js +1 -1
- package/lib/module/expo-config-plugin/ios/withIosFrameworkFiles.js.map +1 -1
- package/lib/module/expo-config-plugin/ios/xcodeHelpers.js +2 -2
- package/lib/module/expo-config-plugin/ios/xcodeHelpers.js.map +1 -1
- package/lib/module/expo-config-plugin/template/android/ReactNativeHostManager.vanilla.kt +5 -7
- package/lib/module/expo-config-plugin/template/android/build.gradle.kts +1 -1
- package/lib/module/expo-config-plugin/template/ios/ExpoModulesProviderExtension.swift +7 -0
- package/lib/module/index.js +1 -1
- package/lib/module/index.js.map +1 -1
- package/lib/module/scaffold/index.js +1 -1
- package/lib/module/scaffold/index.js.map +1 -1
- package/lib/module/scaffold/projectFiles.js +1 -1
- package/lib/module/scaffold/projectFiles.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/withAndroidModuleFiles.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/expo-config-plugin/ios/podfileHelpers.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/expo-config-plugin/ios/withIosFrameworkFiles.d.ts +5 -0
- package/lib/typescript/commonjs/src/expo-config-plugin/ios/withIosFrameworkFiles.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/expo-config-plugin/ios/xcodeHelpers.d.ts +5 -0
- package/lib/typescript/commonjs/src/expo-config-plugin/ios/xcodeHelpers.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/expo-config-plugin/types/android/BrownfieldPluginAndroidConfig.d.ts +6 -0
- package/lib/typescript/commonjs/src/expo-config-plugin/types/android/BrownfieldPluginAndroidConfig.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/scaffold/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/scaffold/projectFiles.d.ts +2 -2
- package/lib/typescript/commonjs/src/scaffold/projectFiles.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/withAndroidModuleFiles.d.ts.map +1 -1
- package/lib/typescript/module/src/expo-config-plugin/ios/podfileHelpers.d.ts.map +1 -1
- package/lib/typescript/module/src/expo-config-plugin/ios/withIosFrameworkFiles.d.ts +5 -0
- package/lib/typescript/module/src/expo-config-plugin/ios/withIosFrameworkFiles.d.ts.map +1 -1
- package/lib/typescript/module/src/expo-config-plugin/ios/xcodeHelpers.d.ts +5 -0
- package/lib/typescript/module/src/expo-config-plugin/ios/xcodeHelpers.d.ts.map +1 -1
- package/lib/typescript/module/src/expo-config-plugin/types/android/BrownfieldPluginAndroidConfig.d.ts +6 -0
- package/lib/typescript/module/src/expo-config-plugin/types/android/BrownfieldPluginAndroidConfig.d.ts.map +1 -1
- package/lib/typescript/module/src/index.d.ts.map +1 -1
- package/lib/typescript/module/src/scaffold/index.d.ts.map +1 -1
- package/lib/typescript/module/src/scaffold/projectFiles.d.ts +2 -2
- package/lib/typescript/module/src/scaffold/projectFiles.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/expo-config-plugin/android/utils/constants.ts +1 -1
- package/src/expo-config-plugin/android/withAndroidModuleFiles.ts +42 -0
- package/src/expo-config-plugin/ios/podfileHelpers.ts +47 -13
- package/src/expo-config-plugin/ios/withIosFrameworkFiles.ts +11 -1
- package/src/expo-config-plugin/ios/xcodeHelpers.ts +67 -9
- package/src/expo-config-plugin/template/android/ReactNativeHostManager.vanilla.kt +5 -7
- package/src/expo-config-plugin/template/android/build.gradle.kts +1 -1
- package/src/expo-config-plugin/template/ios/ExpoModulesProviderExtension.swift +7 -0
- package/src/expo-config-plugin/types/android/BrownfieldPluginAndroidConfig.ts +7 -0
- package/src/index.ts +4 -2
- package/src/scaffold/index.ts +61 -4
- package/src/scaffold/projectFiles.ts +5 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,57 @@
|
|
|
1
1
|
# @callstack/react-native-brownfield
|
|
2
2
|
|
|
3
|
+
## 6.1.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#520](https://github.com/callstack/react-native-brownfield/pull/520) [`b87cdff`](https://github.com/callstack/react-native-brownfield/commit/b87cdff0de1cb147289a7497973b6f191dc74134) Thanks [@KisaneNeko](https://github.com/KisaneNeko)! - fix: pick the right `.so` files for the Android AAR. With `useStrippedSoFiles = false`, the AAR now has `libappmodules.so` and `libreact_codegen_*.so`. Before this fix, those libs were missing and host apps crashed. The AAR also stops embedding the `.so` files of Maven dependencies. The host already gets those through the POM, so its build no longer fails with `2 files found with path 'lib/<abi>/<name>.so'`. If your app module builds or ships a `.so` of its own, list it in `reactBrownfield.dynamicLibs`, which is back. The build lists the `.so` files it left out in `<brownfield module>/build/reports/brownfield/<variant>/skipped-so.txt`. After upgrading, check that file: it lists the `.so` files that used to be in the AAR and now aren't.
|
|
8
|
+
|
|
9
|
+
- [#522](https://github.com/callstack/react-native-brownfield/pull/522) [`20776bb`](https://github.com/callstack/react-native-brownfield/commit/20776bb714c2de1e962515aa7c88235b60c7dabf) Thanks [@KisaneNeko](https://github.com/KisaneNeko)! - feat: the published POM and `module.json` now follow the brownfield module's Gradle exclude rules (`configurations.all { exclude(...) }`). Before, the plugin re-added an excluded dependency when it injected the embedded libraries' dependencies, so the host app still resolved it. The excludes are also written onto every dependency the plugin injects, so the excluded library can't arrive through one of them. On Expo, list them in `android.excludeDependencies` (as `group:module` or `group`), which the config plugin writes into the generated module.
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- [#512](https://github.com/callstack/react-native-brownfield/pull/512) [`520811c`](https://github.com/callstack/react-native-brownfield/commit/520811c47a122cacd1ec15f1b064ad08d699eebb) Thanks [@KisaneNeko](https://github.com/KisaneNeko)! - fix: package classes from libraries' local jars (`libs/*.jar`) into the Android AAR; previously host apps crashed with NoClassDefFoundError. If your app also has those classes, because it added the jar itself as a workaround or depends on a library that the jar bundles, the build now fails with duplicate classes: remove the app's copy
|
|
14
|
+
|
|
15
|
+
- [#513](https://github.com/callstack/react-native-brownfield/pull/513) [`f3dbbd1`](https://github.com/callstack/react-native-brownfield/commit/f3dbbd1c2579f905a358faac0ad1677b3740cebc) Thanks [@KisaneNeko](https://github.com/KisaneNeko)! - fix: keep the resources of every library embedded in the Android AAR; previously only one library's `res/values` survived and host apps failed at resource linking. As in a regular app, the module's own `res` and `resValue`s win over a library's, and when two libraries define the same resource the first one wins (previously the last one won for files such as drawables)
|
|
16
|
+
|
|
17
|
+
- [#521](https://github.com/callstack/react-native-brownfield/pull/521) [`58aedad`](https://github.com/callstack/react-native-brownfield/commit/58aedad94f38098424937533f2ce0b0c3df62067) Thanks [@KisaneNeko](https://github.com/KisaneNeko)! - fix: the AAR build no longer fails with duplicate resources when an embedded library ships the same drawables Metro generates for the app's bundle. Metro's copy wins.
|
|
18
|
+
|
|
19
|
+
- [#503](https://github.com/callstack/react-native-brownfield/pull/503) [`6a258da`](https://github.com/callstack/react-native-brownfield/commit/6a258da42f2bd2cbb112f56948108323aeba74d9) Thanks [@RaphaelFakhri](https://github.com/RaphaelFakhri)! - `ReactNativeBrownfield.onMessage` no longer calls the callback a second time, with the raw message text, when the callback throws. The error now propagates instead of being swallowed.
|
|
20
|
+
- Updated dependencies [[`20776bb`](https://github.com/callstack/react-native-brownfield/commit/20776bb714c2de1e962515aa7c88235b60c7dabf)]:
|
|
21
|
+
- @callstack/brownfield-cli@6.1.0
|
|
22
|
+
|
|
23
|
+
## 6.0.1
|
|
24
|
+
|
|
25
|
+
### Patch Changes
|
|
26
|
+
|
|
27
|
+
- [#487](https://github.com/callstack/react-native-brownfield/pull/487) [`79817d1`](https://github.com/callstack/react-native-brownfield/commit/79817d1a21b0cb28ae63d41e935c57af8e7db39f) Thanks [@KisaneNeko](https://github.com/KisaneNeko)! - Support Expo modules in React Native CLI apps. `brownfield package:*` no longer runs `expo prebuild` on projects with committed `android/` and `ios/` directories, which used to delete the brownfield library module. Prebuild now runs only when the native directory is missing or gitignored. If you commit the generated directories of an Expo app, run `npx expo prebuild` yourself after changing `app.json` or config plugins. `create-react-native-brownfield` now detects Expo and sets up the iOS framework to use the Expo runtime. On a re-run after adding Expo, it also raises an existing framework target to iOS 16.4.
|
|
28
|
+
|
|
29
|
+
`--use-prebuilt-expo` now also turns Expo's precompiled modules on or off for `pod install`, and turns on Swift explicit modules so packaging works in projects that still carry the old `SWIFT_ENABLE_EXPLICIT_MODULES = NO` workaround. It defaults to building Expo from source when the app's React Native version doesn't match the one Expo's precompiled modules were built for.
|
|
30
|
+
|
|
31
|
+
`package:ios` now copies the expo-image dependency XCFrameworks (SDWebImage and libavif) as real files instead of symlinks into `node_modules`, so the package works when moved to another machine.
|
|
32
|
+
|
|
33
|
+
Re-running `create-react-native-brownfield` after `pod install` no longer adds a second Sources build phase to the framework target, which made the next `pod install` fail.
|
|
34
|
+
|
|
35
|
+
The `package:ios` script that `create-react-native-brownfield` adds now passes `--add-spm-package`, so the iOS app adds one local Swift package instead of every XCFramework. Existing scripts aren't changed.
|
|
36
|
+
|
|
37
|
+
- [#508](https://github.com/callstack/react-native-brownfield/pull/508) [`7e63e20`](https://github.com/callstack/react-native-brownfield/commit/7e63e204c449ab36ce5b109ff3eb5db086260089) Thanks [@malopezr7](https://github.com/malopezr7)! - Fix an iOS crash with expo-updates 57 when updates are enabled. The Expo runtime no longer asks the Updates controller for its launch asset before the controller has started.
|
|
38
|
+
|
|
39
|
+
- [#495](https://github.com/callstack/react-native-brownfield/pull/495) [`3b38aeb`](https://github.com/callstack/react-native-brownfield/commit/3b38aebb63810a8d1cc686bd70cccdeb279bf119) Thanks [@hurali97](https://github.com/hurali97)! - fix: resolve the namespace from AndroidManifest.xml `package` for libraries without a `namespace` in build.gradle
|
|
40
|
+
|
|
41
|
+
- [#500](https://github.com/callstack/react-native-brownfield/pull/500) [`0f62490`](https://github.com/callstack/react-native-brownfield/commit/0f62490e7602d1aad56ee5d9eba2fd667dc0171a) Thanks [@hurali97](https://github.com/hurali97)! - fix(android): stop the scaffolded `ReactNativeHostManager` from loading React Native twice
|
|
42
|
+
|
|
43
|
+
The `ReactNativeHostManager.kt` generated by `npm create @callstack/react-native-brownfield` for React Native CLI projects called `loadReactNative(application)` and then `ReactNativeBrownfield.initialize(...)`. Both run `DefaultNewArchitectureEntryPoint.load()`, which overrides the React Native feature flags, so the app crashed on startup with `Feature flags cannot be overridden more than once`.
|
|
44
|
+
|
|
45
|
+
The generated host manager now:
|
|
46
|
+
- no longer calls `loadReactNative` (`ReactNativeBrownfield.initialize` already loads the native libraries and feature flags exactly once);
|
|
47
|
+
- passes the `ReactHost` as a factory to the non-deprecated `initialize` overload, so it is built after `SoLoader.init` instead of crashing with `SoLoader.init() not yet called`;
|
|
48
|
+
- keeps the one behavior `loadReactNative` provided on the side by flagging edge-to-edge when `IS_EDGE_TO_EDGE_ENABLED` is set.
|
|
49
|
+
|
|
50
|
+
Fixes [#492](https://github.com/callstack/react-native-brownfield/issues/492).
|
|
51
|
+
|
|
52
|
+
- Updated dependencies [[`79817d1`](https://github.com/callstack/react-native-brownfield/commit/79817d1a21b0cb28ae63d41e935c57af8e7db39f), [`69fe3e3`](https://github.com/callstack/react-native-brownfield/commit/69fe3e3f05a49036cae1f3564a47ef3eed186155)]:
|
|
53
|
+
- @callstack/brownfield-cli@6.0.1
|
|
54
|
+
|
|
3
55
|
## 6.0.0
|
|
4
56
|
|
|
5
57
|
### Major Changes
|
|
@@ -113,10 +113,14 @@ dependencies {
|
|
|
113
113
|
// minimum Gradle version) for every app that applies this plugin.
|
|
114
114
|
compileOnly(libs.agp)
|
|
115
115
|
compileOnly(libs.common)
|
|
116
|
+
compileOnly(libs.sdk.common)
|
|
117
|
+
compileOnly(libs.layoutlib.api)
|
|
116
118
|
implementation(libs.asm.commons)
|
|
117
119
|
implementation(libs.versioncompare)
|
|
118
120
|
testImplementation(libs.agp)
|
|
119
121
|
testImplementation(libs.common)
|
|
122
|
+
testImplementation(libs.sdk.common)
|
|
123
|
+
testImplementation(libs.layoutlib.api)
|
|
120
124
|
testImplementation(libs.junit.jupiter)
|
|
121
125
|
testImplementation(gradleTestKit())
|
|
122
126
|
testImplementation(kotlin("test"))
|
|
@@ -19,6 +19,8 @@ detekt = { id = "io.gitlab.arturbosch.detekt", version.ref = "detekt" }
|
|
|
19
19
|
[libraries]
|
|
20
20
|
agp = { module = "com.android.tools.build:gradle", name = "agp", version.ref = "agp" }
|
|
21
21
|
common = { module = "com.android.tools:common", version.ref = "common" }
|
|
22
|
+
sdk-common = { module = "com.android.tools:sdk-common", version.ref = "common" }
|
|
23
|
+
layoutlib-api = { module = "com.android.tools.layoutlib:layoutlib-api", version.ref = "common" }
|
|
22
24
|
asm-commons = { module = "org.ow2.asm:asm-commons", version.ref = "asm-commons" }
|
|
23
25
|
versioncompare = { module = "io.github.g00fy2:versioncompare", version.ref = "versioncompare" }
|
|
24
26
|
junit-jupiter = { module = "org.junit.jupiter:junit-jupiter", version.ref = "junit" }
|
|
@@ -19,11 +19,13 @@ import com.callstack.react.brownfield.processors.VariantTaskProvider
|
|
|
19
19
|
import com.callstack.react.brownfield.shared.BaseProject
|
|
20
20
|
import com.callstack.react.brownfield.shared.Constants
|
|
21
21
|
import com.callstack.react.brownfield.shared.Constants.PROJECT_ID
|
|
22
|
+
import com.callstack.react.brownfield.shared.GradleExclude
|
|
22
23
|
import com.callstack.react.brownfield.shared.Logging
|
|
23
24
|
import com.callstack.react.brownfield.shared.PublishingMetadataInjector
|
|
24
25
|
import com.callstack.react.brownfield.shared.UnresolvedArtifactInfo
|
|
25
26
|
import com.callstack.react.brownfield.shared.VersionMediatingDependencySet
|
|
26
27
|
import com.callstack.react.brownfield.shared.dropHardExcludedDependencies
|
|
28
|
+
import com.callstack.react.brownfield.shared.gradleExcludes
|
|
27
29
|
import com.callstack.react.brownfield.utils.AndroidArchiveLibrary
|
|
28
30
|
import com.callstack.react.brownfield.utils.DirectoryManager
|
|
29
31
|
import com.callstack.react.brownfield.utils.Extension
|
|
@@ -33,6 +35,24 @@ import org.gradle.api.Plugin
|
|
|
33
35
|
import org.gradle.api.Project
|
|
34
36
|
import org.gradle.api.ProjectConfigurationException
|
|
35
37
|
|
|
38
|
+
/**
|
|
39
|
+
* Coordinates that must never be published: embedded in the AAR (not resolvable from Maven), or
|
|
40
|
+
* excluded by the brownfield module's own Gradle rules.
|
|
41
|
+
*/
|
|
42
|
+
internal fun hardExcludePredicate(
|
|
43
|
+
project: Project,
|
|
44
|
+
expoPublishingHelper: ExpoPublishingHelper?,
|
|
45
|
+
artifacts: List<UnresolvedArtifactInfo>,
|
|
46
|
+
expoProjects: List<ExpoGradleProjectProjection>,
|
|
47
|
+
excludes: List<GradleExclude>,
|
|
48
|
+
): (String, String) -> Boolean =
|
|
49
|
+
{ groupId, artifactId ->
|
|
50
|
+
(expoPublishingHelper?.shouldExcludeDependency(groupId, artifactId) ?: (groupId == project.rootProject.name)) ||
|
|
51
|
+
artifacts.any { it.moduleGroup == groupId && it.moduleName == artifactId } ||
|
|
52
|
+
expoProjects.any { it.publication?.groupId == groupId && it.publication?.artifactId == artifactId } ||
|
|
53
|
+
excludes.any { it.matches(groupId, artifactId) }
|
|
54
|
+
}
|
|
55
|
+
|
|
36
56
|
class RNBrownfieldPlugin : Plugin<Project> {
|
|
37
57
|
private lateinit var extension: Extension
|
|
38
58
|
private lateinit var project: Project
|
|
@@ -140,11 +160,8 @@ class RNBrownfieldPlugin : Plugin<Project> {
|
|
|
140
160
|
// Coordinates that must never be published: they're embedded in the AAR, not
|
|
141
161
|
// resolvable from Maven. Distinct from "superseded" coordinates, which ARE re-injected
|
|
142
162
|
// (replacing a stale entry) and so must not be dropped here.
|
|
143
|
-
val
|
|
144
|
-
|
|
145
|
-
artifacts.any { it.moduleGroup == groupId && it.moduleName == artifactId } ||
|
|
146
|
-
expoProjects.any { it.publication?.groupId == groupId && it.publication?.artifactId == artifactId }
|
|
147
|
-
}
|
|
163
|
+
val excludes = gradleExcludes(project)
|
|
164
|
+
val hardExcludePredicate = hardExcludePredicate(project, expoPublishingHelper, artifacts, expoProjects, excludes)
|
|
148
165
|
dropHardExcludedDependencies(transitiveDeps, hardExcludePredicate)
|
|
149
166
|
|
|
150
167
|
Logging.log(
|
|
@@ -155,7 +172,7 @@ class RNBrownfieldPlugin : Plugin<Project> {
|
|
|
155
172
|
hardExcludePredicate(groupId, artifactId) || rncSupersededCoordinates.contains(groupId to artifactId)
|
|
156
173
|
}
|
|
157
174
|
|
|
158
|
-
injector.configure(transitiveDeps, removalPredicate)
|
|
175
|
+
injector.configure(transitiveDeps, removalPredicate, excludes)
|
|
159
176
|
Logging.log("PublishingMetadataInjector ran: injected merged transitive dependencies into POM and Gradle Module Metadata")
|
|
160
177
|
|
|
161
178
|
// Informational only — throwing would recreate the upgrade break that the namespaced
|
|
@@ -277,7 +294,7 @@ class RNBrownfieldPlugin : Plugin<Project> {
|
|
|
277
294
|
|
|
278
295
|
/** ===== jniLibsProcessor ===== */
|
|
279
296
|
val jniLibsProcessor = JNILibsProcessor(project)
|
|
280
|
-
jniLibsProcessor.processJniLibs(aarLibraries, variant)
|
|
297
|
+
jniLibsProcessor.processJniLibs(aarLibraries, variant, explodeTask)
|
|
281
298
|
|
|
282
299
|
/** ===== proguardProcessor ===== */
|
|
283
300
|
val proguardProcessor = ProguardProcessor(project)
|
|
@@ -8,8 +8,7 @@ import com.callstack.react.brownfield.exceptions.NameSpaceNotFound
|
|
|
8
8
|
import com.callstack.react.brownfield.processors.VariantHelper
|
|
9
9
|
import com.callstack.react.brownfield.utils.Extension
|
|
10
10
|
import com.callstack.react.brownfield.utils.Utils
|
|
11
|
-
import com.callstack.react.brownfield.utils.
|
|
12
|
-
import org.gradle.api.GradleException
|
|
11
|
+
import com.callstack.react.brownfield.utils.directoryGetter
|
|
13
12
|
import org.gradle.api.Project
|
|
14
13
|
import org.gradle.api.Task
|
|
15
14
|
import org.gradle.api.file.DirectoryProperty
|
|
@@ -57,16 +56,9 @@ object RNSourceSets {
|
|
|
57
56
|
// 2. Use the onVariants block to wire RN bundle outputs via the Variant Sources API
|
|
58
57
|
componentsExtension.onVariants { variant ->
|
|
59
58
|
val variantName = variant.name
|
|
60
|
-
val bundledAssetsVariantName =
|
|
61
|
-
VariantHelper.getBundledAssetsVariantName(
|
|
62
|
-
variantName = variantName,
|
|
63
|
-
buildTypeName = variant.buildType,
|
|
64
|
-
isDebuggable = variant.debuggable,
|
|
65
|
-
)
|
|
66
|
-
val capitalizedBundledAssetsVariantName = bundledAssetsVariantName.capitalized()
|
|
67
59
|
val appProject = getAppProject()
|
|
68
60
|
|
|
69
|
-
val jsBundleTaskName =
|
|
61
|
+
val jsBundleTaskName = VariantHelper.getMetroBundleTaskName(variant)
|
|
70
62
|
|
|
71
63
|
/**
|
|
72
64
|
* Wire the bundle task's own `jsBundleDir`/`resourcesDir` outputs as *generated*
|
|
@@ -89,12 +81,7 @@ object RNSourceSets {
|
|
|
89
81
|
|
|
90
82
|
/**
|
|
91
83
|
* Wires `taskName`'s `getterName` output (expected to be a `DirectoryProperty`) as a
|
|
92
|
-
* generated source directory for `sources`.
|
|
93
|
-
*
|
|
94
|
-
* Resolving the task by name (rather than importing its class) keeps this plugin from
|
|
95
|
-
* depending on RNGP's/expo-updates' internal task types. If the task, or its expected output
|
|
96
|
-
* property, isn't there, this fails the build immediately with a clear message instead of
|
|
97
|
-
* silently producing an empty/stale source directory.
|
|
84
|
+
* generated source directory for `sources`. See [directoryGetter] for the checks.
|
|
98
85
|
*/
|
|
99
86
|
private fun wireGeneratedSourceDirectory(
|
|
100
87
|
appProject: Project,
|
|
@@ -104,27 +91,7 @@ object RNSourceSets {
|
|
|
104
91
|
) {
|
|
105
92
|
if (sources == null) return
|
|
106
93
|
|
|
107
|
-
val
|
|
108
|
-
appProject.tasks.findByName(taskName)
|
|
109
|
-
?: throw GradleException(
|
|
110
|
-
"brownfield: expected task '$taskName' was not found in project " +
|
|
111
|
-
"'${appProject.path}'. Check that the plugin producing it is applied there.",
|
|
112
|
-
)
|
|
113
|
-
|
|
114
|
-
val getter =
|
|
115
|
-
runCatching { task.javaClass.getMethod(getterName) }.getOrElse {
|
|
116
|
-
throw GradleException(
|
|
117
|
-
"brownfield: task '$taskName' (${task.javaClass.name}) does not expose " +
|
|
118
|
-
"'$getterName()'. The plugin that registers it most likely changed its " +
|
|
119
|
-
"API; the brownfield Gradle plugin needs updating to match.",
|
|
120
|
-
it,
|
|
121
|
-
)
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
check(DirectoryProperty::class.java.isAssignableFrom(getter.returnType)) {
|
|
125
|
-
"brownfield: '$taskName.$getterName()' no longer returns a DirectoryProperty."
|
|
126
|
-
}
|
|
127
|
-
|
|
94
|
+
val getter = directoryGetter(appProject, taskName, getterName)
|
|
128
95
|
val taskProvider = appProject.tasks.named(taskName)
|
|
129
96
|
sources.addGeneratedSourceDirectory(taskProvider) { t -> getter.invoke(t) as DirectoryProperty }
|
|
130
97
|
}
|
|
@@ -1,28 +1,27 @@
|
|
|
1
1
|
package com.callstack.react.brownfield.processors
|
|
2
2
|
|
|
3
3
|
import com.android.build.api.variant.LibraryVariant
|
|
4
|
-
import com.callstack.react.brownfield.shared.Logging
|
|
5
4
|
import com.callstack.react.brownfield.utils.AndroidArchiveLibrary
|
|
6
5
|
import com.callstack.react.brownfield.utils.Extension
|
|
7
6
|
import com.callstack.react.brownfield.utils.capitalized
|
|
8
7
|
import org.gradle.api.DefaultTask
|
|
9
8
|
import org.gradle.api.Project
|
|
9
|
+
import org.gradle.api.Task
|
|
10
10
|
import org.gradle.api.file.ConfigurableFileCollection
|
|
11
11
|
import org.gradle.api.file.DirectoryProperty
|
|
12
|
+
import org.gradle.api.file.RegularFileProperty
|
|
12
13
|
import org.gradle.api.provider.ListProperty
|
|
13
|
-
import org.gradle.api.provider.Property
|
|
14
14
|
import org.gradle.api.tasks.CacheableTask
|
|
15
15
|
import org.gradle.api.tasks.Input
|
|
16
|
-
import org.gradle.api.tasks.InputDirectory
|
|
17
16
|
import org.gradle.api.tasks.InputFiles
|
|
18
17
|
import org.gradle.api.tasks.Optional
|
|
19
18
|
import org.gradle.api.tasks.OutputDirectory
|
|
19
|
+
import org.gradle.api.tasks.OutputFile
|
|
20
20
|
import org.gradle.api.tasks.PathSensitive
|
|
21
21
|
import org.gradle.api.tasks.PathSensitivity
|
|
22
22
|
import org.gradle.api.tasks.TaskAction
|
|
23
|
+
import org.gradle.api.tasks.TaskProvider
|
|
23
24
|
import java.io.File
|
|
24
|
-
import kotlin.collections.component1
|
|
25
|
-
import kotlin.collections.component2
|
|
26
25
|
|
|
27
26
|
/**
|
|
28
27
|
* Below contains a list of dynamic libs which we should not embed
|
|
@@ -37,126 +36,246 @@ val IGNORE_EMBEDDED_LIBS =
|
|
|
37
36
|
"libreactnative.so",
|
|
38
37
|
)
|
|
39
38
|
|
|
39
|
+
private val ABIS = listOf("arm64-v8a", "armeabi-v7a", "x86_64", "x86")
|
|
40
|
+
|
|
41
|
+
private const val APP_MODULES_LIB = "libappmodules.so"
|
|
42
|
+
|
|
43
|
+
internal enum class SkipReason { IGNORED, NOT_EMBEDDED }
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* @property copies source file for each `<abi>/<name>` that goes into the AAR
|
|
47
|
+
* @property unmatchedDynamicLibs dynamicLibs entries that match no file in the app module's output
|
|
48
|
+
* @property skipped every lib name that no ABI copies, with why
|
|
49
|
+
* @property ignoredDynamicLibs dynamicLibs entries dropped because an ignore entry matches them
|
|
50
|
+
* @property excludedAbis ABIs the embedded AARs ship but the app module did not build
|
|
51
|
+
*/
|
|
52
|
+
internal data class JniLibsPlan(
|
|
53
|
+
val copies: Map<String, File>,
|
|
54
|
+
val unmatchedDynamicLibs: Set<String>,
|
|
55
|
+
val skipped: Map<String, SkipReason>,
|
|
56
|
+
val ignoredDynamicLibs: Set<String> = emptySet(),
|
|
57
|
+
val excludedAbis: Set<String> = emptySet(),
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
private fun isAppOwned(name: String) = name == APP_MODULES_LIB || (name.startsWith("libreact_codegen_") && name.endsWith(".so"))
|
|
61
|
+
|
|
62
|
+
private fun isIgnored(
|
|
63
|
+
name: String,
|
|
64
|
+
ignoredLibs: List<String>,
|
|
65
|
+
) = ignoredLibs.any { entry -> name == entry || name.contains(entry) }
|
|
66
|
+
|
|
67
|
+
private fun libNames(dir: File?): List<String> = dir?.listFiles()?.filter { it.isFile }?.map { it.name }.orEmpty()
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Picks the .so files for the AAR: the app module's own libs, the libs the embedded libraries
|
|
71
|
+
* ship, and [dynamicLibs], minus [ignoredLibs]. Libs that only come from Maven dependencies stay
|
|
72
|
+
* out, because the host app gets them through the published POM.
|
|
73
|
+
*/
|
|
74
|
+
internal fun planJniLibs(
|
|
75
|
+
aarJniDirs: List<File>,
|
|
76
|
+
appNativeLibsDir: File?,
|
|
77
|
+
ignoredLibs: List<String>,
|
|
78
|
+
dynamicLibs: List<String>,
|
|
79
|
+
): JniLibsPlan {
|
|
80
|
+
val copies = linkedMapOf<String, File>()
|
|
81
|
+
val matchedDynamicLibs = mutableSetOf<String>()
|
|
82
|
+
val candidates = mutableMapOf<String, SkipReason>()
|
|
83
|
+
val ignoredDynamicLibs = mutableSetOf<String>()
|
|
84
|
+
|
|
85
|
+
// An ABI folder without libappmodules.so crashes on devices that pick it, so follow the app
|
|
86
|
+
// module's ABIs (it may use abiFilters) and only fall back to all of them when it built none.
|
|
87
|
+
val appAbis = ABIS.filter { abi -> appNativeLibsDir?.let { File(it, abi).isDirectory } == true }
|
|
88
|
+
val abis = appAbis.ifEmpty { ABIS }
|
|
89
|
+
val excludedAbis = ABIS.filter { abi -> abi !in abis && aarJniDirs.any { File(it, abi).isDirectory } }.toSet()
|
|
90
|
+
|
|
91
|
+
for (abi in abis) {
|
|
92
|
+
val appAbiDir = appNativeLibsDir?.let { File(it, abi) }
|
|
93
|
+
val appNames = libNames(appAbiDir).toSet()
|
|
94
|
+
|
|
95
|
+
val embedded = linkedMapOf<String, File>()
|
|
96
|
+
aarJniDirs.forEach { jniDir ->
|
|
97
|
+
val abiDir = File(jniDir, abi)
|
|
98
|
+
libNames(abiDir).forEach { name -> embedded.putIfAbsent(name, File(abiDir, name)) }
|
|
99
|
+
}
|
|
100
|
+
val extra = dynamicLibs.filter { it in appNames }
|
|
101
|
+
matchedDynamicLibs += extra
|
|
102
|
+
ignoredDynamicLibs += extra.filter { isIgnored(it, ignoredLibs) }
|
|
103
|
+
|
|
104
|
+
val wanted = appNames.filter(::isAppOwned) + (embedded.keys + extra).filterNot { isIgnored(it, ignoredLibs) }
|
|
105
|
+
wanted.forEach { name ->
|
|
106
|
+
copies["$abi/$name"] = appAbiDir?.let { File(it, name) }?.takeIf { it.isFile } ?: embedded.getValue(name)
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
(appNames + embedded.keys).filterNot { it in wanted }.forEach { name ->
|
|
110
|
+
val reason = if (isIgnored(name, ignoredLibs)) SkipReason.IGNORED else SkipReason.NOT_EMBEDDED
|
|
111
|
+
// IGNORED wins: once a name is ignored in one ABI it is ignored everywhere.
|
|
112
|
+
if (candidates[name] != SkipReason.IGNORED) candidates[name] = reason
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
val copiedNames = copies.keys.map { it.substringAfter('/') }.toSet()
|
|
117
|
+
return JniLibsPlan(
|
|
118
|
+
copies = copies,
|
|
119
|
+
unmatchedDynamicLibs = dynamicLibs.toSet() - matchedDynamicLibs,
|
|
120
|
+
skipped = candidates.filterKeys { it !in copiedNames }.toSortedMap(),
|
|
121
|
+
ignoredDynamicLibs = ignoredDynamicLibs,
|
|
122
|
+
excludedAbis = excludedAbis,
|
|
123
|
+
)
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
internal fun planWarnings(plan: JniLibsPlan): List<String> =
|
|
127
|
+
plan.unmatchedDynamicLibs.map { entry ->
|
|
128
|
+
"Brownfield: dynamicLibs entry '$entry' matches no .so file in the app module's native output."
|
|
129
|
+
} +
|
|
130
|
+
plan.ignoredDynamicLibs.map { name ->
|
|
131
|
+
"Brownfield: dynamicLibs entry '$name' is not in the AAR because an ignore entry matches it. " +
|
|
132
|
+
"Remove that entry from ignoreEmbeddedLibs to embed it."
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* One line naming the libs no embedded library ships, or null when there are none. Ignored libs
|
|
137
|
+
* are left out: they are skipped on purpose and would only add noise on every build.
|
|
138
|
+
*/
|
|
139
|
+
internal fun skippedSummary(
|
|
140
|
+
plan: JniLibsPlan,
|
|
141
|
+
reportFile: File?,
|
|
142
|
+
): String? {
|
|
143
|
+
val names = plan.skipped.filterValues { it == SkipReason.NOT_EMBEDDED }.keys.sorted()
|
|
144
|
+
if (names.isEmpty()) return null
|
|
145
|
+
val details = reportFile?.let { " Details: ${it.absolutePath}" }.orEmpty()
|
|
146
|
+
return "Brownfield: left ${names.size} .so file(s) out of the AAR because no embedded library ships them: " +
|
|
147
|
+
"${names.joinToString(", ")}. If one comes from a Maven dependency, the host app gets it through the POM. " +
|
|
148
|
+
"If not (for example, your app module builds or ships it), add it to reactBrownfield.dynamicLibs.$details"
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
internal data class AppNativeLibsSource(val relativeDir: String, val producerTaskName: String)
|
|
152
|
+
|
|
153
|
+
internal fun appNativeLibsSource(
|
|
154
|
+
variantName: String,
|
|
155
|
+
useStrippedSoFiles: Boolean,
|
|
156
|
+
): AppNativeLibsSource {
|
|
157
|
+
val capitalized = variantName.capitalized()
|
|
158
|
+
return if (useStrippedSoFiles) {
|
|
159
|
+
val task = "strip${capitalized}DebugSymbols"
|
|
160
|
+
AppNativeLibsSource("intermediates/stripped_native_libs/$variantName/$task/out/lib", task)
|
|
161
|
+
} else {
|
|
162
|
+
val task = "merge${capitalized}NativeLibs"
|
|
163
|
+
AppNativeLibsSource("intermediates/merged_native_libs/$variantName/$task/out/lib", task)
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
40
167
|
@CacheableTask
|
|
41
168
|
abstract class ProcessAndCopyJniLibsTask : DefaultTask() {
|
|
42
169
|
@get:InputFiles
|
|
43
170
|
@get:PathSensitive(PathSensitivity.RELATIVE)
|
|
44
171
|
abstract val aarJniDirs: ConfigurableFileCollection
|
|
45
172
|
|
|
46
|
-
@
|
|
173
|
+
// @InputFiles rather than @InputDirectory: a variant without native code has no such dir,
|
|
174
|
+
// and @InputDirectory would fail validation before the task can run.
|
|
175
|
+
@get:InputFiles
|
|
47
176
|
@get:Optional
|
|
48
177
|
@get:PathSensitive(PathSensitivity.RELATIVE)
|
|
49
|
-
abstract val
|
|
178
|
+
abstract val appNativeLibsDir: DirectoryProperty
|
|
50
179
|
|
|
51
180
|
@get:Input
|
|
52
|
-
abstract val
|
|
181
|
+
abstract val extraIgnoredLibs: ListProperty<String>
|
|
53
182
|
|
|
54
183
|
@get:Input
|
|
55
|
-
abstract val
|
|
184
|
+
abstract val dynamicLibs: ListProperty<String>
|
|
56
185
|
|
|
57
186
|
@get:OutputDirectory
|
|
58
187
|
abstract val outputDirectory: DirectoryProperty
|
|
59
188
|
|
|
189
|
+
// A declared output, so it is restored on cache hits when nothing is logged.
|
|
190
|
+
@get:OutputFile
|
|
191
|
+
abstract val skippedReportFile: RegularFileProperty
|
|
192
|
+
|
|
60
193
|
@TaskAction
|
|
61
194
|
fun execute() {
|
|
62
195
|
val outDir = outputDirectory.get().asFile
|
|
63
|
-
// Clear out old data to ensure clean, reproducible builds
|
|
64
196
|
outDir.deleteRecursively()
|
|
65
197
|
outDir.mkdirs()
|
|
66
198
|
|
|
67
|
-
val
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
.
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
aarJniDirs.forEach { jniDir ->
|
|
74
|
-
if (jniDir.exists()) {
|
|
75
|
-
processNestedLibs(jniDir.listFiles(), existingJNILibs)
|
|
76
|
-
|
|
77
|
-
// If not using stripped files, copy the unstripped ones directly to our output
|
|
78
|
-
if (!useStrippedSoFiles.get()) {
|
|
79
|
-
jniDir.copyRecursively(outDir, overwrite = true)
|
|
80
|
-
}
|
|
81
|
-
}
|
|
199
|
+
val appDir = appNativeLibsDir.orNull?.asFile
|
|
200
|
+
if (appDir != null && !appDir.exists()) {
|
|
201
|
+
logger.warn(
|
|
202
|
+
"Brownfield: $appDir does not exist, so libappmodules.so and libreact_codegen_*.so " +
|
|
203
|
+
"were not found and are not in the AAR.",
|
|
204
|
+
)
|
|
82
205
|
}
|
|
83
206
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
207
|
+
val plan =
|
|
208
|
+
planJniLibs(
|
|
209
|
+
aarJniDirs.files.toList(),
|
|
210
|
+
appDir,
|
|
211
|
+
IGNORE_EMBEDDED_LIBS + extraIgnoredLibs.getOrElse(emptyList()),
|
|
212
|
+
dynamicLibs.getOrElse(emptyList()),
|
|
213
|
+
)
|
|
89
214
|
|
|
90
|
-
|
|
91
|
-
outDir: File,
|
|
92
|
-
existingJNILibs: MutableMap<String, MutableList<String>>,
|
|
93
|
-
) {
|
|
94
|
-
val fromDir = strippedLibsDir.get().asFile
|
|
95
|
-
if (!fromDir.exists()) return
|
|
215
|
+
plan.copies.forEach { (path, source) -> source.copyTo(File(outDir, path), overwrite = true) }
|
|
96
216
|
|
|
97
|
-
|
|
98
|
-
|
|
217
|
+
writeReport(plan)
|
|
218
|
+
val reportFile = skippedReportFile.get().asFile
|
|
219
|
+
skippedSummary(plan, reportFile)?.let { logger.lifecycle(it) }
|
|
220
|
+
plan.skipped.forEach { (name, reason) -> logger.info("Brownfield: skipped $name ($reason)") }
|
|
221
|
+
planWarnings(plan).forEach { logger.warn(it) }
|
|
222
|
+
if (plan.excludedAbis.isNotEmpty()) {
|
|
223
|
+
logger.info("Brownfield: left out ABIs the app module did not build: ${plan.excludedAbis.sorted().joinToString(", ")}")
|
|
99
224
|
}
|
|
100
225
|
}
|
|
101
226
|
|
|
102
|
-
private fun
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
copyIfAllowed(file, destArchDir)
|
|
113
|
-
}
|
|
227
|
+
private fun writeReport(plan: JniLibsPlan) {
|
|
228
|
+
val reportFile = skippedReportFile.get().asFile
|
|
229
|
+
reportFile.parentFile.mkdirs()
|
|
230
|
+
val lines =
|
|
231
|
+
if (plan.skipped.isEmpty()) {
|
|
232
|
+
listOf("No .so files were left out.")
|
|
233
|
+
} else {
|
|
234
|
+
listOfNotNull(skippedSummary(plan, null)) + plan.skipped.map { (name, reason) -> "$name: $reason" }
|
|
235
|
+
}
|
|
236
|
+
reportFile.writeText(lines.joinToString("\n", postfix = "\n"))
|
|
114
237
|
}
|
|
238
|
+
}
|
|
115
239
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
240
|
+
internal fun wireAarJniDirs(
|
|
241
|
+
task: ProcessAndCopyJniLibsTask,
|
|
242
|
+
jniDirs: List<File>,
|
|
243
|
+
explodeTask: TaskProvider<out Task>,
|
|
244
|
+
) {
|
|
245
|
+
// The dirs are plain paths, so Gradle can't infer who fills them; without this the task can
|
|
246
|
+
// run before the AARs are unpacked and drop every embedded lib.
|
|
247
|
+
task.aarJniDirs.setFrom(jniDirs)
|
|
248
|
+
task.aarJniDirs.builtBy(explodeTask)
|
|
249
|
+
}
|
|
122
250
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
251
|
+
internal fun configureProcessJniTask(
|
|
252
|
+
task: ProcessAndCopyJniLibsTask,
|
|
253
|
+
project: Project,
|
|
254
|
+
appProject: Project,
|
|
255
|
+
projectExt: Extension,
|
|
256
|
+
variantName: String,
|
|
257
|
+
jniDirs: List<File>,
|
|
258
|
+
explodeTask: TaskProvider<out Task>,
|
|
259
|
+
) {
|
|
260
|
+
val source = appNativeLibsSource(variantName, projectExt.useStrippedSoFiles)
|
|
129
261
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
}
|
|
262
|
+
task.extraIgnoredLibs.set(projectExt.ignoreEmbeddedLibs)
|
|
263
|
+
task.dynamicLibs.set(projectExt.dynamicLibs)
|
|
264
|
+
wireAarJniDirs(task, jniDirs, explodeTask)
|
|
265
|
+
task.appNativeLibsDir.set(appProject.layout.buildDirectory.dir(source.relativeDir))
|
|
266
|
+
task.skippedReportFile.set(project.layout.buildDirectory.file("reports/brownfield/$variantName/skipped-so.txt"))
|
|
136
267
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
)
|
|
141
|
-
files?.forEach { folder ->
|
|
142
|
-
val libFiles = folder.listFiles() ?: return@forEach
|
|
143
|
-
val libList = existingJNILibs[folder.name] ?: return@forEach
|
|
144
|
-
|
|
145
|
-
libFiles.forEach { file ->
|
|
146
|
-
if (file.name in libList) {
|
|
147
|
-
file.delete()
|
|
148
|
-
} else {
|
|
149
|
-
libList.add(file.name)
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
}
|
|
268
|
+
task.dependsOn(
|
|
269
|
+
"${appProject.path}:${source.producerTaskName}",
|
|
270
|
+
"${project.path}:generateCodegenSchemaFromJavaScript",
|
|
271
|
+
)
|
|
154
272
|
}
|
|
155
273
|
|
|
156
274
|
class JNILibsProcessor(val project: Project) {
|
|
157
275
|
fun processJniLibs(
|
|
158
276
|
aarLibraries: Collection<AndroidArchiveLibrary>,
|
|
159
277
|
variant: LibraryVariant,
|
|
278
|
+
explodeTask: TaskProvider<out Task>,
|
|
160
279
|
) {
|
|
161
280
|
val variantName = variant.name
|
|
162
281
|
val capitalizedVariantName = variantName.capitalized()
|
|
@@ -165,25 +284,8 @@ class JNILibsProcessor(val project: Project) {
|
|
|
165
284
|
|
|
166
285
|
val processJniTask =
|
|
167
286
|
project.tasks.register("processCustomJniLibsFor$capitalizedVariantName", ProcessAndCopyJniLibsTask::class.java) {
|
|
168
|
-
|
|
169
|
-
it
|
|
170
|
-
|
|
171
|
-
val jniDirs =
|
|
172
|
-
aarLibraries.map { aarLib ->
|
|
173
|
-
aarLib.getJniDir()
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
it.aarJniDirs.setFrom(jniDirs)
|
|
177
|
-
|
|
178
|
-
val fromDirProvider =
|
|
179
|
-
appProject.layout.buildDirectory.dir(
|
|
180
|
-
"intermediates/stripped_native_libs/$variantName/strip${capitalizedVariantName}DebugSymbols/out/lib",
|
|
181
|
-
)
|
|
182
|
-
it.strippedLibsDir.set(fromDirProvider)
|
|
183
|
-
|
|
184
|
-
val stripTaskPath = ":${appProject.name}:strip${capitalizedVariantName}DebugSymbols"
|
|
185
|
-
val codegenTaskPath = ":${project.name}:generateCodegenSchemaFromJavaScript"
|
|
186
|
-
it.dependsOn(stripTaskPath, codegenTaskPath)
|
|
287
|
+
val jniDirs = aarLibraries.map { aarLib -> aarLib.getJniDir() }
|
|
288
|
+
configureProcessJniTask(it, project, appProject, projectExt, variantName, jniDirs, explodeTask)
|
|
187
289
|
}
|
|
188
290
|
|
|
189
291
|
variant.sources.jniLibs?.addGeneratedSourceDirectory(
|