Closed manza7014 closed 2 years ago
检查一下 是否配置 org.gradle.configureondemand = true ,关闭即可
检查一下 是否配置 org.gradle.configureondemand = true ,关闭即可
没有配置这个
目前使用gradle 版本是多少?
目前使用gradle 版本是多少?
gradle版本:6.5 AGP版本:4.0.2
目前一个项目可以正常运行,另一个不行是吧。问题是修改依赖的时机慢导致的。
你可以通过本地依赖:加入以下代码
buildscript {
repositories {
mavenCentral()
google()
}
dependencies {
def pluginDir = getProjectDir().getAbsolutePath() + File.separator + "zPlugin"
//编译加速插件,需要去插件市场搜索 RockectX 并开启可以加速项目编译速度
def rockectxFile = new File(pluginDir,"rockectx.jar")
classpath files(rockectxFile)
}
}
项目根目录创建一下 zPlugin 文件夹,解压下面的 zip 文件拿到本地的 jar 放进 zPlugin 文件夹 rockectx.jar.zip
上面的本地 jar 主要是剔除了 并行的开关。定位是不是并行的原因导致的
好的 ,我试下
目前一个项目可以正常运行,另一个不行是吧。问题是修改依赖的时机慢导致的。
你可以通过本地依赖:加入以下代码
buildscript { repositories { mavenCentral() google() } dependencies { def pluginDir = getProjectDir().getAbsolutePath() + File.separator + "zPlugin" //编译加速插件,需要去插件市场搜索 RockectX 并开启可以加速项目编译速度 def rockectxFile = new File(pluginDir,"rockectx.jar") classpath files(rockectxFile) } }
项目根目录创建一下 zPlugin 文件夹,解压下面的 zip 文件拿到本地的 jar 放进 zPlugin 文件夹 rockectx.jar.zip
上面的本地 jar 主要是剔除了 并行的开关。定位是不是并行的原因导致的
步骤: 1.添加rockectx本地依赖并同步 2.执行RocketXClean 3.首次run正常 4.再次run还是同样的问题
gradle这一块不太懂,github上扒了下这个 //The configuration has been used in a resolution, and it is an error for build logic to change any dependencies, // exclude rules or parent configurations (values that will affect the resolved graph).
private void preventIllegalMutation(MutationType type) {
// TODO: Deprecate and eventually prevent these mutations when already resolved
if (type == MutationType.DEPENDENCY_ATTRIBUTES) {
return;
}
InternalState resolvedState = currentResolveState.get().state;
if (resolvedState == ARTIFACTS_RESOLVED) {
// The public result for the configuration has been calculated.
// It is an error to change anything that would change the dependencies or artifacts
throw new InvalidUserDataException(String.format("Cannot change %s of dependency %s after it has been resolved.", type, getDisplayName()));
} else if (resolvedState == GRAPH_RESOLVED) {
// The task dependencies for the configuration have been calculated using Configuration.getBuildDependencies().
throw new InvalidUserDataException(String.format("Cannot change %s of dependency %s after task dependencies have been resolved", type, getDisplayName()));
} else if (observedState == GRAPH_RESOLVED || observedState == ARTIFACTS_RESOLVED) {
// The configuration has been used in a resolution, and it is an error for build logic to change any dependencies,
// exclude rules or parent configurations (values that will affect the resolved graph).
if (type != MutationType.STRATEGY) {
String extraMessage = insideBeforeResolve ? " Use 'defaultDependencies' instead of 'beforeResolve' to specify default dependencies for a configuration." : "";
throw new InvalidUserDataException(String.format("Cannot change %s of dependency %s after it has been included in dependency resolution.%s", type, getDisplayName(), extraMessage));
}
}
}
@manza7014 好的,那应该和这个没有关系。应该还是兼容性问题。目前我排查到的位置是: //步骤1:入口 DefaultDomainObjectCollection.IteratorImpl.class
public void remove() {
//..
DefaultDomainObjectCollection.this.assertMutableCollectionContents(); // 此处报错
this.iterator.remove();
//..
}
//步骤2:调用 DefaultDomainObjectSet.java
protected void assertMutableCollectionContents() {
this.beforeContainerChange.execute((Object)null);
}
//步骤3: beforeContainerChange 是 下面的 action
private static Action<Void> validateMutationType(final MutationValidator mutationValidator, final MutationType type) {
return new Action<Void>() {
public void execute(Void arg) {
mutationValidator.validateMutation(type); //检查都否修改依赖
}
};
}
//步骤4 :报错位置:
public void validateMutation(MutationType type) {
this.preventIllegalMutation(type);
this.markAsModified(type);
this.notifyChildren(type);
}
private void preventIllegalMutation(MutationType type) {
if (type != MutationType.DEPENDENCY_ATTRIBUTES) {
if (this.resolvedState == InternalState.ARTIFACTS_RESOLVED) {
throw new InvalidUserDataException(String.format("Cannot change %s of dependency %s after it has been resolved.", type, this.getDisplayName()));
} else if (this.resolvedState == InternalState.GRAPH_RESOLVED) {
throw new InvalidUserDataException(String.format("Cannot change %s of dependency %s after task dependencies have been resolved", type, this.getDisplayName()));
} else if ((this.observedState == InternalState.GRAPH_RESOLVED || this.observedState == InternalState.ARTIFACTS_RESOLVED) && type != MutationType.STRATEGY) {
String extraMessage = this.insideBeforeResolve ? " Use 'defaultDependencies' instead of 'beforeResolve' to specify default dependencies for a configuration." : "";
throw new InvalidUserDataException(String.format("Cannot change %s of dependency %s after it has been included in dependency resolution.%s", type, this.getDisplayName(), extraMessage));
}
}
}
@manza7014 可能我需要在 步骤2 反射 beforeContainerChange 这个变量为: ImmutableActionSet.empty(); ,然后再执行 :
parentConfig.dependencies.removeAll { dependency ->
dependency is DefaultProjectDependency && dependency.name.equals(projectWapper.project.name)
}
才能摆脱这个 异常。目前根据gradle 源码查看 去除检查 应该是可行:
@manza7014 有兴趣帮忙提个 pr 吗?修改完毕之后并可以在你的工程检验一下效果。 如果没有时间的话,需要等待我们这边进行修复。
之前还没提过pr :flushed:,我试试
@manza7014 好的你可以先尝试一下,非常感谢
@manza7014 好的你可以先尝试一下,非常感谢 客气,非常感谢作者这个RocketXPlugin,体验了,效果非常显著,👍
@manza7014
好的,关键的提示:
修改 DependenciesHelper.kt 类下面的:
fun modifyDependencies(projectWapper: ChildProjectDependencies) {
/**
*这里加入 反射 parentConfig.dependencies 变量(它是一个 DefaultDomainObjectSet 对象,直接强转)
* 并拿到 beforeContainerChange 变量赋值为 ImmutableActionSet.empty() (记得把变量的原有值保存)
*/
// 剔除原有的依赖
parentConfig.dependencies.removeAll { dependency ->
dependency is DefaultProjectDependency && dependency.name.equals(projectWapper.project.name)
}
// removeAll 操作完毕之后,记得 把原有值 赋值回去 (不赋值回去也问题不大)
}
@manza7014 请问有进展吗?
还没。
parentConfig.dependencies 变量(它是一个 DefaultDomainObjectSet 对象,直接强转)
这里有问题,强转失败,提示类型不对。 parentConfig.dependencies类型应该是DefaultDependencySet。 是不是拿到DefaultDependencySet父类DelegatingDomainObjectSet中的私有属性backingSet(类型:DomainObjectSet,子类DefaultDomainObjectSet)才能修改? 试了试,调试过程中有点问题,今天忙着项目和年报总结就没搞了,想着明天再接着搞呢
调试有点艰难,我每次打了jar包才能试一下,暂时还没有把我的项目app module以及其他module放到RocketXPlugin项目中
@manza7014 你可以把buildSrc 拷贝到你的项目中,然后直接剔除之前的 classpath 依赖,即可调试。
还没。
parentConfig.dependencies 变量(它是一个 DefaultDomainObjectSet 对象,直接强转)
这里有问题,强转失败,提示类型不对。 parentConfig.dependencies类型应该是DefaultDependencySet。 是不是拿到DefaultDependencySet父类DelegatingDomainObjectSet中的私有属性backingSet(类型:DomainObjectSet,子类DefaultDomainObjectSet)才能修改? 试了试,调试过程中有点问题,今天忙着项目和年报总结就没搞了,想着明天再接着搞呢
调试有点艰难,我每次打了jar包才能试一下,暂时还没有把我的项目app module以及其他module放到RocketXPlugin项目中
是的,我看了一下确实是要通过拿到 DelegatingDomainObjectSet 的私有变量 backingSet (DefaultDomainObjectSet )
@manza7014 你可以把buildSrc 拷贝到你的项目中,然后直接剔除之前的 classpath 依赖,即可调试。
好的
@manza7014 我编写了 setBeforeContainerChangeToEmpty 方法,你有空在你的 工程试试。
fun modifyDependencies(projectWapper: ChildProjectDependencies) {
//..
setBeforeContainerChangeToEmpty(parentConfig.dependencies)
// 剔除原有的依赖
parentConfig.dependencies.removeAll { dependency ->
dependency is DefaultProjectDependency && dependency.name.equals(projectWapper.project.name)
}
// ..
}
fun setBeforeContainerChangeToEmpty(dependency :DependencySet):ImmutableActionSet<Any>? {
var ret : ImmutableActionSet<Any>? = null
try {
val fBackingSet = DelegatingDomainObjectSet::class.java.getDeclaredField("backingSet")
fBackingSet.isAccessible = true
val domainObjectSet = fBackingSet.get(dependency)
val fBeforeContainerChange = DefaultDomainObjectSet::class.java.getDeclaredField("beforeContainerChange")
fBeforeContainerChange.isAccessible = true
ret = fBeforeContainerChange.get(domainObjectSet) as? ImmutableActionSet<Any>
fBeforeContainerChange.set(domainObjectSet, ImmutableActionSet.empty<Any>())
}catch (ignore:Exception) {
}
return ret
}
还没。
parentConfig.dependencies 变量(它是一个 DefaultDomainObjectSet 对象,直接强转)
这里有问题,强转失败,提示类型不对。 parentConfig.dependencies类型应该是DefaultDependencySet。 是不是拿到DefaultDependencySet父类DelegatingDomainObjectSet中的私有属性backingSet(类型:DomainObjectSet,子类DefaultDomainObjectSet)才能修改? 试了试,调试过程中有点问题,今天忙着项目和年报总结就没搞了,想着明天再接着搞呢 调试有点艰难,我每次打了jar包才能试一下,暂时还没有把我的项目app module以及其他module放到RocketXPlugin项目中
是的,我看了一下确实是要通过拿到 DelegatingDomainObjectSet 的私有变量 backingSet (DefaultDomainObjectSet )
关键是拿不到:no_mouth:
Can not set final org.gradle.api.DomainObjectSet field org.gradle.api.internal.DelegatingDomainObjectSet.backingSet to java.lang.reflect.Field
你尝试用我的方法,我刚刚试了好像没问题哦
@manza7014 我编写了 setBeforeContainerChangeToEmpty 方法,你有空在你的 工程试试。
fun modifyDependencies(projectWapper: ChildProjectDependencies) { //.. setBeforeContainerChangeToEmpty(parentConfig.dependencies) // 剔除原有的依赖 parentConfig.dependencies.removeAll { dependency -> dependency is DefaultProjectDependency && dependency.name.equals(projectWapper.project.name) } // .. } fun setBeforeContainerChangeToEmpty(dependency :DependencySet):ImmutableActionSet<Any>? { var ret : ImmutableActionSet<Any>? = null try { val fBackingSet = DelegatingDomainObjectSet::class.java.getDeclaredField("backingSet") fBackingSet.isAccessible = true val domainObjectSet = fBackingSet.get(dependency) val fBeforeContainerChange = DefaultDomainObjectSet::class.java.getDeclaredField("beforeContainerChange") fBeforeContainerChange.isAccessible = true ret = fBeforeContainerChange.get(domainObjectSet) as? ImmutableActionSet<Any> fBeforeContainerChange.set(domainObjectSet, ImmutableActionSet.empty<Any>()) }catch (ignore:Exception) { } return ret }
是的,可以了,多谢:+1:
@manza7014 项目可以正常运行了是吧。那你按照这个代码提个 rq ,我合入。
@manza7014 可以尝试一下修改 :AppProjectDependencies.kt 以下代码,我把修改依赖的时机提前一点。
init {
project.afterEvaluate {
val allProject = mutableSetOf<Project>()
project.rootProject.allprojects.forEach {
allProject.add(it)
}
// project.gradle.projectsEvaluated {
// // 调整依赖时机
// if (isFirst) {
// isFirst = false
// resolveDenpendency()
// }
// }
project.gradle.afterProject {
allProject.remove(it)
if (canbeResolveDenpendency(allProject)) {
// 调整依赖时机
if (isFirst) {
isFirst = false
resolveDenpendency()
}
}
}
}
}
fun canbeResolveDenpendency(set: MutableSet<Project>): Boolean {
var ret = true
set.forEach {
if (it != project.rootProject && it.childProjects.size <= 0
&& (hasAndroidPlugin(it) || hasJavaPlugin(it))) {
ret = false
return@forEach
}
}
return ret
}
@manza7014 可以尝试一下修改 :AppProjectDependencies.kt 以下代码,我把修改依赖的时机提前一点。
init { project.afterEvaluate { val allProject = mutableSetOf<Project>() project.rootProject.allprojects.forEach { allProject.add(it) } // project.gradle.projectsEvaluated { // // 调整依赖时机 // if (isFirst) { // isFirst = false // resolveDenpendency() // } // } project.gradle.afterProject { allProject.remove(it) if (canbeResolveDenpendency(allProject)) { // 调整依赖时机 if (isFirst) { isFirst = false resolveDenpendency() } } } } } fun canbeResolveDenpendency(set: MutableSet<Project>): Boolean { var ret = true set.forEach { if (it != project.rootProject && it.childProjects.size <= 0 && (hasAndroidPlugin(it) || hasJavaPlugin(it))) { ret = false return@forEach } } return ret }
* Exception is: org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':app:compileTDCFDebugJavaWithJavac'. at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.lambda$executeIfValid$1(ExecuteActionsTaskExecuter.java:207) at org.gradle.internal.Try$Failure.ifSuccessfulOrElse(Try.java:263) at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeIfValid(ExecuteActionsTaskExecuter.java:205) at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:186) at org.gradle.api.internal.tasks.execution.CleanupStaleOutputsExecuter.execute(CleanupStaleOutputsExecuter.java:114) at org.gradle.api.internal.tasks.execution.FinalizePropertiesTaskExecuter.execute(FinalizePropertiesTaskExecuter.java:46) at org.gradle.api.internal.tasks.execution.ResolveTaskExecutionModeExecuter.execute(ResolveTaskExecutionModeExecuter.java:62) at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:57) at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:56) at org.gradle.api.internal.tasks.execution.CatchExceptionTaskExecuter.execute(CatchExceptionTaskExecuter.java:36) at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.executeTask(EventFiringTaskExecuter.java:77) at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.call(EventFiringTaskExecuter.java:55) at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.call(EventFiringTaskExecuter.java:52) at org.gradle.internal.operations.DefaultBuildOperationExecutor$CallableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:409) at org.gradle.internal.operations.DefaultBuildOperationExecutor$CallableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:399) at org.gradle.internal.operations.DefaultBuildOperationExecutor$1.execute(DefaultBuildOperationExecutor.java:157) at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:242) at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:150) at org.gradle.internal.operations.DefaultBuildOperationExecutor.call(DefaultBuildOperationExecutor.java:94) at org.gradle.internal.operations.DelegatingBuildOperationExecutor.call(DelegatingBuildOperationExecutor.java:36) at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter.execute(EventFiringTaskExecuter.java:52) at org.gradle.execution.plan.LocalTaskNodeExecutor.execute(LocalTaskNodeExecutor.java:41) at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:356) at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:343) at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:336) at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:322) at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.lambda$run$0(DefaultPlanExecutor.java:127) at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.execute(DefaultPlanExecutor.java:191) at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.executeNextNode(DefaultPlanExecutor.java:182) at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.run(DefaultPlanExecutor.java:124) at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64) at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:48) at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:56) Caused by: org.gradle.api.internal.tasks.compile.CompilationFailedException: Compilation failed; see the compiler error output for details
步骤:把昨天的修改: setBeforeContainerChangeToEmpty去掉了,只做了上面你说的这个修改然后报错
显示:
错误: 程序包com.yskj.applypermission不存在
import com.yskj.applypermission.PermissionChecker;
app module中某个文件引用的permission module中的类文件不存在,其他module文件也存在找不到的现象
使用 classpath 'io.github.trycatchx:rocketx:1.0.12' 解决以上问题
使用 classpath 'io.github.trycatchx:rocketx:1.0.12' 解决以上问题
好的
步骤 1.首次运行正常 2.再次运行报错,日志如下 另:在另外一个项目上运行正常 @trycatchx