栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 系统运维 > 运维 > Linux

Android自动化打包失败所引出的Gradle执行顺序问题

Linux 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Android自动化打包失败所引出的Gradle执行顺序问题

场景

前段时间在搞Android自动化打包的事情。
我们的library是需要提供给其他团队使用的,所以在使用Jenkins自动化打包过程中,需要将library打包成aar并发布到maven仓库上。

所以对于我们gradle,就需要先将myLibrary打包成aar并发布到maven仓库上,再清空app的缓存,并将app打包成apk
对应gradle命令如下

gradlew myLibrary:clean myLibrary:uploadArchives app:clean app:assembleRelease

按原先的理解来说,gradle在执行命令的时候,会顺序执行,会先执行myLibrary:clean,再执行myLibrary:uploadArchives,然后执行app:clean,最后执行app:assembleRelease
在项目的依赖没有问题的时候,确实是没有问题的。
但是,由于我们是先上传myLibrary到maven仓库,然后app再去获取最新的myLibrary 的 maven依赖,这个过程中,当myLibrary上传maven 仓库成功后,会自动将myLibrary的maven依赖的版本号+1。

这个具体看我的另一篇博客 Android Maven仓库搭建 - 实现自动化打包自动拉取最新maven依赖

这个时候就出问题了,会发现直接就报找不到依赖的错误了

FAILURE: Build failed with an exception.

* What went wrong:
Could not determine the dependencies of task ':app:lintVitalRelease'.
> Could not resolve all artifacts for configuration ':app:debugCompileClasspath'.
   > Could not find com.heiko.test:myLibrary:2.0.99.
     Required by:
         project :app

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

这是为什么呢 ?
按gradle执行命令的顺序,按之前的理解是会先执行myLibrary:uploadArchives将aar上传到maven仓库,这时候再去执行app:assembleRelease 应该已经可以取到最新的依赖了才对呀 ?

测试

百思不得其解之际,写了一个gradle的demo,对task的相关方法进行了打印

task myTask1 {
    configure {
        println("myTask1:configure")
    }
    doFirst {
        println("myTask1:doFirst")
    }
    doLast {
        println("myTask1:doLast")
    }
}

task myTask2 {
    configure {
        println("myTask2:configure")
    }
    doFirst {
        println("myTask2:doFirst")
    }
    doLast {
        println("myTask2:doLast")
    }
}

task myTask3 {
    configure {
        println("myTask3:configure")
    }
    doFirst {
        println("myTask3:doFirst")
    }
    doLast {
        println("myTask3:doLast")
    }
}

然后我们使用命令行来执行myTask1、 myTask2 、myTask3

gradlew myTask1 myTask2 myTask3

可以看到执行结果

Starting a Gradle Daemon, 1 busy Daemon could not be reused, use --status for details

> Configure project :
myTask1:configure
myTask2:configure
myTask3:configure

> Task :myTask1
myTask1:doFirst
myTask1:doLast

> Task :myTask2
myTask2:doFirst
myTask2:doLast

> Task :myTask3
myTask3:doFirst
myTask3:doLast

BUILD SUCCESSFUL in 5s
3 actionable tasks: 3 executed

这时,可以发现gradle会先去执行所有task的configure方法,再去真正依次执行各个task

gradle的生命周期

这就引申出gradle的生命周期了

  • initialization:初始化阶段
    • 执行工程的setting.gradle文件
    • 解析整个工程下的所有Project,构建所有的Project对应的project对象
  • Configuration:配置阶段
    • 解析所有的Projects对象中的task,构建好所有task的依赖图 (执行的先后顺序)
  • Excution:执行阶段
    • 执行具体的task及依赖task (先执行目标Task依赖的Task,再执行目标Task)

这里说明一下
Project : 每个build.gradle 就对应一个project,Project里可以有多个Task
Task : 主要的工作执行者,每个Task由多个Action组成

我们在settings.gradle中打印一句日志

再执行一下gradlew myTask1 myTask2 myTask3,可以看到执行顺序

解决方案

知道了这个概念我们就可以知道,所有gradle task在执行之前,都会先执行所有task的configure,进行配置。
所以,我们必须要把上面的这个gradle命令进行拆分。

步骤一 : 清空myLibrary的缓存,并将myLibrary打包成aar并发布到maven仓库上

gradlew myLibrary:clean myLibrary:uploadArchives

步骤二 : 清空app的缓存,并将app打包成apk

gradlew app:clean app:assembleRelease

这样子执行,就不存在最初说的那个问题了。
Jenkins是支持创建多个gradle执行命令的,所以是不需要把gradlew命令杂糅在一起,是可以拆分开来分步骤执行的,这个也是我们前期踩坑的地方。

重新配置好Jenkins,就可以继续搞我们的自动化打包了,详见 Android Maven仓库搭建 - 实现自动化打包自动拉取最新maven依赖

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/894333.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号