概述
为什么要上传源码?
我们通过自定义插件的方式完成了上传一个组件到Maven仓库的功能,不过上传的aar或jar中并没有包含源码,如果依赖没有源码的组件出问题时不容易进行调试,所以我希望能够通过一个开关动态的打开/关闭源码的上传功能,如果对内发布就开放源码上传,如果对外发布就关闭。
在脚本中如何实现?
如果使用脚本开发的上传功能的话,可以通过如下的方式进行源码配置:
在Android模块
//上传脚本中新增task,类型为Jar
task androidSourceJar(type: Jar) {
// from project.android.sourceSets.main.java.sourceFiles //不包括Kotlin文件
from project.android.sourceSets.main.java.getSrcDirs() //包括Kotlin文件
archiveClassifier = 'sources'
}
afterEvaluate {
publishing {
publications {
//配置生成上传release节点的task
release(MavenPublication) {
from components.release
artifact androidSourceJar //设置artifact为上面定义的task
groupId = libGroup
artifactId = libArtifactId
version = libVersion
}
}
//....省略其他部分代码
}
}
通过上面的修改,无源码的1.0.1版本和有源码的1.0.2版本对比如下:
这样的话该组件的使用者在组件出现问题时,就可以进行静态代码分析或动态代码调试去解决问题了。
在Java模块
在Java模块中,与Android基本相似,只有细微的差别,如下:
// 上传脚本中新增task,类型为Jar
task sourceJar(type: Jar) {
from sourceSets.main.allSource
archiveClassifier = 'sources'
}
publishing {
publications {
//配置生成上传Java节点的task
mavenJava(MavenPublication) {
from components.java
artifact sourceJar //设置artifact为上面定义的task
groupId = libGroup
artifactId = libArtifactId
version = libVersion
}
}
// ....省略其他部分代码
}
通过上面的配置,就可以起到Java库的源码上传功能。
在插件中如何实现?
其实在插件中配置源码上传的功能与在脚本中配置完全一致,但区别的就是API上又些许不同。
首先为了能够动态的打开/关闭源码上传的功能,我们在_Publisher_参数中新增一个名为_withSource_的Boolean属性。
open class Publisher {
//...省略部分代码
//是否携带源码发布到maven仓库
var withSource: Boolean = false //此为新增
}
然后在自定义Task中做如下修改:
open class PublisherTask : DefaultTask() {
//是否完成执行任务
private var executeFinishFlag: AtomicBoolean = AtomicBoolean(false)
//检验状态是否通过
private var checkStatus = false
//自定义参数
private lateinit var publisher: Publisher
//生成的上传Maven仓库的task名称
private var currentPublishTaskName: String? = null
init {
group = "upload"
project.run {
publisher = extensions.getByName(Publisher.NAME) as Publisher
//动态为该模块引入上传插件
apply(hashMapOf<String, String>(Pair("plugin", "maven-publish")))
val publishing = project.extensions.getByType(PublishingExtension::class.java)
//当前模块是否为android模块,当前只支持android和java模块 非android即java
val isAndroidModule = project.plugins.hasPlugin("com.android.library")
val dynamicGenerateSourceTask = dynamicGenerateSourceTask(isAndroidModule)
afterEvaluate {
components.forEach {
if (isAndroidModule) {
//android只注册release的发布,如果需要all/debug或更多其他的可以自定义注册
if (it.name == "release") {
doRegisterTask(publishing, it.name, it, dynamicGenerateSourceTask)
}
} else {
//Java只注册java的发布,如果需要kotlin或更多其他的可以自定义注册
if (it.name == "java") {
doRegisterTask(publishing, it.name, it, dynamicGenerateSourceTask)
}
}
}
}
}
}
//注册上传maven仓库的名称
private fun doRegisterTask(
publishing: PublishingExtension,
name: String,
component: SoftwareComponent,
withSourceTask: Task?,
) {
currentPublishTaskName = "publish${name}PublicationToMavenRepository"
publishing.publications { publications ->
if (publications.findByName(name) == null) {
publications.create("$name",
MavenPublication::class.java) { publication ->
publication.groupId = publisher.libGroup
publication.artifactId = publisher.libArtifact
publication.version = publisher.libVersion
//如果支持携带源码,则配置 artifact 为源码task
withSourceTask?.let {
publication.artifact(it)
}
publication.from(component)
}
publishing.repositories { artifactRepositories ->
artifactRepositories.maven { mavenArtifactRepository ->
mavenArtifactRepository.url =
if (publisher.libVersion.endsWith("SNAPSHOT")) {
URI(publisher.repoSnapshot)
} else {
URI(publisher.repoRelease)
}
mavenArtifactRepository.credentials { credentials ->
credentials.username = publisher.repoAccount
credentials.password = publisher.repoPassword
}
}
}
}
}
}
/**
* 新增 动态生成源码task
* @param isAndroidModule 是否为android模块
*/
private fun dynamicGenerateSourceTask(isAndroidModule: Boolean): Task? {
if (!publisher.withSource) {
return null
}
// 其实taskName叫什么都无所谓,但是处于规范,还是这么命名吧
val taskName = if (isAndroidModule) {
"androidSourcesJar"
} else {
"sourcesJar"
}
//这个地方的api跟脚本中所有不同
val sourceSetFiles = if (isAndroidModule) {
//获取build.gradle中的android节点
val androidSet = project.extensions.getByName("android") as LibraryExtension
val sourceSet = androidSet.sourceSets
//获取android节点下的源码目录
sourceSet.findByName("main")?.java?.srcDirs
} else {
//获取java模块中的源码目录
val plugin = project.convention.getPlugin(JavaPluginConvention::class.java)
plugin.sourceSets.findByName("main")?.allSource
}
//查找或注册源码task
return project.tasks.findByName(taskName) ?: project.tasks.create(taskName,
Jar::class.java) {
it.from(sourceSetFiles)
it.archiveClassifier.set("sources")
}
}
@TaskAction
fun doTask() {
executeTask()
//开启线程守护,防止子线程任务还没执行完毕,task就已经结束了
while (!executeFinishFlag.get()) {
Thread.sleep(500)
}
}
private fun isWindows(): Boolean {
return System.getProperty("os.name").toLowerCase().contains("windows")
}
private fun executeTask() {
//1、对publisher配置的信息进行基础校验
//2、把publisher上传到服务器端,做版本重复性校验
checkStatus = requestCheckVersion()
//如果前两步都校验通过了,checkStatus设置为true
//解决可能发生的模块嵌套问题
val realTaskName =
project.projectDir.absolutePath
.removePrefix(project.rootDir.absolutePath)
.replace(File.separator, ":") + ":$currentPublishTaskName"
//适配windows环境
val exeCommand = if (isWindows()) {
"${project.rootDir}${File.separator}gradlew.bat"
} else {
"${project.rootDir}${File.separator}gradlew"
}
if (checkStatus) {
val out = ByteArrayOutputStream()
//通过命令行的方式进行调用上传maven的task
project.exec { exec ->
exec.standardOutput = out
exec.isIgnoreExitValue = true
exec.commandLine(
exeCommand,
realTaskName
)
}
val result = out.toString()
if (result.contains("BUILD SUCCESSFUL")) {
//上传maven仓库成功,上报到服务器
val isSuccess = requestUploadVersion()
if (isSuccess) {
//提示成功信息
} else {
//提示错误信息
}
executeFinish()
} else {
throw Exception("上传Maven仓库失败,请检查配置!")
}
}
}
private fun requestCheckVersion(): Boolean {
//TODO 上报服务器进行版本检查,这里直接模拟返回成功
return true
}
private fun requestUploadVersion(): Boolean {
//TODO 上报服务器进行版本更新操作,这里直接模拟返回成功
return true
}
/**
* 任务执行完毕
*/
private fun executeFinish() {
executeFinishFlag.set(true)
}
}
之后我们就可以在build.gradle中publisher节点下修改_withSource_的值来动态的开关源码支持了。
publisher {
//...省略其他配置
//发布人
publisher = "wangyumdao"
withSource = true //开启源码上传脑功能
}
最后
如果想要成为架构师或想突破20~30K薪资范畴,那就不要局限在编码,业务,要会选型、扩展,提升编程思维。此外,良好的职业规划也很重要,学习的习惯很重要,但是最重要的还是要能持之以恒,任何不能坚持落实的计划都是空谈。
如果你没有方向,这里给大家分享一套由阿里高级架构师编写的《Android八大模块进阶笔记》,帮大家将杂乱、零散、碎片化的知识进行体系化的整理,让大家系统而高效地掌握Android开发的各个知识点。
相对于我们平时看的碎片化内容,这份笔记的知识点更系统化,更容易理解和记忆,是严格按照知识体系编排的。
全套视频资料:
一、面试合集
二、源码解析合集
三、开源框架合集
欢迎大家一键三连支持,若需要文中资料,直接扫码免费领取↓↓↓
最后
以上就是愤怒星月为你收集整理的使用Gradle插件上传组件到Maven之源码上传的全部内容,希望文章能够帮你解决使用Gradle插件上传组件到Maven之源码上传所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复