Android Project Support - Fix manifest merge task being skipped
Issue
This plugin is not compatible with Android projects as the com.android.application gradle plugin adds tasks and steps up it's depencies on the project.afterEvaluate event as well. The existing logic on whether to apply rules or not is done by checking config.allDependencies.isEmpty(). This will be empty for the processDebugResources task for example. processReleaseResources is executed when calling the standard build task on an Android project.
Note that ./gradlew app:dependencies --configuration compile works fine, however tasks that do manifest merging fail. For example if we use mismatched versions of the com.android.support group in the main app's build.gradle but try to create an alignment rule to sync them it won't be applied to the processReleaseResources task and following error will throw:
Caused by: java.lang.RuntimeException: Manifest merger failed : Attribute meta-data#android.support.VERSION@value value=(26.0.0) from [com.android.support:appcompat-v7:26.0.0] AndroidManifest.xml:28:13-35
is also present at [com.android.support:support-v4:26.1.0] AndroidManifest.xml:28:13-35 value=(26.1.0).
Suggestion: add 'tools:replace="android:value"' to <meta-data> element at AndroidManifest.xml to override.
at com.android.builder.core.AndroidBuilder.mergeManifestsForApplication(AndroidBuilder.java:509)
at com.android.build.gradle.tasks.MergeManifests.doFullTaskAction(MergeManifests.java:150)
at com.android.build.gradle.internal.tasks.IncrementalTask.taskAction(IncrementalTask.java:106)
at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:73)
at org.gradle.api.internal.project.taskfactory.DefaultTaskClassInfoStore$IncrementalTaskAction.doExecute(DefaultTaskClassInfoStore.java:179)
at org.gradle.api.internal.project.taskfactory.DefaultTaskClassInfoStore$StandardTaskAction.execute(DefaultTaskClassInfoStore.java:135)
at org.gradle.api.internal.project.taskfactory.DefaultTaskClassInfoStore$StandardTaskAction.execute(DefaultTaskClassInfoStore.java:122)
at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter$1.run(ExecuteActionsTaskExecuter.java:121)
at org.gradle.internal.progress.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:336)
at org.gradle.internal.progress.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:328)
at org.gradle.internal.progress.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:199)
at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:110)
at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeAction(ExecuteActionsTaskExecuter.java:110)
at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:92)
... 28 more
The following test reproduces this issue. https://github.com/nebula-plugins/gradle-resolution-rules-plugin/pull/58/files#diff-c71d74290a4498733d4ad203fc844abaR393
Solutions
Solution 1
This is the one that is implemented in this pull.
Add a delay fallback on the project.gradle.taskGraph.afterTask when the rules are applied. In my testing I found that this is run after the Android plugin sets up the dependencies on it's tasks. Since this doesn't pass all existing tests with the delayed event on it's own we need to keep the project.onExecute event.
Solution 2
Another solution would be to simply remove the config.allDependencies.isEmpty() check. However it looks like this was put into place due to performance reasons.
TODO
- [x] Investigate if
project.onExecutecan be delayed soconfig.allDependenciesare fully resolved by any other gradle plugins. - [x] Add a unit test reproducing the issue
- [x] Fix failing
"Skipping dependency rules for configuration \':compile\' - No dependencies are configured"test
@DanielThomas I just completed this pull request, could you give it a review?
This plugin solves a number of common gradle dependency issues and would be a great help to Android developers if they could use it as well! Specifically around having group alignment for the Android Support Library and Google Play Services Library since each includes a number of modules per group.