Git Product home page Git Product logo

Comments (29)

trycatchx avatar trycatchx commented on July 28, 2024 2

@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 操作完毕之后,记得 把原有值 赋值回去 (不赋值回去也问题不大)
          
    }

from rocketx.

trycatchx avatar trycatchx commented on July 28, 2024

检查一下 是否配置 org.gradle.configureondemand = true ,关闭即可

from rocketx.

manza7014 avatar manza7014 commented on July 28, 2024

检查一下 是否配置 org.gradle.configureondemand = true ,关闭即可

没有配置这个

from rocketx.

trycatchx avatar trycatchx commented on July 28, 2024

目前使用gradle 版本是多少?

from rocketx.

manza7014 avatar manza7014 commented on July 28, 2024

目前使用gradle 版本是多少?

gradle版本:6.5
AGP版本:4.0.2

from rocketx.

trycatchx avatar trycatchx commented on July 28, 2024

目前一个项目可以正常运行,另一个不行是吧。问题是修改依赖的时机慢导致的。

你可以通过本地依赖:加入以下代码

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 主要是剔除了 并行的开关。定位是不是并行的原因导致的

from rocketx.

manza7014 avatar manza7014 commented on July 28, 2024

好的 ,我试下

from rocketx.

manza7014 avatar manza7014 commented on July 28, 2024

目前一个项目可以正常运行,另一个不行是吧。问题是修改依赖的时机慢导致的。

你可以通过本地依赖:加入以下代码

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还是同样的问题

from rocketx.

manza7014 avatar manza7014 commented on July 28, 2024

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));
            }
        }
    }

from rocketx.

trycatchx avatar trycatchx commented on July 28, 2024

@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));
            }
        }
    }

from rocketx.

trycatchx avatar trycatchx commented on July 28, 2024

@manza7014 可能我需要在 步骤2 反射 beforeContainerChange 这个变量为: ImmutableActionSet.empty(); ,然后再执行 :

   parentConfig.dependencies.removeAll { dependency ->
                    dependency is DefaultProjectDependency && dependency.name.equals(projectWapper.project.name)
                }

才能摆脱这个 异常。目前根据gradle 源码查看 去除检查 应该是可行:
image

from rocketx.

trycatchx avatar trycatchx commented on July 28, 2024

@manza7014 有兴趣帮忙提个 pr 吗?修改完毕之后并可以在你的工程检验一下效果。
如果没有时间的话,需要等待我们这边进行修复。

from rocketx.

manza7014 avatar manza7014 commented on July 28, 2024

之前还没提过pr 😳,我试试

from rocketx.

trycatchx avatar trycatchx commented on July 28, 2024

@manza7014 好的你可以先尝试一下,非常感谢

from rocketx.

manza7014 avatar manza7014 commented on July 28, 2024

@manza7014 好的你可以先尝试一下,非常感谢
客气,非常感谢作者这个RocketXPlugin,体验了,效果非常显著,👍

from rocketx.

trycatchx avatar trycatchx commented on July 28, 2024

@manza7014 请问有进展吗?

from rocketx.

manza7014 avatar manza7014 commented on July 28, 2024

还没。

parentConfig.dependencies 变量(它是一个 DefaultDomainObjectSet 对象,直接强转)

这里有问题,强转失败,提示类型不对。
parentConfig.dependencies类型应该是DefaultDependencySet。
是不是拿到DefaultDependencySet父类DelegatingDomainObjectSet中的私有属性backingSet(类型:DomainObjectSet,子类DefaultDomainObjectSet)才能修改?
试了试,调试过程中有点问题,今天忙着项目和年报总结就没搞了,想着明天再接着搞呢

调试有点艰难,我每次打了jar包才能试一下,暂时还没有把我的项目app module以及其他module放到RocketXPlugin项目中

from rocketx.

trycatchx avatar trycatchx commented on July 28, 2024

@manza7014 你可以把buildSrc 拷贝到你的项目中,然后直接剔除之前的 classpath 依赖,即可调试。

from rocketx.

trycatchx avatar trycatchx commented on July 28, 2024

还没。

parentConfig.dependencies 变量(它是一个 DefaultDomainObjectSet 对象,直接强转)

这里有问题,强转失败,提示类型不对。 parentConfig.dependencies类型应该是DefaultDependencySet。 是不是拿到DefaultDependencySet父类DelegatingDomainObjectSet中的私有属性backingSet(类型:DomainObjectSet,子类DefaultDomainObjectSet)才能修改? 试了试,调试过程中有点问题,今天忙着项目和年报总结就没搞了,想着明天再接着搞呢

调试有点艰难,我每次打了jar包才能试一下,暂时还没有把我的项目app module以及其他module放到RocketXPlugin项目中

是的,我看了一下确实是要通过拿到 DelegatingDomainObjectSet 的私有变量 backingSet (DefaultDomainObjectSet )

from rocketx.

manza7014 avatar manza7014 commented on July 28, 2024

@manza7014 你可以把buildSrc 拷贝到你的项目中,然后直接剔除之前的 classpath 依赖,即可调试。

好的

from rocketx.

trycatchx avatar trycatchx commented on July 28, 2024

@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
    }

from rocketx.

manza7014 avatar manza7014 commented on July 28, 2024

还没。

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

from rocketx.

trycatchx avatar trycatchx commented on July 28, 2024

你尝试用我的方法,我刚刚试了好像没问题哦

from rocketx.

manza7014 avatar manza7014 commented on July 28, 2024

@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:

from rocketx.

trycatchx avatar trycatchx commented on July 28, 2024

@manza7014 项目可以正常运行了是吧。那你按照这个代码提个 rq ,我合入。

from rocketx.

trycatchx avatar trycatchx commented on July 28, 2024

@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
    }

from rocketx.

manza7014 avatar manza7014 commented on July 28, 2024

@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文件也存在找不到的现象

from rocketx.

trycatchx avatar trycatchx commented on July 28, 2024

使用 classpath 'io.github.trycatchx:rocketx:1.0.12' 解决以上问题

from rocketx.

manza7014 avatar manza7014 commented on July 28, 2024

使用 classpath 'io.github.trycatchx:rocketx:1.0.12' 解决以上问题

好的

from rocketx.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.