#0 升级1.0.10版本

This commit is contained in:
LinYYY
2022-11-16 17:22:16 +08:00
parent ef1cb59408
commit 09405c0202
35 changed files with 2002 additions and 379 deletions

View File

@@ -37,7 +37,7 @@ dependencies {
*/
implementation component(':library')
implementation component(':libraryKotlin') //需要如此申明才能享受编译时依赖sdk打包时包括sdk及实现
implementation component(':pins') //等价 project(':libraryWithoutPlugin')
// implementation component(':pins') //等价 project(':libraryWithoutPlugin')
implementation component(':libraryWithoutPlugin') //等价 project(':libraryWithoutPlugin')
}

View File

@@ -1,8 +1,8 @@
apply from: "./gradleScript/config.gradle"
buildscript {
ext.kotlin_version = '1.3.50'
ext.component_version = '1.0.8'
ext.kotlin_version = '1.6.21'
ext.component_version = '1.0.10'
repositories {
google()
@@ -10,11 +10,11 @@ buildscript {
maven { url 'https://dl.bintray.com/yummylau/maven' }
}
dependencies {
classpath 'com.android.tools.build:gradle:3.1.0'
classpath "com.effective.plugins:component:$component_version"
classpath 'com.android.tools.build:gradle:4.1.0'
// classpath "com.effective.plugins:component:$component_version"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
//调试需要
// classpath "com.effective.plugins:component-plugin"
classpath "com.effective.plugins:component-plugin"
//发布需要
classpath 'com.novoda:bintray-release:0.9.1'

View File

@@ -1,26 +1,37 @@
apply plugin: 'groovy'
apply plugin: 'maven'
apply plugin: 'com.novoda.bintray-release'
apply plugin: 'maven-publish'
group = 'com.effective.plugins'
archivesBaseName = 'component'
version = '1.0.8'
version = '1.0.10'
//设置本地发布路径
uploadArchives {
repositories {
mavenDeployer {
/**配置Maven部署器将工件上传到本地目录这里是放到与该项目同级目录的repo目录下*/
repository(url: uri('../repo'))
// Because the components are created only during the afterEvaluate phase, you must
// configure your publications using the afterEvaluate() lifecycle method.
afterEvaluate {
publishing {
publications {
release(MavenPublication) {
from components.java
groupId = group
artifactId = archivesBaseName
version = version
}
}
repositories {
maven {
url = "../repo"
}
}
}
}
dependencies {
implementation gradleApi()
implementation localGroovy()
implementation 'com.android.tools.build:gradle:3.1.0'
implementation 'org.jetbrains.kotlin:kotlin-compiler-embeddable:1.3.70'
implementation 'com.android.tools.build:gradle:4.1.0'
implementation 'org.jetbrains.kotlin:kotlin-compiler-embeddable:1.6.21'
implementation 'org.ow2.asm:asm:7.1'
implementation 'org.ow2.asm:asm-commons:7.1'
implementation 'org.ow2.asm:asm-util:7.1'
@@ -43,13 +54,13 @@ repositories {
}
publish {
userOrg = 'yummylau'
groupId = 'com.effective.plugins'
artifactId = 'component'
publishVersion = '1.0.8'
desc = 'Android component plugin'
website = 'https://github.com/YummyLau/ComponentPlugin'
}
//publish {
// userOrg = 'yummylau'
// groupId = 'com.effective.plugins'
// artifactId = 'component'
// publishVersion = '1.0.8'
// desc = 'Android component plugin'
// website = 'https://github.com/YummyLau/ComponentPlugin'
//}

View File

@@ -1,12 +1,25 @@
package com.plugin.component
import com.plugin.component.extension.ComponentExtension
import com.plugin.component.log.Logger
import com.plugin.component.plugin.AbsPlugin
import com.plugin.component.plugin.DebugPlugin
import com.plugin.component.plugin.PinPlugin
import com.plugin.component.plugin.SdkPlugin
import com.plugin.component.utils.ProjectUtil
import org.gradle.BuildListener
import org.gradle.api.Action
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.internal.dispatch.MethodInvocation
import org.gradle.internal.event.BroadcastDispatch
import org.gradle.internal.event.ListenerBroadcast
import org.gradle.invocation.DefaultGradle
import org.gradle.listener.ClosureBackedMethodInvocationDispatch
import java.lang.reflect.Field
import java.lang.reflect.Method
import java.lang.reflect.Modifier
/**
* ./gradlew --no-daemon ComponentPlugin -Dorg.gradle.debug=true
@@ -25,20 +38,39 @@ class ComponentPlugin extends AbsPlugin implements Plugin<Project> {
private AbsPlugin debug = new DebugPlugin()
private AbsPlugin pins = new PinPlugin()
private ComponentExtension componentExtension
private boolean isFirst = true
static Project androidProject
static Project rootProject
@Override
void apply(Project project) {
if (project == project.rootProject) {
rootProject = project.rootProject
componentExtension = project.getExtensions().create(Constants.COMPONENT, ComponentExtension, project)
initExtension(componentExtension)
Runtimes.initRuntimeConfigurationOnEvaluate(project)
project.afterEvaluate {
androidProject = ProjectUtil.getProject(project, componentExtension.appModule)
Runtimes.initRuntimeConfigurationAfterEvaluate(project, componentExtension)
Runtimes.hookAfterApplyingAndroidPlugin(project, this)
Runtimes.hookAfterApplyingAndroidPlugin(project, androidProject, this)
Runtimes.injectComponentPlugin(project)
Runtimes.registerPublishTask(project)
}
// def projectsEvaluatedList = Runtimes.hookProjectsEvaluatedAction(project)
project.gradle.projectsEvaluated {
afterAllEvaluate(project)
if (isFirst) {
isFirst = false
//修改引用
afterAllEvaluate(project)
// //后执行移除的监听主要调整执行顺序重依赖才能生效和不报错可能有AGP 版本兼容问题)
// Class clazz = Class.forName("org.gradle.api.invocation.Gradle")
// Method method = clazz.getDeclaredMethod("projectsEvaluated", Action.class)
// Object[] objects = [it]
// MethodInvocation mMethodInvocation = new MethodInvocation(method, objects)
// projectsEvaluatedList.forEach {
// it.dispatch(mMethodInvocation)
// }
}
}
} else {
evaluateBeforeAndroidPlugin(project)
@@ -73,9 +105,9 @@ class ComponentPlugin extends AbsPlugin implements Plugin<Project> {
}
@Override
void afterEvaluateAfterAndroidPlugin(Project project) {
sdk.afterEvaluateAfterAndroidPlugin(project)
debug.afterEvaluateAfterAndroidPlugin(project)
void afterEvaluateAfterAndroidPlugin(Project project, Project androidProject) {
sdk.afterEvaluateAfterAndroidPlugin(project, androidProject)
debug.afterEvaluateAfterAndroidPlugin(project, androidProject)
}
@Override

View File

@@ -27,16 +27,18 @@ class Constants {
public static String PLUGIN_CACHE = "scan_cache"
//file
public static String DEFAULT_MAIN_MODULE_NAME = "app"
public static String DEFAULT_MAIN_MODULE_NAME = "main"
//默认工程主项目名称
public static String SDK_DIR = '.gradle/component/sdk'
//sdk存放目录
public static String IMPL_DIR = 'build/component/impl'
public static String IMPL_DIR = '.gradle/component/impl'
//impl存放目录
public static String BUILD_SDK_DIR = 'build/component/sdk'
//生成的sdk文件的build目录
public static String BUILD_IMPL_DIR = 'build/component/impl'
//生成的impl的build目录
//发布日志路径
public static String PUBLISH_LOG_FILE = "componentpublish.log"
public static String BUILD_SOURCE_DIR = 'source'
public static String BUILD_CLASSES_DIR = 'classes'
public static String BUILD_OUTPUT_DIR = 'outputs'
@@ -52,4 +54,29 @@ class Constants {
public static String ASSETS_PATH = "src/main/assets"
public static String JNILIBS_PATH = "src/main/jniLibs"
public static String MANIFEST = "src/main/AndroidManifest.xml"
//git hooks
public static String HOOKS_DIR = "hooks"
public static String HOOKS_CONTENT =
"""#!/bin/sh
remote="\$1"
url="\$2"
branch=\$(git symbolic-ref --short -q HEAD)
strB="BUILD SUCCESSFUL"
echo "current branch:\$branch"
tempLog=/tmp/\$(date +%s).log && touch \$tempLog
if [[ "\$branch" =~ (^develop\$)|(^release/*) ]]; then
./gradlew ComponentPublishDebug | tee \$tempLog
result=\$(cat \$tempLog)
checkStr=\$(echo "\$result" | grep "\${strB}")
if [[ "\$checkStr" != "" ]]; then
exit 0;
else
exit 1;
fi
fi
exit 0;
"""
}

View File

@@ -24,7 +24,7 @@ public class FlatDirModuleComponentSelector implements ModuleComponentSelector {
private FlatDirModuleComponentSelector(ModuleIdentifier module, ImmutableVersionConstraint version, ImmutableAttributes attributes, List<Capability> requestedCapabilities) {
assert module != null: "module cannot be null"
assert version != null: "version cannot be null"
assert version != null: "sdkVersion cannot be null"
assert attributes != null: "attributes cannot be null"

View File

@@ -21,13 +21,29 @@ import com.plugin.component.extension.option.sdk.SdkOption
import com.plugin.component.log.Logger
import com.plugin.component.log.MutLineLog
import com.plugin.component.plugin.AbsPlugin
import com.plugin.component.task.ComponentPublishTask
import com.plugin.component.transform.ComponentTransform
import com.plugin.component.utils.FileUtil
import com.plugin.component.utils.GitUtil
import com.plugin.component.utils.JarUtil
import com.plugin.component.utils.ProjectUtil
import com.plugin.component.utils.PublicationUtil
import org.gradle.BuildListener
import org.gradle.api.Action
import org.gradle.api.GradleException
import org.gradle.api.Project
import org.gradle.api.Task
import org.gradle.api.plugins.AppliedPlugin
import org.gradle.api.tasks.TaskExecutionException
import org.gradle.api.tasks.TaskProvider
import org.gradle.internal.event.BroadcastDispatch
import org.gradle.internal.event.ListenerBroadcast
import org.gradle.invocation.DefaultGradle
import org.gradle.listener.ClosureBackedMethodInvocationDispatch
import java.lang.reflect.Field
import java.lang.reflect.Modifier
import java.util.concurrent.ConcurrentHashMap
class Runtimes {
@@ -36,7 +52,7 @@ class Runtimes {
//impl 发布信息
private static Map<String, PublicationOption> sImplPublicationMap = new HashMap<>()
//模块信息
private static Map<String, ProjectInfo> sProjectInfoMap = new HashMap<>()
private static Map<String, ProjectInfo> sProjectInfoMap = new ConcurrentHashMap<>()
private static Map<String, PinConfiguration> sPinConfigurations = new HashMap<>()
@@ -71,6 +87,7 @@ class Runtimes {
sImplDir.mkdirs()
}
}
initGitHooks(root)
root.repositories {
flatDir {
@@ -79,6 +96,7 @@ class Runtimes {
}
}
PublicationManager.getInstance().loadManifest(root)
Logger.buildOutput("load Manifest")
PublicationDependenciesOption.metaClass.component { String value ->
return Constants.COMPONENT_PRE + value
}
@@ -94,6 +112,25 @@ class Runtimes {
)
}
private static void initGitHooks(Project root) {
if (GitUtil.gitExist) {
File hooksDir = new File(root.projectDir, Constants.HOOKS_DIR)
if (!hooksDir.exists()) {
hooksDir.mkdirs()
}
File prePushHook = new File(hooksDir, "pre-push")
if (!prePushHook.exists()) {
prePushHook.createNewFile()
FileOutputStream fos = new FileOutputStream(prePushHook)
OutputStreamWriter osw = new OutputStreamWriter(fos, "UTF-8")
osw.write(Constants.HOOKS_CONTENT)
osw.flush()
osw.close()
}
FileUtil.shell("git config core.hooksPath ${hooksDir.absolutePath} && chmod 700 ${hooksDir.absolutePath}/*")
}
}
static initRuntimeConfigurationAfterEvaluate(Project root, ComponentExtension componentExtension) {
sExtension = componentExtension
sDebugOption = sExtension.debugOption
@@ -127,6 +164,23 @@ class Runtimes {
}
}
//添加flat路径
root.allprojects.each {
if (it == root) return
if (!shouldApplyComponentPlugin(it)) return
Project childProject = it
ProjectInfo projectInfo = new ProjectInfo(childProject)
addProjectInfo(childProject.name, projectInfo)
childProject.repositories {
flatDir {
dirs sSdkDir.absolutePath
dirs sImplDir.absolutePath
mutLineLog.build4("* " + childProject.name + " add flatDir Dir[" + sSdkDir.absolutePath + "]")
mutLineLog.build4("* " + childProject.name + " add flatDir Dir[" + sImplDir.absolutePath + "]")
}
}
}
mutLineLog.build4("* 初始化 pins main 目录")
List<String> topSort = PublicationManager.getInstance().dependencyGraph.topSort()
Collections.reverse(topSort)
@@ -136,44 +190,42 @@ class Runtimes {
return
}
Project childProject = root.findProject(publication.project)
ProjectInfo projectInfo = getProjectInfo(childProject.name)
if (projectInfo != null && projectInfo.isPublish || sSdkOption.isPublishMode) {
publication.sdkNeedPublish = true
publication.impNeedPublish = true
publication.forceUseLocal(true)
//发布时删除本地文件,确保不会使用本地文件
File targetSdk = new File(sSdkDir, PublicationUtil.getJarName(publication))
if (targetSdk.exists()) {
targetSdk.delete()
}
File targetImpl = new File(sImplDir, PublicationUtil.getAarName(publication))
if (targetImpl.exists()) {
targetImpl.delete()
}
}
PublicationUtil.filterPublicationDependencies(publication)
if (publication.version != null) {
JarUtil.handleMavenJar(childProject, publication)
if (!publication.forceLocal && publication.sdkVersion != null) {
mutLineLog.build4("* " + JarUtil.handleMavenJar(childProject, publication))
} else {
mutLineLog.build4("* " + JarUtil.handleLocalJar(childProject, publication))
}
PublicationManager.getInstance().hitPublication(publication)
}
//添加flat路径
root.allprojects.each {
if (it == root) return
if (!shouldApplyComponentPlugin(it)) return
Project childProject = it
childProject.repositories {
flatDir {
dirs sSdkDir.absolutePath
mutLineLog.build4("* " + childProject.name + "add flatDir Dir[" + sSdkDir.absolutePath + "]")
dirs sImplDir.absolutePath
}
}
}
Logger.buildBlockLog("预处理插件", mutLineLog)
}
static hookAfterApplyingAndroidPlugin(Project root, AbsPlugin... plugins) {
static hookAfterApplyingAndroidPlugin(Project root, Project androidProject, AbsPlugin... plugins) {
MutLineLog mutLineLog = new MutLineLog()
root.allprojects.each {
if (it == root) return
if (!shouldApplyComponentPlugin(it)) return
Project childProject = it
ProjectInfo projectInfo = new ProjectInfo(childProject)
addProjectInfo(childProject.name, projectInfo)
ProjectInfo projectInfo = getProjectInfo(it.name)
mutLineLog.build4("* " + childProject.name)
@@ -183,32 +235,10 @@ class Runtimes {
mutLineLog.build4(" taskNames = " + projectInfo.taskNames)
mutLineLog.build4(" isSyncTask = " + projectInfo.isSync())
mutLineLog.build4(" isAssemble = " + projectInfo.isAssemble)
mutLineLog.build4(" isPublish = " + projectInfo.isPublish)
mutLineLog.build4(" isDebug = " + projectInfo.isDebug)
//
// childProject.plugins.all {
// Class extensionClass
// if (it instanceof AppPlugin) {
// extensionClass = AppExtension
// } else if (it instanceof LibraryPlugin) {
// extensionClass = LibraryExtension
// } else {
// return
// }
// childProject.extensions.configure(extensionClass, new Action<? extends TestedExtension>() {
// @Override
// void execute(TestedExtension testedExtension) {
// if (plugins != null && plugins.size() > 0) {
// for (AbsPlugin absPlugin : plugins) {
// absPlugin.evaluateAfterAndroidPlugin(childProject)
// }
// }
// }
// })
// }
mutLineLog.build4(" modules = " + projectInfo.modules)
/**
* 代替上述注解逻辑
*/
childProject.plugins.whenObjectAdded {
if (it instanceof AppPlugin || it instanceof LibraryPlugin) {
if (plugins != null && plugins.size() > 0) {
@@ -226,7 +256,7 @@ class Runtimes {
}
if (plugins != null && plugins.size() > 0) {
for (AbsPlugin absPlugin : plugins) {
absPlugin.afterEvaluateAfterAndroidPlugin(childProject)
absPlugin.afterEvaluateAfterAndroidPlugin(childProject, androidProject)
}
}
}
@@ -235,6 +265,65 @@ class Runtimes {
Logger.buildBlockLog("子 PROJECT 信息", mutLineLog)
}
//AGP4.1.0后调整了插件入口,废弃。
//把所有 监听了 projectsEvaluated 的匿名内部类移除
static List<BroadcastDispatch<BuildListener>> hookProjectsEvaluatedAction(Project project) {
def removeDispatch = new ArrayList<BroadcastDispatch<BuildListener>>()
try {
ListenerBroadcast<BuildListener> buildListenerBroadcast
def fBuildListenerBroadcast = DefaultGradle.class.getDeclaredField("buildListenerBroadcast")
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true)
modifiersField.setInt(fBuildListenerBroadcast, fBuildListenerBroadcast.getModifiers() & ~Modifier.FINAL)
fBuildListenerBroadcast.setAccessible(true)
buildListenerBroadcast = (ListenerBroadcast<BuildListener>) fBuildListenerBroadcast.get(project.gradle)
Field fBroadcast = ListenerBroadcast.class.getDeclaredField("broadcast")
fBroadcast.setAccessible(true)
BroadcastDispatch<BuildListener> broadcast = (BroadcastDispatch<BuildListener>) fBroadcast.get(buildListenerBroadcast)
def fDispatchers = broadcast.getClass().getDeclaredField("dispatchers")
fDispatchers.setAccessible(true)
ArrayList<BroadcastDispatch<BuildListener>> dispatchers = (ArrayList<BroadcastDispatch<BuildListener>>) fDispatchers.get(broadcast)
Class clazz =
Class.forName("org.gradle.internal.event.BroadcastDispatch\$ActionInvocationHandler")
Class clazz2 =
Class.forName("org.gradle.listener.ClosureBackedMethodInvocationDispatch")
def iterator = dispatchers.iterator()
while (iterator.hasNext()) {
try {
def next = iterator.next()
def fDispatch = next.getClass().getDeclaredField("dispatch")
fDispatch.setAccessible(true)
def dispatch = fDispatch.get(next)
Logger.buildOutput("dispatch:$dispatch")
def fMethodName
if (dispatch instanceof ClosureBackedMethodInvocationDispatch) {
fMethodName = clazz2.getDeclaredField("methodName")
} else if (dispatch.getClass() == clazz) {
fMethodName = clazz.getDeclaredField("methodName")
} else {
continue
}
fMethodName.setAccessible(true)
def methodName = fMethodName.get(dispatch)
if (methodName instanceof String && methodName.contains("projectsEvaluated")) {
removeDispatch.add(next)
iterator.remove()
}
} catch (Exception ignore) {
ignore.printStackTrace()
}
}
} catch (Exception ignore) {
ignore.printStackTrace()
}
return removeDispatch
}
/**
* 测试 AppPlugin/LibraryPlugin 时许
* t(evaluate) < t(configure) < t(whenObjectAdded) < t(withPlugin) < t(afterEvaluate)
@@ -302,6 +391,33 @@ class Runtimes {
Logger.buildBlockLog("子 PROJECT 注入插件", mutLineLog)
}
static void registerPublishTask(Project root) {
TaskProvider<ComponentPublishTask> debugTask = root.tasks.register("ComponentPublishDebug", ComponentPublishTask.class)
TaskProvider<ComponentPublishTask> releaseTask = root.tasks.register("ComponentPublishRelease", ComponentPublishTask.class)
}
static void checkPublishEnable(Project project) {
boolean shouldShutdown = false
project.rootProject.allprojects.each { childProject ->
if (childProject == project) return
if (!shouldApplyComponentPlugin(childProject)) return
PublicationOption sdkPublication = getSdkPublication(childProject.name)
PublicationOption implPublication = getImplPublication(childProject.name)
if (sdkPublication == null || implPublication == null) {
return
}
if (!GitUtil.canPublish(sdkPublication.sdkSourceSet.path) || !GitUtil.canPublish(implPublication.impSourceSet.path)) {
shouldShutdown = true
}
}
if (shouldShutdown) {
throw new GradleException("Must commit and push changes before publish")
}
}
static Map<String, PinConfiguration> getPinConfigurations() {
return sPinConfigurations
@@ -377,4 +493,12 @@ class Runtimes {
}
return null
}
static void clean() {
sSdkPublicationMap.clear()
sImplPublicationMap.clear()
sProjectInfoMap.clear()
sPinConfigurations.clear()
sAssembleModules.clear()
}
}

View File

@@ -22,6 +22,8 @@ class ComponentExtension {
Set<String> validModules
Project project
String appModule //app模块
ComponentExtension(Project project) {
this.project = project
debugOption = new DebugOption(project)
@@ -61,6 +63,16 @@ class ComponentExtension {
}
}
/**
* 配置app主模块名称
* @param moduleName
*/
void app(String... modules) {
if(modules != null && modules.size() > 0){
this.appModule = modules[0]
}
}
/**
* sdk模块
@@ -118,6 +130,7 @@ class ComponentExtension {
String toString() {
StringBuilder stringBuilder = new StringBuilder("\n")
stringBuilder.append(" ------------------------------------------------------------------" + "\n")
stringBuilder.append(" | appModule = " + appModule.toString() + "\n")
stringBuilder.append(" | include = " + includeModules.toList().toString() + "\n")
stringBuilder.append(" | exclude = " + excludeModules.toList().toString() + "\n")
stringBuilder.append(" | Select by " + (!includeModules.isEmpty() ? "includeModel" : "excludeModel") + "\n")

View File

@@ -1,12 +1,18 @@
package com.plugin.component.extension
import com.plugin.component.Constants
import com.plugin.component.extension.module.ProjectInfo
import com.plugin.component.extension.option.sdk.SdkOption
import com.plugin.component.log.Logger
import com.plugin.component.Runtimes
import com.plugin.component.extension.module.Digraph
import com.plugin.component.extension.module.SourceFile
import com.plugin.component.extension.module.SourceSet
import com.plugin.component.extension.option.sdk.PublicationOption
import com.plugin.component.log.MutLineLog
import com.plugin.component.utils.GitUtil
import com.plugin.component.utils.HttpUrlConnectHelper
import com.plugin.component.utils.ProjectUtil
import com.plugin.component.utils.PublicationUtil
import org.gradle.api.GradleException
import org.gradle.api.Project
@@ -20,6 +26,8 @@ import javax.xml.transform.Transformer
import javax.xml.transform.TransformerFactory
import javax.xml.transform.dom.DOMSource
import javax.xml.transform.stream.StreamResult
import java.nio.charset.Charset
import java.text.SimpleDateFormat
/**
* 发布sdk管理
@@ -49,31 +57,127 @@ class PublicationManager {
void loadManifest(Project rootProject) {
sdkPublicationManifest = new HashMap<>()
implPublicationManifest = new HashMap<>()
dependencyGraph = new Digraph<String>()
publicationDependencies = new HashMap<>()
boolean isAssemble = false
boolean isPublish = false
List<String> taskNames = ProjectUtil.getTasks(rootProject)
if (!taskNames.isEmpty()) {
for (String task : taskNames) {
if (task.toUpperCase().contains("ASSEMBLE")
|| task.contains("aR")
|| task.contains("asR")
|| task.contains("asD")
|| task.toUpperCase().contains("TINKER")
|| task.toUpperCase().contains("INSTALL")
|| task.toUpperCase().contains("RESGUARD")) {
isAssemble = true
} else if (task.toUpperCase().contains("COMPONENTPUBLISH")) {
isPublish = true
}
}
}
rootProject.gradle.buildFinished {
if (it.failure != null) {
Logger.buildOutput("build fail!")
return
}
saveManifest()
saveManifest(isAssemble)
logPublishInfo(rootProject, isPublish || isAssemble)
Runtimes.clean()
Logger.buildOutput("build finished!")
}
loadSdkManifest()
if (isAssemble) {
loadImpManifest()
}
}
File sdkPublicationManifest = new File(Runtimes.sSdkDir, 'publicationManifest.xml')
File implPublicationManifest = new File(Runtimes.sImplDir, 'publicationManifest.xml')
if (!sdkPublicationManifest.exists()) {
private static void logPublishInfo(Project rootProject, boolean needLogTask) {
if (!needLogTask) {
return
}
boolean isPublish = Runtimes.sSdkOption.isPublishMode
MutLineLog mutLineLog = new MutLineLog()
MutLineLog mutLineLogFile = new MutLineLog()
if (!implPublicationManifest.exists()) {
rootProject.allprojects.each { childProject ->
if (!Runtimes.shouldApplyComponentPlugin(childProject)) return
PublicationOption sdkPublication = Runtimes.getSdkPublication(childProject.name)
PublicationOption implPublication = Runtimes.getImplPublication(childProject.name)
ProjectInfo projectInfo = Runtimes.getProjectInfo(childProject.name)
if (sdkPublication == null || implPublication == null || projectInfo == null) {
return
}
isPublish = isPublish || projectInfo.isPublish
mutLineLog.build4("***********************************************************************************************************")
mutLineLog.build4("* SDK ${sdkPublication.name} publication=${PublicationUtil.getMavenGAV(sdkPublication)} publish=${sdkPublication.sdkNeedPublish}")
mutLineLog.build4("* commitInfo:")
mutLineLog.build4("* ${sdkPublication.sdkSourceSet.gitCommitInfo}")
mutLineLog.build4("* commitTime:${sdkPublication.sdkSourceSet.commitTime} commitUser:${sdkPublication.sdkSourceSet.commitUser}")
mutLineLog.build4("* ")
mutLineLog.build4("* Impl ${implPublication.name} publication=${PublicationUtil.getImpMavenGAV(implPublication, !projectInfo.isDebug)} publish=${implPublication.impNeedPublish}")
mutLineLog.build4("* commitInfo:")
mutLineLog.build4("* ${implPublication.impSourceSet.gitCommitInfo}")
mutLineLog.build4("* commitTime:${implPublication.impSourceSet.commitTime} commitUser:${implPublication.impSourceSet.commitUser}")
if (sdkPublication.sdkNeedPublish || implPublication.impNeedPublish) {
mutLineLogFile.build("***********************************************************************************************************")
if (sdkPublication.sdkNeedPublish) {
mutLineLogFile.build("* SDK ${sdkPublication.name} publication=${PublicationUtil.getMavenGAV(sdkPublication)} publish=${sdkPublication.sdkNeedPublish}")
mutLineLogFile.build("* commitInfo:")
mutLineLogFile.build("* ${sdkPublication.sdkSourceSet.gitCommitInfo}")
mutLineLogFile.build("* commitTime:${sdkPublication.sdkSourceSet.commitTime} commitUser:${sdkPublication.sdkSourceSet.commitUser}")
}
if (implPublication.impNeedPublish) {
mutLineLogFile.build("* Impl ${implPublication.name} publication=${PublicationUtil.getImpMavenGAV(implPublication, !projectInfo.isDebug)} publish=${implPublication.impNeedPublish}")
mutLineLogFile.build("* commitInfo:")
mutLineLogFile.build("* ${implPublication.impSourceSet.gitCommitInfo}")
mutLineLogFile.build("* commitTime:${implPublication.impSourceSet.commitTime} commitUser:${implPublication.impSourceSet.commitUser}")
}
}
}
mutLineLog.build4("***********************************************************************************************************")
if (!mutLineLogFile.done().isEmpty()) {
mutLineLogFile.build("***********************************************************************************************************")
}
if (isPublish) {
Logger.buildBlockLog("Publish Info", mutLineLog)
if (mutLineLogFile.done().isEmpty()) {
return
}
/*
* http://10.0.9.238:8088/probe/plugin-publish-log?log=${long}
* 每次日志通过log传递
* http://10.0.9.238:8080/godlike/plugin-logs/publish.log
* 浏览器打开查看
*/
def format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
StringBuilder builder = new StringBuilder()
String publishTile = "Publish Components in ${format.format(new Date())}"
builder.append(" ↓↓↓↓↓↓↓↓↓↓ $publishTile ↓↓↓↓↓↓↓↓↓↓\n")
builder.append(mutLineLogFile.done() + "\n")
builder.append(" ↑↑↑↑↑↑↑↑↑↑ $publishTile ↑↑↑↑↑↑↑↑↑↑\n")
String base = new String(Base64.urlEncoder.encode(builder.toString().getBytes("utf-8")), "utf-8")
HttpUrlConnectHelper.sendRequest("http://10.0.9.238:8088/probe/plugin-publish-log?log=${base}", "GET")
Logger.buildOutput("See http://10.0.9.238:8088/probe/log-query for more detail logs")
}
}
private void loadSdkManifest() {
File sdkPublicationManifestFile = new File(Runtimes.sSdkDir, 'publicationManifest.xml')
if (!sdkPublicationManifestFile.exists()) {
return
}
DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance()
Document document = builderFactory.newDocumentBuilder().parse(sdkPublicationManifest)
Document document = builderFactory.newDocumentBuilder().parse(sdkPublicationManifestFile)
//搜寻所有publication节点
NodeList publicationNodeList = document.documentElement.getElementsByTagName("publication")
@@ -85,8 +189,8 @@ class PublicationManager {
publication.project = publicationElement.getAttribute("project")
publication.groupId = publicationElement.getAttribute("groupId")
publication.artifactId = publicationElement.getAttribute("artifactId")
publication.version = publicationElement.getAttribute("version")
if (publication.version == "") publication.version = null
publication.sdkVersion = publicationElement.getAttribute("version")
if (publication.sdkVersion == "") publication.sdkVersion = null
publication.invalid = Boolean.valueOf(publicationElement.getAttribute("invalid"))
//如果有效
@@ -96,6 +200,12 @@ class PublicationManager {
SourceSet sourceSet = new SourceSet()
sourceSet.path = sourceSetElement.getAttribute("path")
sourceSet.lastModifiedSourceFile = new HashMap<>()
sourceSet.gitVersion = sourceSetElement.getAttribute("gitVersion")
try {
sourceSet.quickVerifyModified = sourceSetElement.getAttribute("quickVerifyModified").toLong()
} catch (Exception ignored) {
sourceSet.quickVerifyModified = 0L
}
NodeList fileNodeList = sourceSetElement.getElementsByTagName("file")
for (int k = 0; k < fileNodeList.getLength(); k++) {
Element fileElement = (Element) fileNodeList.item(k)
@@ -104,23 +214,131 @@ class PublicationManager {
sourceFile.lastModified = fileElement.getAttribute("lastModified").toLong()
sourceSet.lastModifiedSourceFile.put(sourceFile.path, sourceFile)
}
publication.misSourceSet = sourceSet
publication.sdkSourceSet = sourceSet
}
this.sdkPublicationManifest.put(PublicationUtil.getPublicationId(publication), publication)
}
}
private void loadImpManifest() {
File implPublicationManifestFile = new File(Runtimes.sImplDir, 'publicationManifest.xml')
if (!implPublicationManifestFile.exists()) {
return
}
DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance()
Document document = builderFactory.newDocumentBuilder().parse(implPublicationManifestFile)
//搜寻所有publication节点
NodeList publicationNodeList = document.documentElement.getElementsByTagName("publication")
for (int i = 0; i < publicationNodeList.getLength(); i++) {
Element publicationElement = (Element) publicationNodeList.item(i)
PublicationOption publication = new PublicationOption()
publication.project = publicationElement.getAttribute("project")
publication.groupId = publicationElement.getAttribute("groupId")
publication.artifactId = publicationElement.getAttribute("artifactId")
publication.implVersion = publicationElement.getAttribute("version")
if (publication.implVersion == "") publication.implVersion = null
publication.invalid = Boolean.valueOf(publicationElement.getAttribute("invalid"))
//如果有效
if (!publication.invalid) {
NodeList sourceSetNodeList = publicationElement.getElementsByTagName("sourceSet")
Element sourceSetElement = (Element) sourceSetNodeList.item(0)
SourceSet sourceSet = new SourceSet()
sourceSet.path = sourceSetElement.getAttribute("path")
sourceSet.lastModifiedSourceFile = new HashMap<>()
sourceSet.gitVersion = sourceSetElement.getAttribute("gitVersion")
try {
sourceSet.quickVerifyModified = sourceSetElement.getAttribute("quickVerifyModified").toLong()
} catch (Exception ignored) {
sourceSet.quickVerifyModified = 0L
}
NodeList fileNodeList = sourceSetElement.getElementsByTagName("file")
for (int k = 0; k < fileNodeList.getLength(); k++) {
Element fileElement = (Element) fileNodeList.item(k)
SourceFile sourceFile = new SourceFile()
sourceFile.path = fileElement.getAttribute("path")
sourceFile.lastModified = fileElement.getAttribute("lastModified").toLong()
sourceSet.lastModifiedSourceFile.put(sourceFile.path, sourceFile)
}
publication.impSourceSet = sourceSet
}
this.implPublicationManifest.put(PublicationUtil.getPublicationId(publication), publication)
}
}
private void saveManifest(boolean isAssemble) {
if (!Runtimes.sSdkDir.exists()) {
Runtimes.sSdkDir.mkdirs()
}
saveSdkManifest()
if (isAssemble) {
if (!Runtimes.sImplDir.exists()) {
Runtimes.sImplDir.mkdirs()
}
saveImpManifest()
}
}
/**
* 保存 impPublicationManifest.xml
*/
private void saveImpManifest() {
File implPublicationManifest = new File(Runtimes.sImplDir, 'publicationManifest.xml')
DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance()
Document document = builderFactory.newDocumentBuilder().newDocument()
Element manifestElement = document.createElement("manifest")
this.implPublicationManifest.each {
PublicationOption publication = it.value
if (!publication.hit || publication.invalid) return
Element publicationElement = document.createElement('publication')
publicationElement.setAttribute('project', publication.project)
publicationElement.setAttribute('groupId', publication.groupId)
publicationElement.setAttribute('artifactId', publication.artifactId)
publicationElement.setAttribute('version', publication.implVersion)
publicationElement.setAttribute('invalid', publication.invalid ? "true" : "false")
if (!publication.invalid) {
Element sourceSetElement = document.createElement('sourceSet')
sourceSetElement.setAttribute('path', publication.impSourceSet.path)
sourceSetElement.setAttribute('quickVerifyModified', publication.impSourceSet.quickVerifyModified.toString())
sourceSetElement.setAttribute("gitVersion", publication.impSourceSet.gitVersion)
// publication.impSourceSet.lastModifiedSourceFile.each {
// SourceFile sourceFile = it.value
// Element sourceFileElement = document.createElement('file')
// sourceFileElement.setAttribute('path', sourceFile.path)
// sourceFileElement.setAttribute('lastModified', sourceFile.lastModified.toString())
// sourceSetElement.appendChild(sourceFileElement)
// }
publicationElement.appendChild(sourceSetElement)
}
manifestElement.appendChild(publicationElement)
}
Transformer transformer = TransformerFactory.newInstance().newTransformer()
transformer.setOutputProperty(OutputKeys.INDENT, "yes")
transformer.setOutputProperty(OutputKeys.CDATA_SECTION_ELEMENTS, "yes")
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2")
transformer.transform(new DOMSource(manifestElement), new StreamResult(implPublicationManifest))
}
/**
* 保存 sdkPublicationManifest.xml
*/
private void saveManifest() {
if (!Runtimes.sSdkDir.exists()) {
Runtimes.sSdkDir.mkdirs()
}
private void saveSdkManifest() {
File sdkPublicationManifestFile = new File(Runtimes.sSdkDir, 'publicationManifest.xml')
File implPublicationManifest = new File(Runtimes.sSdkDir, 'publicationManifest.xml')
DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance()
Document document = builderFactory.newDocumentBuilder().newDocument()
@@ -134,19 +352,21 @@ class PublicationManager {
publicationElement.setAttribute('project', publication.project)
publicationElement.setAttribute('groupId', publication.groupId)
publicationElement.setAttribute('artifactId', publication.artifactId)
publicationElement.setAttribute('version', publication.version)
publicationElement.setAttribute('version', publication.sdkVersion)
publicationElement.setAttribute('invalid', publication.invalid ? "true" : "false")
if (!publication.invalid) {
Element sourceSetElement = document.createElement('sourceSet')
sourceSetElement.setAttribute('path', publication.misSourceSet.path)
publication.misSourceSet.lastModifiedSourceFile.each {
SourceFile sourceFile = it.value
Element sourceFileElement = document.createElement('file')
sourceFileElement.setAttribute('path', sourceFile.path)
sourceFileElement.setAttribute('lastModified', sourceFile.lastModified.toString())
sourceSetElement.appendChild(sourceFileElement)
}
sourceSetElement.setAttribute('path', publication.sdkSourceSet.path)
sourceSetElement.setAttribute('quickVerifyModified', publication.sdkSourceSet.quickVerifyModified.toString())
sourceSetElement.setAttribute("gitVersion", publication.sdkSourceSet.gitVersion)
// publication.sdkSourceSet.lastModifiedSourceFile.each {
// SourceFile sourceFile = it.value
// Element sourceFileElement = document.createElement('file')
// sourceFileElement.setAttribute('path', sourceFile.path)
// sourceFileElement.setAttribute('lastModified', sourceFile.lastModified.toString())
// sourceSetElement.appendChild(sourceFileElement)
// }
publicationElement.appendChild(sourceSetElement)
}
manifestElement.appendChild(publicationElement)
@@ -166,11 +386,14 @@ class PublicationManager {
if (publication.dependencies != null) {
if (publication.dependencies.implementation != null) {
publication.dependencies.implementation.each {
// Logger.buildOutput("addDependencyGraph: project:${projectName} dependency: ${it}")
if (it instanceof String && it.startsWith(Constants.COMPONENT_PRE)) {
String sdkDependency = PublicationUtil.getPublication(publication)
// String sdkDependency = PublicationUtil.getPublication(publication)
String sdkDependency = PublicationUtil.parseComponentToPublicationId(it)
// Logger.buildOutput("add sdkDependency project:${projectName} dependency: ${sdkDependency}")
dependencyGraph.add(key, sdkDependency)
if (!dependencyGraph.isDag()) {
throw new RuntimeException("Circular dependency in project [${projectName}] with '${sdkDependency}'.")
throw new RuntimeException("Circular dependency in project [${projectName}] with '${it}'.")
}
}
}
@@ -179,7 +402,8 @@ class PublicationManager {
if (publication.dependencies.compileOnly != null) {
publication.dependencies.compileOnly.each {
if (it instanceof String && it.startsWith(Constants.COMPONENT_PRE)) {
String sdkDependency = PublicationUtil.getPublication(publication)
// String sdkDependency = PublicationUtil.getPublication(publication)
String sdkDependency = PublicationUtil.parseComponentToPublicationId(it)
dependencyGraph.add(key, sdkDependency)
if (!dependencyGraph.isDag()) {
throw new RuntimeException("Circular dependency in project [${projectName}] with '${sdkDependency}'.")
@@ -195,19 +419,56 @@ class PublicationManager {
* @param publication
* @return
*/
boolean hasModified(PublicationOption publication) {
boolean hasSdkModified(PublicationOption publication) {
PublicationOption lastPublication = sdkPublicationManifest.get(PublicationUtil.getPublicationId(publication))
// Logger.buildOutput("lastPublication:${lastPublication}")
// Logger.buildOutput("currentPublication:${publication}")
if (lastPublication == null) {
return true
}
if (publication.invalid != lastPublication.invalid) {
return true
}
return hasModifiedSourceSet(publication.misSourceSet, lastPublication.misSourceSet)
return hasModifiedSourceSet(publication.sdkSourceSet, lastPublication.sdkSourceSet)
}
/**
* 判断是否修改
* @param publication
* @return
*/
boolean hasImpModified(PublicationOption publication) {
// File file = new File(Runtimes.sImplDir, PublicationUtil.getAarName(publication))
// if (!file.exists()) {
// return true
// }
PublicationOption lastPublication = implPublicationManifest.get(PublicationUtil.getPublicationId(publication))
// Logger.buildOutput("lastPublication:${lastPublication}")
// Logger.buildOutput("currentPublication:${publication}")
if (lastPublication == null) {
return true
}
if (publication.invalid != lastPublication.invalid) {
return true
}
return hasModifiedSourceSet(publication.impSourceSet, lastPublication.impSourceSet)
}
boolean hasModifyWithGitDiff(SourceSet sourceSet) {
if (!GitUtil.gitExist){
return false
}
String gitStatus = GitUtil.getGitDiff(sourceSet.path)
if (gitStatus == null || gitStatus.isEmpty()) {
return false
}
return true
}
private boolean hasModifiedSourceSet(SourceSet sourceSet1, SourceSet sourceSet2) {
return hasModifiedSourceFile(sourceSet1.lastModifiedSourceFile, sourceSet2.lastModifiedSourceFile)
return sourceSet1.quickVerifyModified != sourceSet2.quickVerifyModified
// return hasModifiedSourceFile(sourceSet1.lastModifiedSourceFile, sourceSet2.lastModifiedSourceFile)
}
private boolean hasModifiedSourceFile(Map<String, SourceFile> map1, Map<String, SourceFile> map2) {
@@ -231,6 +492,10 @@ class PublicationManager {
sdkPublicationManifest.put(PublicationUtil.getPublicationId(publication), publication)
}
void addImpPublication(PublicationOption publication) {
implPublicationManifest.put(PublicationUtil.getPublicationId(publication), publication)
}
PublicationOption getPublication(String groupId, String artifactId) {
return sdkPublicationManifest.get(PublicationUtil.getPublicationId(groupId, artifactId))
}
@@ -252,6 +517,30 @@ class PublicationManager {
return publications
}
PublicationOption getSdkPublicationByProject(Project project) {
String displayName = project.getDisplayName()
String projectName = displayName.substring(displayName.indexOf("'") + 1, displayName.lastIndexOf("'"))
PublicationOption publicationOption = null
sdkPublicationManifest.each {
if (projectName == it.value.project) {
publicationOption = it.value
}
}
return publicationOption
}
PublicationOption getImplPublicationByProject(Project project) {
String displayName = project.getDisplayName()
String projectName = displayName.substring(displayName.indexOf("'") + 1, displayName.lastIndexOf("'"))
PublicationOption publicationOption = null
implPublicationManifest.each {
if (projectName == it.value.project) {
publicationOption = it.value
}
}
return publicationOption
}
void hitPublication(PublicationOption publication) {
PublicationOption existsPublication = sdkPublicationManifest.get(PublicationUtil.getPublicationId(publication))
if (existsPublication == null) return

View File

@@ -20,6 +20,7 @@ class ProjectInfo {
public String taskNames
public List<String> modules = new ArrayList<>() //包含的模块
public boolean isAssemble = false //是否是asAssemble
public boolean isPublish = false //是否发布
public boolean isDebug = false //是否是debug
public String compileModuleName = "" //入口模块名字
public Set<String> componentDependencies = new HashSet<>() //模块依赖的component
@@ -61,6 +62,11 @@ class ProjectInfo {
}
String[] strings = task.split(":")
modules.add(strings.length > 1 ? strings[strings.length - 2] : "all")
} else if (task.toUpperCase().contains("COMPONENTPUBLISH")) {
isPublish = true
if (task.toUpperCase().contains("DEBUG")) {
isDebug = true
}
}
}
}

View File

@@ -7,4 +7,9 @@ package com.plugin.component.extension.module
class SourceSet {
String path // 路径
Map<String, SourceFile> lastModifiedSourceFile // 源码修改的资源集
Long quickVerifyModified // 文件是否快速校验
String gitVersion //当前git版本
String gitCommitInfo //git提交信息
String commitUser //git提交者
String commitTime //git提交时间
}

View File

@@ -1,5 +1,7 @@
package com.plugin.component.extension.option.sdk
import org.gradle.util.ConfigureUtil
/**
* sdk 依赖记录
* created by yummylau 2019/08/09
@@ -22,4 +24,22 @@ class PublicationDependenciesOption {
}
compileOnly.add(value)
}
void implementation(Closure closure) {
PublicationDependencyModuleOption option = new PublicationDependencyModuleOption()
ConfigureUtil.configure(closure, option)
if (implementation == null) {
implementation = new ArrayList<>()
}
implementation.add(option)
}
void compileOnly(Closure closure) {
PublicationDependencyModuleOption option = new PublicationDependencyModuleOption()
ConfigureUtil.configure(closure, option)
if (compileOnly == null) {
compileOnly = new ArrayList<>()
}
compileOnly.add(option)
}
}

View File

@@ -0,0 +1,17 @@
package com.plugin.component.extension.option.sdk
/**
* 依赖实现处理
*/
class PublicationDependencyModuleOption {
String path
Map<String, String> exclude
void path(String value) {
this.path = value
}
void exclude(Map<String, String> value) {
this.exclude = value
}
}

View File

@@ -14,20 +14,30 @@ class PublicationOption {
String scrName = "main" //资源目录名
String sourceSetName //sourceSet名
File buildDir //构建目录
File impDir //imp实现目录
String project //模块project路径
SourceSet misSourceSet //资源集如果当前maven不可用则需要记录源码及最后修改时间信息
SourceSet sdkSourceSet //sdk资源集如果当前maven不可用则需要记录源码及最后修改时间信息
SourceSet impSourceSet //imp资源集
String versionNew //新版本
boolean isSdk //是否时sdk
boolean invalid //是否非法
boolean hit //是否隐藏
boolean useLocal //是否使用本地jar
boolean forceLocal //强制使用本地打包
boolean useUserSdkVersion //使用用户指定Sdk版本
boolean useUserImplVersion //使用用户指定Impl版本
boolean impNeedPack //实现aar是否需要重新打包
boolean sdkNeedPublish = true //SDK是否需要发布
boolean impNeedPublish = true //imp是否需要发布
boolean useLocalImp //是否使用本地aar
boolean online = false //是否正式环境
/**
* option 用于配置sdk资源
*/
String groupId //依赖分组id
String artifactId //依赖id
String version //依赖版本
String sdkVersion //依赖版本
String implVersion //impl版本
String localProject //依赖版本
Closure sourceFilter //资源过滤
PublicationDependenciesOption dependencies //所持有的依赖信息
@@ -49,8 +59,19 @@ class PublicationOption {
this.artifactId = artifactId
}
void version(String version) {
this.version = version
void sdkVersion(String version) {
this.sdkVersion = version
this.useUserSdkVersion = true
}
void implVersion(String version) {
this.implVersion = version
this.useUserImplVersion = true
}
void forceUseLocal(boolean forceUseLocal) {
this.forceLocal = forceUseLocal
this.useLocal = true
}
void dependencies(Closure closure) {
@@ -61,4 +82,40 @@ class PublicationOption {
void sourceFilter(Closure closure) {
this.sourceFilter = closure
}
String getArtifactIdString() {
return "${artifactId}${online ? '' : "-test"}"
}
@Override
public String toString() {
def sdkQuickVerify = ""
if (sdkSourceSet != null) {
sdkQuickVerify = sdkSourceSet.quickVerifyModified
}
def implQuickVerify = ""
if (impSourceSet != null) {
implQuickVerify = impSourceSet.quickVerifyModified
}
return "PublicationOption{" +
"name='" + name + '\'' +
", scrName='" + scrName + '\'' +
", sourceSetName='" + sourceSetName + '\'' +
", buildDir=" + buildDir +
", impDir=" + impDir +
", project='" + project + '\'' +
", versionNew='" + versionNew + '\'' +
", isSdk=" + isSdk +
", invalid=" + invalid +
", hit=" + hit +
", useLocal=" + useLocal +
", impNeedPack=" + impNeedPack +
", groupId='" + groupId + '\'' +
", artifactId='" + artifactId + '\'' +
", sdkVersion='" + sdkVersion + '\'' +
", localProject='" + localProject + '\'' +
", sdkQuickVerify='" + sdkQuickVerify + '\'' +
", implQuickVerify='" + implQuickVerify + '\'' +
'}';
}
}

View File

@@ -1,14 +1,18 @@
package com.plugin.component.extension.option.sdk
import com.plugin.component.Constants
import com.plugin.component.log.Logger
import com.plugin.component.Runtimes
import com.plugin.component.extension.PublicationManager
import com.plugin.component.utils.FileUtil
import com.plugin.component.utils.GitUtil
import com.plugin.component.utils.ProjectUtil
import com.plugin.component.utils.PublicationUtil
import org.gradle.api.Action
import org.gradle.api.NamedDomainObjectContainer
import org.gradle.api.Project
import org.gradle.api.artifacts.dsl.RepositoryHandler
import org.gradle.api.artifacts.repositories.MavenArtifactRepository
import org.gradle.util.ConfigureUtil
class SdkOption {
@@ -16,7 +20,11 @@ class SdkOption {
Project project
int compileSdkVersion //编译版本
CompileOptions compileOption //编译选项
Action<? super RepositoryHandler> configure //仓库配置
Action<? super RepositoryHandler> repositories //仓库配置
boolean isAutoVersion //是否使用自动版本
boolean isPublishMode //是否发布模式
boolean isOnline
String mavenUrl //maven仓库
SdkOption(Project project) {
this.project = project
@@ -24,6 +32,10 @@ class SdkOption {
}
void mavenUrl(String mavenUrl) {
this.mavenUrl = mavenUrl
}
/**
* 编译sdk
* @param version
@@ -46,7 +58,44 @@ class SdkOption {
* @param configure
*/
void repositories(Action<? super RepositoryHandler> configure) {
this.configure = configure
this.repositories = configure
}
/**
* 仓库配置
* @param closure
*/
void repositories(Closure closure) {
this.repositories(ConfigureUtil.configureUsing(closure))
}
/**
* 是否使用自动版本
* @param flag
*/
void autoVersion(boolean flag) {
isAutoVersion = flag
if (flag) {
if (!GitUtil.gitExist) {
throw RuntimeException("git command not found! Please check your git path")
}
}
}
/**
* 是否发布模式
* @param flag
*/
void publishMode(boolean flag) {
this.isPublishMode = flag
}
/**
* 是否线上环境
* @param flag
*/
void online(boolean flag) {
this.isOnline = flag
}
/**
@@ -60,11 +109,32 @@ class SdkOption {
publications.each {
it.isSdk = true
it.name = ProjectUtil.getProjectName(it.name)
if (isPublishMode) {
it.forceUseLocal(true)
}
it.online = this.isOnline
it.sdkNeedPublish = isPublishMode
it.impNeedPublish = isPublishMode
Project childProject = ProjectUtil.getProject(project, it.name)
if (childProject != null) {
PublicationUtil.initPublication(childProject, it)
PublicationManager.getInstance().addDependencyGraph(it.name, it)
if (isPublishMode) {
childProject.plugins.apply(Constants.PLUGIN_MAVEN_PUBLISH)
}
PublicationUtil.initPublication(childProject, it, isAutoVersion)
Logger.buildOutput("init publication:${it}")
// PublicationManager.getInstance().addDependencyGraph(it.name, it)
Runtimes.addSdkPublication(childProject.name, it)
Runtimes.addImplPublication(childProject.name, it)
}
}
publications.each {
it.isSdk = true
it.name = ProjectUtil.getProjectName(it.name)
Project childProject = ProjectUtil.getProject(project, it.name)
if (childProject != null) {
// PublicationUtil.initPublication(childProject, it)
PublicationManager.getInstance().addDependencyGraph(it.name, it)
// Runtimes.addSdkPublication(childProject.name, it)
}
}
}
@@ -73,16 +143,16 @@ class SdkOption {
String toString() {
StringBuilder stringBuilder = new StringBuilder("\n")
stringBuilder.append(" ------------------------------------------------------------------" + "\n")
stringBuilder.append(" | AndroidJarPath = " + Runtimes.getAndroidJarPath() + "\n" )
stringBuilder.append(" | compileSdkVersion = " + compileSdkVersion + "\n" )
stringBuilder.append(" | CompileOptions = " + compileOption.toString()+ "\n" )
stringBuilder.append(" | configuration = [ " + "\n" )
stringBuilder.append(" | AndroidJarPath = " + Runtimes.getAndroidJarPath() + "\n")
stringBuilder.append(" | compileSdkVersion = " + compileSdkVersion + "\n")
stringBuilder.append(" | CompileOptions = " + compileOption.toString() + "\n")
stringBuilder.append(" | configuration = [ " + "\n")
Set<String> keys = Runtimes.getSdkPublicationMap().keySet()
for(String key: keys){
for (String key : keys) {
PublicationOption publicationOption = Runtimes.getSdkPublication(key)
stringBuilder.append(" | name = " + publicationOption.name + ", gav = " + publicationOption.groupId + "." + publicationOption.artifactId + "\n" )
stringBuilder.append(" | name = " + publicationOption.name + ", gav = " + publicationOption.groupId + "." + publicationOption.artifactId + "\n")
}
stringBuilder.append(" | ] " + "\n" )
stringBuilder.append(" | ] " + "\n")
stringBuilder.append(" -------------------------------------------------------------------" + "\n")
return stringBuilder.toString()
}

View File

@@ -13,7 +13,7 @@ abstract class AbsPlugin {
abstract void evaluateAfterAndroidPlugin(Project project)
abstract void afterEvaluateAfterAndroidPlugin(Project project)
abstract void afterEvaluateAfterAndroidPlugin(Project project,Project androidProject)
abstract void afterAllEvaluate(Project root)
}

View File

@@ -28,7 +28,7 @@ class BasePlugin extends AbsPlugin {
}
@Override
void afterEvaluateAfterAndroidPlugin(Project project) {
void afterEvaluateAfterAndroidPlugin(Project project, Project androidProject) {
}

View File

@@ -9,7 +9,7 @@ import org.gradle.api.Project
class DebugPlugin extends BasePlugin {
@Override
void afterEvaluateAfterAndroidPlugin(Project project) {
void afterEvaluateAfterAndroidPlugin(Project project, Project androidProject) {
ProjectInfo projectInfo = Runtimes.getProjectInfo(project.name)
if (projectInfo != null && ProjectUtil.isProjectSame(projectInfo.name, Runtimes.getDebugModuleName())) {
ProjectUtil.modifyDebugSets(projectInfo.project.rootProject, projectInfo)

View File

@@ -262,7 +262,7 @@ class PinPlugin extends BasePlugin {
// generate microModules.xml for PinInfo IDEA plugin.
def ideaFile = new File(buildResult.gradle.rootProject.rootDir, '.idea')
if (!ideaFile.exists()) return
def pininfos = '<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<modules>\n'
def pininfos = '<?xml sdkVersion=\"1.0\" encoding=\"UTF-8\"?>\n<modules>\n'
Map<String, PinConfiguration> allPins = Runtimes.getPinConfigurations()
Set<String> moduleNames = allPins.keySet()

View File

@@ -1,23 +1,33 @@
package com.plugin.component.plugin
import com.plugin.component.log.Logger
import com.plugin.component.ComponentPlugin
import com.plugin.component.Runtimes
import com.plugin.component.extension.PublicationManager
import com.plugin.component.extension.module.ProjectInfo
import com.plugin.component.extension.option.sdk.PublicationOption
import com.plugin.component.log.Logger
import com.plugin.component.log.MutLineLog
import com.plugin.component.utils.AarUtil
import com.plugin.component.utils.ProjectUtil
import com.plugin.component.utils.PublicationUtil
import org.gradle.api.Project
import org.gradle.api.artifacts.Configuration
import org.gradle.api.artifacts.Dependency
import org.gradle.api.internal.artifacts.dependencies.DefaultProjectDependency
import org.gradle.api.internal.artifacts.dependencies.DefaultSelfResolvingDependency
import org.gradle.api.internal.file.collections.DefaultConfigurableFileCollection
import org.gradle.api.internal.file.collections.DefaultConfigurableFileTree
class SdkPlugin extends BasePlugin {
@Override
void evaluateAfterAndroidPlugin(Project project) {
//针对每个module
ProjectInfo projectInfo = Runtimes.getProjectInfo(project.name)
//解析: component
//example component(':library')
//example component(':library') 转换为 ':com.effective.android-librarySdk:'
//规则:
// 1. component 对象必须为实现 component 插件的project
// 2. component(<project>) project 逻辑上被划分为 impl / debug / sdk其中 sdk 通过 api 暴露给上层impl 直接打包
@@ -29,58 +39,137 @@ class SdkPlugin extends BasePlugin {
List<PublicationOption> publications = PublicationManager.getInstance().getPublicationByProject(project)
project.dependencies {
publications.each {
Logger.buildOutput("添加依赖名字: " + PublicationUtil.getPublication(it))
api PublicationUtil.getPublication(it)
}
}
Logger.buildOutput("Syncing gradle...")
/**
* Syncing Gradle will evaluateAfterAndroidPlugin the build files by comparing the current files to the project state that Gradle and Android Studio maintain.
* If it finds any changes it will execute just those specific tasks.
*/
//project 需要依赖 sdk 中声明的依赖意味着同步的时候component.gradle 中 sdk { dependencies { <xxxxx> }} 内容需要同步迁移到 project
if (projectInfo.isSync()) {
Logger.buildOutput("Syncing gradle...")
publications.each {
PublicationUtil.addPublicationDependencies(projectInfo, it)
}
// if (projectInfo.isSync()) {
// Logger.buildOutput("Syncing gradle...")
publications.each {
PublicationUtil.addPublicationDependencies(projectInfo, it)
}
// }
}
@Override
void afterEvaluateAfterAndroidPlugin(Project project) {
void afterEvaluateAfterAndroidPlugin(Project project, Project androidProject) {
//整理资源路径
ProjectInfo projectInfo = Runtimes.getProjectInfo(project.name)
ProjectUtil.modifySourceSets(projectInfo)
//todo 发布
// List<PublicationOption> publicationList = PublicationManager.getInstance().getPublicationByProject(project)
// List<PublicationOption> publicationPublishList = new ArrayList<>()
// publicationList.each {
// if (it.version != null) {
// publicationPublishList.add(it)
// }
// }
//
// if (publicationPublishList.size() > 0) {
// project.plugins.apply(Constants.PLUGIN_MAVEN_PUBLISH)
// def publishing = project.extensions.getByName(Constants.PUBLISHING)
// if (mComponentExtension != null && mComponentExtension.configure != null) {
// publishing.repositories mComponentExtension.configure
// }
//
// publicationPublishList.each {
// PublicationUtil.createPublishTask(project, it)
// }
// }
}
@Override
void afterAllEvaluate(Project root) {
ProjectInfo compileProject = Runtimes.getCompileProjectWhenAssemble()
if (compileProject != null) {
// handleImpAar(root)
List<String> topSort = PublicationManager.getInstance().dependencyGraph.topSort()
Collections.reverse(topSort)
topSort.each {
PublicationOption publication = PublicationManager.getInstance().publicationDependencies.get(it)
if (publication == null) {
return
}
Project childProject = root.findProject(publication.project)
ProjectInfo projectInfo = Runtimes.getProjectInfo(childProject.name)
if (projectInfo.isAssemble) {
if (Runtimes.sSdkOption.isPublishMode) {
Runtimes.checkPublishEnable(childProject)
}
PublicationUtil.handleSdkPublish(childProject, ComponentPlugin.androidProject, publication, null)
handleImpAar(childProject, publication)
} else if (projectInfo.isPublish) {
publication.impNeedPublish = true
publication.sdkNeedPublish = true
def publishTask = null
if (projectInfo.isDebug) {
publishTask = root.tasks.named("ComponentPublishDebug")
} else {
publishTask = root.tasks.named("ComponentPublishRelease")
}
PublicationUtil.handleSdkPublish(childProject, ComponentPlugin.androidProject, publication, publishTask.get())
PublicationUtil.handleImplPublish(childProject, publication, projectInfo.isDebug, publishTask.get())
PublicationManager.getInstance().addImpPublication(publication)
}
}
dealAssemble(root)
}
MutLineLog mutLineLog = new MutLineLog()
private static void handleImpAar(Project project, PublicationOption publication) {
ProjectInfo projectInfo = Runtimes.getProjectInfo(project.name)
if (projectInfo == null) {
return
}
if (publication != null && !publication.invalid && ComponentPlugin.androidProject != null) {
boolean hasModify = PublicationManager.getInstance().hasImpModified(publication)
boolean hasGitDiff = PublicationManager.getInstance().hasModifyWithGitDiff(publication.impSourceSet)
File impFile = new File(Runtimes.sImplDir, PublicationUtil.getAarName(publication))
if (!publication.forceLocal && publication.implVersion != null) {
long startTime = System.currentTimeMillis()
boolean isAarExists = AarUtil.isArrExits(project, publication, !projectInfo.isDebug)
long cost = System.currentTimeMillis() - startTime
if (isAarExists && !hasGitDiff) {
publication.impNeedPack = false
publication.useLocalImp = false
PublicationManager.getInstance().addImpPublication(publication)
Logger.buildOutput("Handle Maven Imp ${publication.name} cost ${cost}ms. aar exists.No need to pack")
} else if (!hasModify && impFile.exists()) {
publication.impNeedPack = false
publication.useLocalImp = true
PublicationManager.getInstance().addImpPublication(publication)
Logger.buildOutput("Handle Local Imp ${publication.name} cost ${cost}ms. aar not exists but not modify and local file exists.No need to pack")
} else {
publication.impNeedPack = true
publication.useLocalImp = true
if (projectInfo.isDebug) {
//注册打包arr task
AarUtil.packImpAar(project, ComponentPlugin.androidProject, publication, null)
}
Logger.buildOutput("Handle Local Imp ${publication.name} cost ${cost}ms. Need pack")
}
} else {
Logger.buildOutput("Handle Local Imp ${publication.name}.")
if (publication.impNeedPublish) {
boolean isAarExists = AarUtil.isArrExits(project, publication, !projectInfo.isDebug)
publication.useLocalImp = !isAarExists
publication.impNeedPack = hasModify || !isAarExists
if (!isAarExists) {
PublicationUtil.handleImplPublish(project, publication, projectInfo.isDebug, null)
} else {
publication.impNeedPublish = false
}
PublicationManager.getInstance().addImpPublication(publication)
} else {
if (projectInfo.isDebug) {
publication.useLocalImp = true
if (hasModify) {
publication.impNeedPack = true
//注册打包arr task
AarUtil.packImpAar(project, ComponentPlugin.androidProject, publication, null)
} else {
publication.impNeedPack = false
}
PublicationManager.getInstance().addImpPublication(publication)
}
}
}
}
}
private void dealAssemble(Project root) {
//处理循环依赖
ProjectInfo compileProject = Runtimes.getCompileProjectWhenAssemble()
MutLineLog mutLineLog = new MutLineLog()
mutLineLog.build4("开始处理Assemble场景 compileProject:${compileProject}")
if (compileProject != null) {
if (Runtimes.sAssembleModules.size() > 1) {
mutLineLog.build4("task has one more assemble module,skip transforming [component] to [project]")
} else {
@@ -108,21 +197,181 @@ class SdkPlugin extends BasePlugin {
currentDependencies.addAll(nextDependencies)
nextDependencies.clear()
}
hasResolve.each {
Logger.buildOutput("resolve project:${compileProject.name} realDependency:${it}")
}
if (!hasResolve.isEmpty()) {
StringBuilder stringBuilder = new StringBuilder()
for (String realDependency : hasResolve) {
stringBuilder.append(" :project(")
stringBuilder.append(realDependency)
stringBuilder.append(")")
compileProject.project.dependencies {
implementation compileProject.project.project(":" + realDependency)
}
}
mutLineLog.build4("application[" + compileProject.name + "] component 合并依赖 = " + stringBuilder.toString())
handleCompileModuleDependency(compileProject, root, hasResolve, mutLineLog)
}
}
Logger.buildBlockLog("单 ASSEMBLE 场景处理循环依赖", mutLineLog)
}
Logger.buildBlockLog("单 ASSEMBLE 场景处理循环依赖", mutLineLog)
}
private void handleCompileModuleDependency(ProjectInfo compileProject, Project root, HashSet<String> hasResolve, MutLineLog mutLineLog) {
StringBuilder stringBuilder = new StringBuilder()
//收集所有模块的引用配置
ArrayList<Configuration> allConfigList = new ArrayList<>()
compileProject.project.rootProject.allprojects.each { project ->
if (project == root) return
if (!Runtimes.shouldApplyComponentPlugin(project)) return
project.configurations.each { config ->
if (config.name == "api" || config.name == "implementation"
|| config.name == "compileOnly"
|| config.name == "debugImplementation"
|| config.name == "debugApi"
|| config.name == "debugCompileOnly") {
allConfigList.add(config)
}
}
}
//收集project之间的引用依赖关系 收集被依赖的project需要参与编译
HashMap<Project, ArrayList<Configuration>> needCompileProjectConfigMap = new HashMap<>()
compileProject.project.rootProject.allprojects.each { project ->
if (project == root) return
allConfigList.each { config ->
for (Dependency dependency : config.dependencies) {
if (dependency instanceof DefaultProjectDependency && dependency.dependencyProject.name == project.name) {
ArrayList<Configuration> configs = needCompileProjectConfigMap.get(project)
if (configs == null) {
configs = new ArrayList<>()
needCompileProjectConfigMap.put(project, configs)
}
configs.add(config)
//一个config只需要添加一次就好了
return
}
}
}
}
//剔除被收集的编译工程的引用
allConfigList.clear()
compileProject.project.rootProject.allprojects.each { project ->
if (project == root) return
if (!Runtimes.shouldApplyComponentPlugin(project)) return
project.configurations.each { config ->
if (config.name == "api" || config.name == "implementation"
|| config.name == "compileOnly"
|| config.name == "debugImplementation"
|| config.name == "debugApi"
|| config.name == "debugCompileOnly") {
if (compileProject.project != project)
allConfigList.add(config)
}
}
}
HashMap<String, Map<String, String>> aarList = new HashMap<>()
for (String realDependency : hasResolve) {
PublicationOption publication = Runtimes.getImplPublication(realDependency)
Logger.buildOutput("resolve publication ${publication}")
if (publication != null && compileProject.isDebug) {
if (publication.impNeedPack) {
stringBuilder.append(" :project(")
stringBuilder.append(realDependency)
stringBuilder.append(")")
compileProject.project.dependencies {
implementation compileProject.project.project(":" + realDependency)
}
needCompileProjectConfigMap.put(Runtimes.getProjectInfo(realDependency).project, new ArrayList<Configuration>())
} else {
Map<String, String> map = new LinkedHashMap<>()
if (publication.useLocalImp) {
stringBuilder.append("${PublicationUtil.getAarName(publication)} ")
map.put("name", publication.groupId + '-' + publication.artifactId + '-imp')
map.put("ext", "aar")
} else {
stringBuilder.append("${PublicationUtil.getImpMavenGAV(publication, !compileProject.isDebug)} ")
map.put("path", PublicationUtil.getImpMavenGAV(publication, !compileProject.isDebug))
}
aarList.put(realDependency, map)
}
PublicationManager.getInstance().addImpPublication(publication)
} else {
stringBuilder.append(" :project(")
stringBuilder.append(realDependency)
stringBuilder.append(")")
compileProject.project.dependencies {
implementation compileProject.project.project(":" + realDependency)
}
needCompileProjectConfigMap.put(Runtimes.getProjectInfo(realDependency).project, new ArrayList<Configuration>())
}
}
if (compileProject.isDebug && !aarList.isEmpty()) {
compileProject.project.rootProject.allprojects.each { project ->
if (project == root) return
Logger.buildOutput("replace aarproject: $project.name")
// 替换成aar文件
aarList.each { map ->
//剔除所有配置中的不需要编译模块的依赖
project.configurations.each { config ->
config.dependencies.removeAll { dependency ->
dependency instanceof DefaultProjectDependency && dependency.dependencyProject.name == map.key
}
}
project.dependencies {
if (map.getValue().size() > 1) {
api map.value
} else {
api map.value.get("path")
}
}
}
}
aarList.each { map ->
allConfigList.each { config ->
config.dependencies.removeAll { dependency ->
dependency instanceof DefaultProjectDependency && dependency.dependencyProject.name == map.key
}
}
}
List<Map<String, Object>> needAndDependency = new ArrayList<>()
//分离所有dependency 进行预处理
allConfigList.each { config ->
config.dependencies.each { dependency ->
if (dependency instanceof DefaultProjectDependency) {
def dependencyClone = dependency.copy()
dependencyClone.targetConfiguration = null
Map<String, Object> map = new HashMap<>()
map.put(config.name, dependencyClone)
needAndDependency.add(map)
} else {
if (dependency instanceof DefaultSelfResolvingDependency && (dependency.files instanceof DefaultConfigurableFileCollection || dependency.files instanceof DefaultConfigurableFileTree)) {
// 这里的依赖是以下两种: 无需添加在 编译project ,因为 jar 包直接进入 自身的 aar 中的libs 文件夹
// implementation rootProject.files("libs/*.jar")
// implementation fileTree(dir: "libs", include: ["*.jar"])
} else {
Map<String, Object> map = new HashMap<>()
map.put(config.name, dependency)
needAndDependency.add(map)
}
}
}
}
//遍历所有需要编译的project 将引用传递至需要编译的project中module引用只需要传递api方式引用的
needCompileProjectConfigMap.each { entry ->
if (entry.key == root) return
needAndDependency.each { map ->
Map.Entry<String, Object> config = map.entrySet().first()
Dependency dependency = config.value
if (config.key == "api") {
if (dependency instanceof DefaultProjectDependency && dependency.dependencyProject.name == entry.key.name) {
return
}
compileProject.project.dependencies.add(config.key, config.value)
entry.key.dependencies.add(config.key, config.value)
} else {
//不传递implement project
if (dependency instanceof DefaultProjectDependency) {
return
}
compileProject.project.dependencies.add(config.key, config.value)
// entry.key.dependencies.add(config.key, config.value)
}
}
}
}
mutLineLog.build4("application[" + compileProject.name + "] component 合并依赖 = " + stringBuilder.toString())
}
}

View File

@@ -0,0 +1,43 @@
package com.plugin.component.task
import com.plugin.component.Runtimes
import com.plugin.component.extension.option.sdk.PublicationOption
import com.plugin.component.log.Logger
import com.plugin.component.utils.FileUtil
import com.plugin.component.utils.PublicationUtil
import org.gradle.api.DefaultTask
import org.gradle.api.tasks.Internal
import org.gradle.api.tasks.TaskAction
/**
* 复制aar到Runtime#sImplDir路径下
*/
class AarLocalPublishTask extends DefaultTask {
@Internal
String inputPath
@Internal
File inputFile
@Internal
File outputDir
@Internal
PublicationOption publication
@TaskAction
void uploadLocalMaven() {
String aarName = PublicationUtil.getAarName(publication)
inputPath = FileUtil.findAarPath(project)
outputDir = Runtimes.sImplDir
if (inputPath != null) {
inputFile = new File(inputPath)
File outputFile = new File(outputDir, aarName)
if (outputFile.exists()) {
outputFile.delete()
}
FileUtil.copyFile(inputFile, outputFile)
} else {
Logger.buildOutput("project:${project.name} aar not found")
}
}
}

View File

@@ -4,6 +4,8 @@ package com.plugin.component.task
import com.plugin.component.Runtimes
import com.plugin.component.extension.PublicationManager
import com.plugin.component.extension.option.sdk.PublicationOption
import com.plugin.component.utils.JarUtil
import com.plugin.component.utils.PublicationUtil
import org.gradle.api.DefaultTask
import org.gradle.api.tasks.TaskAction
@@ -18,14 +20,17 @@ class CompileSdkTask extends DefaultTask {
@TaskAction
void compileSource() {
def project = getProject()
def releaseJar = JarUtil.packJavaSourceJar(project, publication, Runtimes.getAndroidJarPath(), Runtimes.getCompileOption(), false)
if (releaseJar == null) {
throw new RuntimeException("nothing to push.")
File target = new File(Runtimes.sSdkDir, PublicationUtil.getJarName(publication))
if (!target.exists()) {
def releaseJar = JarUtil.packJavaSourceJar(project, publication, Runtimes.getAndroidJarPath(), Runtimes.getCompileOption(), false)
if (releaseJar == null) {
throw new RuntimeException("nothing to push.")
}
}
JarUtil.packJavaDocSourceJar(publication)
PublicationManager publicationManager = PublicationManager.getInstance()
if (publication.versionNew != null) {
publication.version = publication.versionNew
publication.sdkVersion = publication.versionNew
}
publicationManager.addPublication(publication)
}

View File

@@ -0,0 +1,24 @@
package com.plugin.component.task
import com.plugin.component.Runtimes
import com.plugin.component.log.Logger
import org.gradle.api.DefaultTask
import org.gradle.api.tasks.TaskAction
/**
* 组件发布
* create by linyue 2022/08/22
*/
class ComponentPublishTask extends DefaultTask {
ComponentPublishTask() {
setGroup("component plugin")
}
@TaskAction
void publish() {
Logger.buildOutput("startPublish")
Runtimes.checkPublishEnable(project)
}
}

View File

@@ -184,7 +184,7 @@ public class ComponentTransform extends Transform {
ScanSummaryInfo cacheSummary = readPluginCache(); // 读取缓存
ScanSummaryInfo scanSummaryInfo = ScanRuntime.updateSummaryInfo(cacheSummary); // 整理本次扫结果,返回最新的模块结构
ScanSummaryInfo scanSummaryInfo = ScanRuntime.updateSummaryInfo(cacheSummary); // 整理本次扫结果,返回最新的模块结构
ScanRuntime.buildComponentSdkInfo();
ScanRuntime.logScanInfo();

View File

@@ -51,7 +51,6 @@ public class ComponentWeaver implements IWeaver {
String inputPath = inputJar.getAbsolutePath();
String outputPath = outputJar.getAbsolutePath();
ZipFile inputZip = new ZipFile(inputJar);
ZipOutputStream outputZip = new ZipOutputStream(new BufferedOutputStream(java.nio.file.Files.newOutputStream(outputJar.toPath())));
Enumeration<? extends ZipEntry> inEntries = inputZip.entries();
while (inEntries.hasMoreElements()) {
ZipEntry entry = inEntries.nextElement();
@@ -63,26 +62,11 @@ public class ComponentWeaver implements IWeaver {
beforeWeaveClass(inputPath, outputPath, className);
if (!isWeavableClass(className)) {
newEntryContent = org.apache.commons.io.IOUtils.toByteArray(originalFile);
} else {
newEntryContent = weaveSingleClassToByteArray(inputPath, originalFile);
if (isWeavableClass(className)) {
weaveSingleClassToByteArray(inputPath, originalFile);
}
CRC32 crc32 = new CRC32();
crc32.update(newEntryContent);
outEntry.setCrc(crc32.getValue());
outEntry.setMethod(ZipEntry.STORED);
outEntry.setSize(newEntryContent.length);
outEntry.setCompressedSize(newEntryContent.length);
outEntry.setLastAccessTime(ZERO);
outEntry.setLastModifiedTime(ZERO);
outEntry.setCreationTime(ZERO);
outputZip.putNextEntry(outEntry);
outputZip.write(newEntryContent);
outputZip.closeEntry();
}
outputZip.flush();
outputZip.close();
FileUtils.copyFile(inputJar, outputJar);
}
public final void weaveSingleClassToFile(File inputFile, File outputFile, String inputBaseDir) throws IOException {
@@ -98,10 +82,8 @@ public class ComponentWeaver implements IWeaver {
FileUtils.touch(outputFile);
InputStream inputStream = new FileInputStream(inputFile);
byte[] bytes = weaveSingleClassToByteArray(inputPath, inputStream);
FileOutputStream fos = new FileOutputStream(outputFile);
fos.write(bytes);
fos.close();
inputStream.close();
FileUtils.copyFile(inputFile, outputFile);
} else {
if (inputFile.isFile()) {
FileUtils.touch(outputFile);

View File

@@ -10,6 +10,9 @@ import org.objectweb.asm.ClassVisitor
import org.objectweb.asm.Opcodes
import org.objectweb.asm.Type
/**
* 扫描注解并且收集
*/
class ScanCodeAdapter extends ClassVisitor {
private String className

View File

@@ -0,0 +1,136 @@
package com.plugin.component.utils
import com.android.build.gradle.AppExtension
import com.android.build.gradle.api.ApplicationVariant
import com.plugin.component.Runtimes
import com.plugin.component.extension.PublicationManager
import com.plugin.component.extension.option.sdk.PublicationOption
import com.plugin.component.log.Logger
import com.plugin.component.task.AarLocalPublishTask
import com.plugin.component.task.ComponentPublishTask
import org.apache.http.util.TextUtils
import org.gradle.api.Project
import org.gradle.api.Task
import org.gradle.api.artifacts.Configuration
import org.gradle.api.artifacts.dsl.RepositoryHandler
import org.gradle.api.tasks.TaskProvider
class AarUtil {
static void packImpAar(Project currentProject, Project androidProject, PublicationOption publication, Task dependTask) {
AppExtension appExtension = androidProject.extensions.getByType(AppExtension.class)
appExtension.applicationVariants.each {
if (it.buildType.name.toLowerCase().contains("debug")) {
if (dependTask == null) {
TaskProvider<Task> assembleTask = getAssembleTask(androidProject, it)
Logger.buildOutput("getAssembleTask:${assembleTask.name}")
dependTask = assembleTask.get()
}
hookBundleAarTask(currentProject, dependTask, it.buildType.name, publication, false)
}
}
}
static void packImpAarRelease(Project currentProject, Project androidProject, PublicationOption publication, Task dependTask) {
AppExtension appExtension = androidProject.extensions.getByType(AppExtension.class)
appExtension.applicationVariants.each {
if (it.buildType.name.toLowerCase().contains("release")) {
if (dependTask == null) {
TaskProvider<Task> assembleTask = getAssembleTask(androidProject, it)
Logger.buildOutput("getAssembleTask:${assembleTask.name}")
dependTask = assembleTask.get()
}
hookBundleAarTask(currentProject, dependTask, it.buildType.name, publication, true)
}
}
}
static TaskProvider<Task> getAssembleTask(Project androidProject, ApplicationVariant variant) {
TaskProvider<Task> assembleTask =
androidProject.tasks.named("assemble${variant.flavorName.capitalize()}${variant.buildType.name.capitalize()}")
return assembleTask
}
static boolean isArrExits(Project project, PublicationOption publication, boolean isRelease) {
String filePath = null
String fileName = isRelease ? publication.getArtifactIdString() + "-imp-" + publication.implVersion + ".aar" : publication.getArtifactIdString() + "-imp-debug-" + publication.implVersion + ".aar"
String artifactId = isRelease ? publication.getArtifactIdString() + "-imp" : publication.getArtifactIdString() + "-imp-debug"
// http://172.16.xxx.xxx:8081/nexus/content/groups/public/com/xxx/cif/xxx-cif-api/0.0.1-SNAPSHOT/xxx-cif-api-0.0.1-20170515.040917-89.jar
String url = Runtimes.sSdkOption.getMavenUrl()
String result = HttpUrlConnectHelper.sendRequest("$url/${publication.groupId.replace('.', '/')}/$artifactId/${publication.implVersion}/$fileName","HEAD")
if (!TextUtils.isEmpty(result)) {
filePath = "$url/${publication.groupId.replace('.', '/')}/$artifactId/${publication.implVersion}/$fileName"
}
// def name = "component[${publication.groupId}-${publication.artifactId}]Classpath"
// Configuration configuration = project.configurations.create(name)
// project.dependencies.add(name, PublicationUtil.getImpMavenGAV(publication, isRelease))
// try {
// configuration.copy().files.each {
// Logger.buildOutput("aarName:${it.name}")
// if (it.name.endsWith(fileName)) {
// filePath = it.absolutePath
// }
// }
// } catch (Exception e) {
//// e.printStackTrace()
// Logger.buildOutput(e.getMessage())
// }
// project.configurations.remove(configuration)
return filePath != null
}
private static void hookBundleAarTask(Project currentProject, Task assembleTask, String buildType, PublicationOption publication, boolean isRelease) {
Task bundleTask = assembleTask
if (publication.impNeedPack) {
bundleTask = getBundleAarTask(currentProject, buildType.capitalize())
bundleTask.getTaskDependencies().getDependencies(bundleTask).each {
if (it != assembleTask && assembleTask instanceof ComponentPublishTask) {
//找到bundleAar的所有task让他们都依赖ComponentPublishTask
it.dependsOn(assembleTask)
}
}
bundleTask.dependsOn(assembleTask)
bundleTask.mustRunAfter(assembleTask)
assembleTask.finalizedBy(bundleTask)
}
AarLocalPublishTask aarLocalPublishTask = currentProject.tasks.maybeCreate("uploadLocalMaven" + buildType.capitalize(), AarLocalPublishTask.class)
aarLocalPublishTask.publication = publication
aarLocalPublishTask.dependsOn(bundleTask)
bundleTask.finalizedBy(aarLocalPublishTask)
aarLocalPublishTask.doFirst {
Logger.buildOutput("${aarLocalPublishTask.name} start")
}
aarLocalPublishTask.doLast {
Logger.buildOutput("${aarLocalPublishTask.name} finish")
}
if (publication.impNeedPublish) {
def publicationName = 'Component-' + currentProject.name + buildType.capitalize() + 'Imp'
String publishTaskNamePrefix = "publish${publicationName}PublicationTo"
currentProject.tasks.whenTaskAdded {
if (it.name.startsWith(publishTaskNamePrefix)) {
it.dependsOn aarLocalPublishTask
it.doLast {
PublicationManager.getInstance().addImpPublication(publication)
}
}
}
PublicationUtil.createImpPublishingPublication(currentProject, publication, publicationName, isRelease)
TaskProvider<Task> publishTask = currentProject.tasks.named("${publishTaskNamePrefix}MavenRepository")
aarLocalPublishTask.finalizedBy(publishTask.get())
}
}
/**
* 获取到每个模块的bundleXXXAar task,用于打包每个module的aar
* @param currentProject
* @param variantName
*/
private static Task getBundleAarTask(Project currentProject, String variantName) {
String taskName = "bundle${variantName}Aar"
TaskProvider<Task> bundleAarTask = currentProject.tasks.named(taskName)
return bundleAarTask.get()
}
}

View File

@@ -1,6 +1,8 @@
package com.plugin.component.utils
import com.plugin.component.ComponentPlugin
import com.plugin.component.Constants
import org.gradle.api.Project
class FileUtil {
@@ -62,4 +64,30 @@ class FileUtil {
e.printStackTrace()
}
}
static String findAarPath(Project project) {
File aarDir = new File(project.buildDir.absolutePath + "/outputs/aar/")
if (aarDir.exists()) {
File[] files = aarDir.listFiles(new FilenameFilter() {
@Override
boolean accept(File dir, String name) {
return name.endsWith(".aar")
}
})
if (files.size() > 0) {
return files.first().absolutePath
}
}
return null
}
static String shell(String cmd) {
def out = new ByteArrayOutputStream()
ComponentPlugin.rootProject.exec {
executable 'bash'
args '-c', cmd
standardOutput = out
}
return out.toString().trim()
}
}

View File

@@ -0,0 +1,32 @@
package com.plugin.component.utils
class GitUtil {
static boolean canPublish(String filePath) {
if (isGitExist()) {
if (getGitBranch().matches("(^develop\$)|(^release/(.)*)")) {
return getGitDiff(filePath).isEmpty()
}
return getGitDiff(filePath).isEmpty() && getGitCherry().isEmpty()
} else {
return true
}
}
static boolean isGitExist() {
return !FileUtil.shell("git --help").contains("git command not found")
}
static String getGitDiff(String filePath) {
return FileUtil.shell("git diff ${filePath}")
}
static String getGitCherry() {
return FileUtil.shell("git cherry")
}
static String getGitBranch() {
return FileUtil.shell("git symbolic-ref --short -q HEAD")
}
}

View File

@@ -0,0 +1,62 @@
package com.plugin.component.utils;
import com.plugin.component.log.Logger;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
/**
* createBy:linyue
* date:2022/9/9
* description:
*/
public class HttpUrlConnectHelper {
public static String sendRequest(String urlParam, String requestType) {
HttpURLConnection con = null;
BufferedReader buffer = null;
StringBuffer resultBuffer = null;
try {
URL url = new URL(urlParam);
//得到连接对象
con = (HttpURLConnection) url.openConnection();
//设置请求类型
con.setRequestMethod(requestType);
//设置请求需要返回的数据类型和字符集类型
con.setRequestProperty("Content-Type", "application/json;charset=utf-8");
//允许写出
con.setDoOutput(true);
//允许读入
con.setDoInput(true);
//不使用缓存
con.setUseCaches(false);
//得到响应码
int responseCode = con.getResponseCode();
// Logger.buildOutput("responseCode", responseCode);
if (responseCode == HttpURLConnection.HTTP_OK) {
if (requestType.equals("HEAD")) {
return "OK";
}
//得到响应流
InputStream inputStream = con.getInputStream();
//将响应流转换成字符串
resultBuffer = new StringBuffer();
String line;
buffer = new BufferedReader(new InputStreamReader(inputStream));
while ((line = buffer.readLine()) != null) {
resultBuffer.append(line);
}
return resultBuffer.toString();
}
} catch (Exception e) {
e.printStackTrace();
}
return "";
}
}

View File

@@ -1,11 +1,13 @@
package com.plugin.component.utils
import com.plugin.component.Constants
import com.plugin.component.extension.option.sdk.PublicationDependencyModuleOption
import com.plugin.component.log.Logger
import com.plugin.component.Runtimes
import com.plugin.component.extension.PublicationManager
import com.plugin.component.extension.option.sdk.CompileOptions
import com.plugin.component.extension.option.sdk.PublicationOption
import org.apache.http.util.TextUtils
import org.gradle.api.GradleException
import org.gradle.api.JavaVersion
import org.gradle.api.Project
@@ -14,7 +16,6 @@ import org.gradle.internal.jvm.Jvm
import org.jetbrains.kotlin.cli.common.ExitCode
import org.jetbrains.kotlin.cli.jvm.K2JVMCompiler
import java.util.concurrent.TimeUnit
import java.util.jar.JarEntry
import java.util.jar.JarFile
import java.util.zip.ZipFile
@@ -45,8 +46,8 @@ class JarUtil {
outputDir.mkdirs()
def argFiles = []
File file = new File(publication.misSourceSet.path)
String prefix = publication.misSourceSet.path
File file = new File(publication.sdkSourceSet.path)
String prefix = publication.sdkSourceSet.path
filterJavaSource(file, prefix, sourceDir, argFiles, publication.sourceFilter)
if (argFiles.size() == 0) {
return null
@@ -57,21 +58,21 @@ class JarUtil {
Configuration configuration = project.configurations.create(name)
if (publication.dependencies != null) {
if (publication.dependencies.implementation != null) {
publication.dependencies.implementation.each {
if (it instanceof String && it.startsWith(Constants.COMPONENT_PRE)) {
project.dependencies.add(name, PublicationUtil.parseComponent(it))
}else{
project.dependencies.add(name, it)
publication.dependencies.implementation.each { dependency ->
// Logger.buildOutput("packJar: publication:${PublicationUtil.getPublicationId(publication)} move dependencies:${it}")
if (dependency instanceof PublicationDependencyModuleOption) {
project.dependencies.add(name, dependency.path)
} else {
project.dependencies.add(name, dependency)
}
}
}
if (publication.dependencies.compileOnly != null) {
publication.dependencies.compileOnly.each {
if (it instanceof String && it.startsWith(Constants.COMPONENT_PRE)) {
project.dependencies.add(name, PublicationUtil.parseComponent(it))
}else{
project.dependencies.add(name, it)
publication.dependencies.compileOnly.each { dependency ->
if (dependency instanceof PublicationDependencyModuleOption) {
project.dependencies.add(name, dependency.path)
} else {
project.dependencies.add(name, dependency)
}
}
}
@@ -79,6 +80,8 @@ class JarUtil {
def classPath = [androidJarPath]
configuration.copy().files.each {
// Logger.buildOutput("packJar: copyFile name:${it.name}")
//添加所有打包的classpatch
if (it.name.endsWith('.aar')) {
classPath << getAARClassesJar(it)
} else {
@@ -86,7 +89,7 @@ class JarUtil {
}
}
project.configurations.remove(configuration)
Logger.buildOutput("packing ${project.name} sdk jar")
return generateJavaSourceJar(classesDir, argFiles, classPath, compileOptions, vars)
}
@@ -106,12 +109,6 @@ class JarUtil {
CompileOptions compileOptions,
boolean vars) {
//window classpath 路径分割符号与 mac/linux需要做区分
def classpathSeparator = ";"
if (!System.properties['os.name'].toLowerCase().contains('windows')) {
classpathSeparator = ":"
}
boolean keepParameters = vars && Jvm.current().javaVersion >= JavaVersion.VERSION_1_8
//读取java和kotlin文件
@@ -140,7 +137,7 @@ class JarUtil {
JavaVersion targetCompatibility = compileOptions.targetCompatibility
def target = targetCompatibility.toString()
if (!targetCompatibility.isJava8() && !targetCompatibility.isJava6()) {
throw new GradleException("Failure to compile component kotlin source to bytecode: unknown JVM target version: $target, supported versions: 1.6, 1.8\nTry:\n " +
throw new GradleException("Failure to compile component kotlin source to bytecode: unknown JVM target sdkVersion: $target, supported versions: 1.6, 1.8\nTry:\n " +
" module {\n" +
" ...\n" +
" compileOption {\n" +
@@ -156,10 +153,12 @@ class JarUtil {
if (classPath.size() > 0) {
args.add('-classpath')
args.add(classPath.join(classpathSeparator))
args.add(classPath.join(File.pathSeparator))
}
ExitCode exitCode = compiler.exec(System.out, (String[]) args.toArray())
Logger.buildOutput("编译参数: " + (String[]) args.toArray())
Logger.buildOutput("kotlin 编译结果: +${exitCode}")
if (exitCode != ExitCode.OK) {
throw new GradleException("Failure to compile component kotlin source to bytecode.")
}
@@ -170,25 +169,67 @@ class JarUtil {
}
if (!javaFiles.isEmpty()) {
def command = "javac " + (keepParameters ? "-parameters" : "") + " -d . -encoding UTF-8 -target " + compileOptions.targetCompatibility.toString() + " -source " + compileOptions.sourceCompatibility.toString() + (classPath.size() > 0 ? (" -classpath " + classPath.join(classpathSeparator) + " ") : "") + javaFiles.join(' ')
def p = (command).execute(null, classesDir)
LinkedList<String> paras = new LinkedList();
paras.add('javac')
paras.add('-parameters')
paras.add('-d')
paras.add(classesDir.getAbsolutePath())
paras.add('-encoding')
paras.add('UTF-8')
paras.add('-target')
paras.add(compileOptions.targetCompatibility.toString())
paras.add('-source')
paras.add(compileOptions.sourceCompatibility.toString())
def result = p.waitFor(30, TimeUnit.SECONDS)
if (!result) {
throw new GradleException("Timed out when compile component java source to bytecode with command.\nExecute command:\n" + command)
}
paras.add('-classpath')
paras.add(classPath.join(File.pathSeparator))
paras.addAll(javaFiles);
if (p.exitValue() != 0) {
throw new GradleException("Failure to compile component java source to bytecode: \n" + p.err.text + "\nExecute command:\n" + command)
String[] javacParameters = (String[]) paras.toArray(new String[paras.size()])
Runtime runtime = Runtime.getRuntime()
def p = runtime.exec(javacParameters, null, classesDir);
Logger.buildOutput("javac execute command:${javacParameters}")
def shellErrorResultReader = new BufferedReader(new InputStreamReader(p.getErrorStream()));
def shellInfoResultReader = new BufferedReader(new InputStreamReader(p.getInputStream()));
//需要输出缓冲区数据 不然会阻塞在waitFor
String infoLine;
while ((infoLine = shellInfoResultReader.readLine()) != null) {
Logger.buildOutput("脚本文件执行信息:{}", infoLine);
}
String errorLine;
while ((errorLine = shellErrorResultReader.readLine()) != null) {
Logger.buildOutput("脚本文件执行信息:{}", errorLine);
}
def result = p.waitFor()
Logger.buildOutput("javac execute result:${result}")
if (result != 0) {
throw new GradleException("Failure to compile component java source to bytecode: \n" + p.err.text + "\nExecute command:\n" + javacParameters)
}
p.destroy()
}
Logger.buildOutput("jar execute command: jar cf outputs/classes.jar -C classes . \nclasses path ${classesDir.parentFile.absolutePath}")
// def p = "jar cvf outputs/classes.jar -C classes . ".execute(null, classesDir.parentFile)
Runtime runtime = Runtime.getRuntime()
def p = runtime.exec("jar cf outputs/classes.jar -C classes . ", null, classesDir.parentFile);
def shellErrorResultReader = new BufferedReader(new InputStreamReader(p.getErrorStream()));
def shellInfoResultReader = new BufferedReader(new InputStreamReader(p.getInputStream()));
//需要输出缓冲区数据 不然会阻塞在waitFor
String infoLine;
while ((infoLine = shellInfoResultReader.readLine()) != null) {
Logger.buildOutput("脚本文件执行信息:{}", infoLine);
}
String errorLine;
while ((errorLine = shellErrorResultReader.readLine()) != null) {
Logger.buildOutput("脚本文件执行信息:{}", errorLine);
}
def p = "jar cvf outputs/classes.jar -C classes . ".execute(null, classesDir.parentFile)
def result = p.waitFor()
p.waitFor()
Logger.buildOutput("jar excute result:${result}")
// p.waitFor()
if (result != 0) {
throw new RuntimeException("failure to package classes.jar: \n" + p.err.text)
}
p.destroy()
return new File(classesDir.parentFile, 'outputs/classes.jar')
}
@@ -201,13 +242,25 @@ class JarUtil {
def javaSource = new File(publication.buildDir, "javaSource")
javaSource.deleteDir()
javaSource.mkdirs()
filterJavaDocSource(new File(publication.misSourceSet.path), publication.misSourceSet.path, javaSource)
def outputDir = new File(publication.buildDir, Constants.BUILD_OUTPUT_DIR)
if (!outputDir.exists()) {
outputDir.mkdirs()
}
filterJavaDocSource(new File(publication.sdkSourceSet.path), publication.sdkSourceSet.path, javaSource)
return generateJavaDocSourceJar(javaSource)
}
private static File generateJavaDocSourceJar(File sourceDir) {
def p = "jar cvf ../outputs/classes-source.jar .".execute(null, sourceDir)
def shellInfoResultReader = new BufferedReader(new InputStreamReader(p.getInputStream()));
//需要输出缓冲区数据 不然会阻塞在waitFor
String infoLine;
while ((infoLine = shellInfoResultReader.readLine()) != null) {
Logger.buildOutput("脚本文件执行信息:{}", infoLine);
}
def result = p.waitFor()
Logger.buildOutput("jar excute result:${result}")
if (result != 0) {
throw new RuntimeException("failure to make component-sdk java source directory: \n" + p.err.text)
}
@@ -217,6 +270,7 @@ class JarUtil {
/**
* 递归过滤目录找到文件copy到目标输出路径
*
* @param file
* @param prefix
@@ -264,16 +318,67 @@ class JarUtil {
}
}
static boolean isMavenJarExists(Project project, PublicationOption publication) {
String filePath = null
String fileName = publication.artifactId + "-" + publication.sdkVersion + ".jar"
// http://172.16.xxx.xxx:8081/nexus/content/groups/public/com/xxx/cif/xxx-cif-api/0.0.1-SNAPSHOT/xxx-cif-api-0.0.1-20170515.040917-89.jar
String url = Runtimes.sSdkOption.getMavenUrl()
String line = HttpUrlConnectHelper.sendRequest("$url/${publication.groupId.replace('.', '/')}/${publication.artifactId}/${publication.sdkVersion}/$fileName", "HEAD")
if (!TextUtils.isEmpty(line)) {
filePath = "$url/${publication.groupId.replace('.', '/')}/${publication.artifactId}/${publication.sdkVersion}/$fileName"
}
// def name = "component[${publication.groupId}-${publication.artifactId}]Classpath"
// Configuration configuration = project.configurations.create(name)
// if (publication.dependencies != null) {
// if (publication.dependencies.implementation != null) {
// publication.dependencies.implementation.each { dependency ->
//// Logger.buildOutput("packJar: publication:${PublicationUtil.getPublicationId(publication)} move dependencies:${it}")
// if (dependency instanceof PublicationDependencyModuleOption) {
// project.dependencies.add(name, dependency.path)
// } else {
// project.dependencies.add(name, dependency)
// }
// }
// }
// if (publication.dependencies.compileOnly != null) {
// publication.dependencies.compileOnly.each { dependency ->
// if (dependency instanceof PublicationDependencyModuleOption) {
// project.dependencies.add(name, dependency.path)
// } else {
// project.dependencies.add(name, dependency)
// }
// }
// }
// }
// project.dependencies.add(name, PublicationUtil.getMavenGAV(publication))
// try {
// configuration.copy().files.each {
// if (it.name.endsWith(fileName)) {
// filePath = it.absolutePath
// }
// }
// } catch (Exception e) {
//// e.printStackTrace()
// Logger.buildOutput(e.getMessage())
// }
// project.configurations.remove(configuration)
return filePath != null
}
static boolean compareMavenJar(Project project, PublicationOption publication, String localPath) {
String filePath = null
String fileName = publication.artifactId + "-" + publication.version + ".jar"
String fileName = publication.artifactId + "-" + publication.sdkVersion + ".jar"
def name = "component[${publication.groupId}-${publication.artifactId}]Classpath"
Configuration configuration = project.configurations.create(name)
project.dependencies.add(name, publication.groupId + ":" + publication.artifactId + ":" + publication.version)
configuration.copy().files.each {
if (it.name.endsWith(fileName)) {
filePath = it.absolutePath
project.dependencies.add(name, PublicationUtil.getMavenGAV(publication))
try {
configuration.copy().files.each {
if (it.name.endsWith(fileName)) {
filePath = it.absolutePath
}
}
} catch (Exception e) {
// e.printStackTrace()
}
project.configurations.remove(configuration)
if (filePath == null) return false
@@ -341,19 +446,26 @@ class JarUtil {
return jarFile.absolutePath
}
static void handleMavenJar(Project project, PublicationOption publication) {
static String handleMavenJar(Project project, PublicationOption publication) {
long startTime = System.currentTimeMillis()
File target = new File(Runtimes.sSdkDir, PublicationUtil.getJarName(publication))
if (publication.invalid) {
PublicationManager.getInstance().addPublication(publication)
if (target.exists()) {
target.delete()
}
return
return "Handle Maven jar " + PublicationUtil.getJarName(publication) + " cost " + (System.currentTimeMillis() - startTime) + "ms"
}
boolean isMavenJarExists = isMavenJarExists(project, publication)
boolean hasGitDiff = PublicationManager.getInstance().hasModifyWithGitDiff(publication.sdkSourceSet)
boolean hasModifiedSource = PublicationManager.getInstance().hasSdkModified(publication)
boolean hasModifiedSource = PublicationManager.getInstance().hasModified(publication)
if (target.exists()) {
if (!hasGitDiff && isMavenJarExists) {
publication.invalid = false
publication.useLocal = false
PublicationManager.getInstance().addPublication(publication)
return "Handle Maven jar " + PublicationUtil.getJarName(publication) + " cost " + (System.currentTimeMillis() - startTime) + "ms"
} else if (target.exists()) {
if (hasModifiedSource) {
def releaseJar = JarUtil.packJavaSourceJar(project, publication, Runtimes.getAndroidJarPath(), Runtimes.getCompileOption(), true)
if (releaseJar == null) {
@@ -362,52 +474,30 @@ class JarUtil {
if (target.exists()) {
target.delete()
}
return
return "Handle Maven jar " + PublicationUtil.getJarName(publication) + " cost " + (System.currentTimeMillis() - startTime) + "ms"
}
FileUtil.copyFile(releaseJar, target)
}
publication.invalid = false
publication.useLocal = true
PublicationManager.getInstance().addPublication(publication)
} else if (!hasModifiedSource) {
PublicationOption lastPublication = PublicationManager.getInstance().getPublication(publication.groupId, publication.artifactId)
if (lastPublication.version != publication.version) {
publication.versionNew = publication.version
publication.version = lastPublication.version
}
publication.invalid = false
publication.useLocal = false
PublicationManager.getInstance().addPublication(publication)
return
return "Handle Local jar " + PublicationUtil.getJarName(publication) + " cost " + (System.currentTimeMillis() - startTime) + "ms"
} else {
def releaseJar = JarUtil.packJavaSourceJar(project, publication, Runtimes.getAndroidJarPath(), Runtimes.getCompileOption(), false)
def releaseJar = JarUtil.packJavaSourceJar(project, publication, Runtimes.getAndroidJarPath(), Runtimes.getCompileOption(), true)
if (releaseJar == null) {
publication.invalid = true
PublicationManager.getInstance().addPublication(publication)
if (target.exists()) {
target.delete()
}
return
}
PublicationOption lastPublication = PublicationManager.getInstance().getPublication(publication.groupId, publication.artifactId)
if (lastPublication == null) {
lastPublication = publication
}
boolean equals = JarUtil.compareMavenJar(project, lastPublication, releaseJar.absolutePath)
if (equals) {
if (target.exists()) {
target.delete()
}
publication.useLocal = false
} else {
releaseJar = JarUtil.packJavaSourceJar(project, publication, Runtimes.getAndroidJarPath(), Runtimes.getCompileOption(), true)
FileUtil.copyFile(releaseJar, target)
publication.useLocal = true
return "Handle Maven jar " + PublicationUtil.getJarName(publication) + " cost " + (System.currentTimeMillis() - startTime) + "ms"
}
FileUtil.copyFile(releaseJar, target)
publication.useLocal = true
publication.invalid = false
PublicationManager.getInstance().addPublication(publication)
}
return "Handle Local jar " + PublicationUtil.getJarName(publication) + " cost " + (System.currentTimeMillis() - startTime) + "ms"
}
static String handleLocalJar(Project project, PublicationOption publication) {
@@ -423,16 +513,17 @@ class JarUtil {
}
if (target.exists()) {
boolean hasModifiedSource = PublicationManager.getInstance().hasModified(publication)
boolean hasModifiedSource = PublicationManager.getInstance().hasSdkModified(publication)
if (!hasModifiedSource) {
publication.invalid = false
publication.useLocal = true
PublicationManager.getInstance().addPublication(publication)
Logger.buildOutput("${project.name} sdk nothing change,use local cache")
return "Handle Local jar " + PublicationUtil.getJarName(publication) + " cost " + (System.currentTimeMillis() - startTime) + "ms"
}
}
File releaseJar = JarUtil.packJavaSourceJar(project, publication, Runtimes.getAndroidJarPath(), Runtimes.getCompileOption(), true)
File releaseJar = packJavaSourceJar(project, publication, Runtimes.getAndroidJarPath(), Runtimes.getCompileOption(), true)
if (releaseJar == null) {
publication.invalid = true
PublicationManager.getInstance().addPublication(publication)

View File

@@ -1,6 +1,11 @@
package com.plugin.component.utils
import com.android.build.gradle.AppExtension
import com.plugin.component.ComponentPlugin
import com.plugin.component.Constants
import com.plugin.component.extension.PublicationManager
import com.plugin.component.extension.option.sdk.PublicationDependencyModuleOption
import com.plugin.component.extension.option.sdk.SdkOption
import com.plugin.component.log.Logger
import com.plugin.component.Runtimes
import com.plugin.component.extension.module.ProjectInfo
@@ -8,8 +13,17 @@ import com.plugin.component.extension.module.SourceFile
import com.plugin.component.extension.module.SourceSet
import com.plugin.component.extension.option.sdk.PublicationOption
import com.plugin.component.task.CompileSdkTask
import org.apache.http.util.TextUtils
import org.gradle.api.Project
import org.gradle.api.Task
import org.gradle.api.artifacts.Dependency
import org.gradle.api.artifacts.ExcludeRule
import org.gradle.api.component.SoftwareComponent
import org.gradle.api.publish.PublishingExtension
import org.gradle.api.publish.maven.MavenPublication
import org.gradle.api.tasks.TaskProvider
import java.text.SimpleDateFormat
class PublicationUtil {
@@ -25,14 +39,23 @@ class PublicationUtil {
return publication.groupId + '-' + publication.artifactId + '.jar'
}
static getAarName(PublicationOption publication) {
return publication.groupId + '-' + publication.artifactId + '-imp' + '.aar'
}
static getMavenGAV(PublicationOption publication) {
return publication.groupId + ':' + publication.artifactId + ':' + publication.version
return publication.groupId + ':' + publication.artifactId + ':' + publication.sdkVersion
}
static getImpMavenGAV(PublicationOption publication, boolean isRelease) {
return publication.groupId + ':' + publication.getArtifactIdString() + "-imp${isRelease ? '' : '-debug'}" + ':' + publication.implVersion + "@aar"
}
static getLocalGAV(PublicationOption publication) {
return ':' + publication.groupId + '-' + publication.artifactId + ':'
}
/**
* 解析 component 依赖
* @param projectInfo
@@ -57,12 +80,26 @@ class PublicationUtil {
* @return
*/
static parseComponent(String value) {
value = value.replace(Constants.COMPONENT, "")
value = value.replace(Constants.COMPONENT_PRE, "")
String key = ProjectUtil.getComponentValue(value)
PublicationOption publication = Runtimes.getSdkPublication(key)
return getPublication(publication)
}
static parseComponentToPublicationId(String value) {
value = value.replace(Constants.COMPONENT_PRE, "")
String key = ProjectUtil.getComponentValue(value)
PublicationOption publication = Runtimes.getSdkPublication(key)
return getPublicationId(publication)
}
static parseComponentDependency(String value) {
value = value.replace(Constants.COMPONENT_PRE, "")
String key = ProjectUtil.getComponentValue(value)
PublicationOption publication = Runtimes.getSdkPublication(key)
return publication
}
/**
* 获取 publication 依赖
* @param publication
@@ -92,7 +129,13 @@ class PublicationUtil {
dependency = parseComponent(it)
}
Logger.buildOutput("compileOnly " + dependency)
compileOnly dependency
if (dependency instanceof String) {
compileOnly dependency
} else if (dependency instanceof PublicationDependencyModuleOption) {
compileOnly(dependency.path) {
exclude dependency.exclude
}
}
}
}
if (publication.dependencies.implementation != null) {
@@ -102,7 +145,13 @@ class PublicationUtil {
dependency = parseComponent(it)
}
Logger.buildOutput("implementation " + dependency)
implementation dependency
if (dependency instanceof String) {
implementation dependency
} else if (dependency instanceof PublicationDependencyModuleOption) {
implementation(dependency.path) {
exclude dependency.exclude
}
}
}
}
}
@@ -113,91 +162,273 @@ class PublicationUtil {
* @param project
* @param publication
*/
static void initPublication(Project project, PublicationOption publication) {
static void initPublication(Project project, PublicationOption publication, boolean isAutoVersion) {
String displayName = project.getDisplayName()
publication.project = displayName.substring(displayName.indexOf("'") + 1, displayName.lastIndexOf("'"))
def buildSdk = new File(project.projectDir, publication.isSdk ? Constants.BUILD_SDK_DIR : Constants.BUILD_IMPL_DIR)
publication.sourceSetName = publication.scrName
initSdkSourceSet(project, publication, isAutoVersion)
initImpSourceSet(project, publication, isAutoVersion)
}
/**
* 收集实现类相关的信息
* @param project
* @param publication
*/
private static void initImpSourceSet(Project project, PublicationOption publication, boolean isAutoVersion) {
def buildSdk = new File(project.projectDir, Constants.BUILD_IMPL_DIR)
publication.impDir = new File(buildSdk, publication.scrName)
SourceSet impSourceSet = new SourceSet()
def impDir = project.projectDir
impSourceSet.path = impDir.absolutePath
impSourceSet.lastModifiedSourceFile = new HashMap<>()
if (isAutoVersion && !publication.useUserImplVersion) {
String split = "@_@"
String gitInfo = FileUtil.shell("git log --max-count=1 --pretty=format:\"%cd${split}%h${split}%cn${split}%s\" --date=format:'%Y%m%d%H%M%S' ${impDir.absolutePath}")
Logger.buildOutput("filename:$impDir.absolutePath gitInfo$gitInfo")
String[] infos = gitInfo.split(split)
if (infos.size() == 4) {
String commitTime = infos[0]
String gitHash = infos[1]
String commitUser = infos[2]
String commitInfo = infos[3]
String version = "${commitTime}_${gitHash}"
Logger.buildOutput("filename:$impDir.absolutePath git最近提交$version")
if (!TextUtils.isEmpty(version)) {
impSourceSet.gitVersion = version
publication.implVersion = version
impSourceSet.commitTime = commitTime
impSourceSet.commitUser = commitUser
impSourceSet.gitCommitInfo = commitInfo
}
}
}
def sourceDir
if (publication.sourceSetName.contains('/')) {
sourceDir = new File(project.projectDir, publication.sourceSetName)
} else {
sourceDir = new File(project.projectDir, 'src/' + publication.sourceSetName)
}
long quickVerify = 0L
project.fileTree(sourceDir).each {
SourceFile sourceFile = new SourceFile()
sourceFile.path = it.path
sourceFile.lastModified = it.lastModified()
impSourceSet.lastModifiedSourceFile.put(sourceFile.path, sourceFile)
quickVerify += it.lastModified()
}
//检测build.gradle和proguard-rules.pro文件是否有变化
File buildGradle = new File(project.projectDir, 'build.gradle')
if (buildGradle.exists()) {
SourceFile sourceFile = new SourceFile()
sourceFile.path = buildGradle.path
sourceFile.lastModified = buildGradle.lastModified()
impSourceSet.lastModifiedSourceFile.put(sourceFile.path, sourceFile)
quickVerify += buildGradle.lastModified()
}
File proguardRules = new File(project.projectDir, 'proguard-rules.pro')
if (proguardRules.exists()) {
SourceFile sourceFile = new SourceFile()
sourceFile.path = proguardRules.path
sourceFile.lastModified = proguardRules.lastModified()
impSourceSet.lastModifiedSourceFile.put(sourceFile.path, sourceFile)
quickVerify += proguardRules.lastModified()
}
impSourceSet.quickVerifyModified = quickVerify
publication.impSourceSet = impSourceSet
publication.impNeedPack = !impSourceSet.lastModifiedSourceFile.isEmpty()
}
private static void initSdkSourceSet(Project project, PublicationOption publication, boolean isAutoVersion) {
def buildSdk = new File(project.projectDir, Constants.BUILD_SDK_DIR)
publication.buildDir = new File(buildSdk, publication.scrName)
SourceSet misSourceSet = new SourceSet()
def misDir
SourceSet sdkSourceSet = new SourceSet()
def sdkDir
if (publication.sourceSetName.contains('/')) {
misDir = new File(project.projectDir, publication.sourceSetName + '/sdk/')
sdkDir = new File(project.projectDir, publication.sourceSetName + '/sdk/')
} else {
misDir = new File(project.projectDir, 'src/' + publication.sourceSetName + '/sdk/')
sdkDir = new File(project.projectDir, 'src/' + publication.sourceSetName + '/sdk/')
}
misSourceSet.path = misDir.absolutePath
misSourceSet.lastModifiedSourceFile = new HashMap<>()
project.fileTree(misDir).each {
sdkSourceSet.path = sdkDir.absolutePath
sdkSourceSet.lastModifiedSourceFile = new HashMap<>()
long quickVerify = 0L
if (isAutoVersion && !publication.useUserSdkVersion) {
String split = "@_@"
String gitInfo = FileUtil.shell("git log --max-count=1 --pretty=format:\"%cd${split}%h${split}%cn${split}%s\" --date=format:'%Y%m%d%H%M%S' ${sdkDir.absolutePath}")
Logger.buildOutput("filename:$sdkDir.absolutePath gitInfo$gitInfo")
String[] infos = gitInfo.split(split)
if (infos.size() == 4) {
String commitTime = infos[0]
String gitHash = infos[1]
String commitUser = infos[2]
String commitInfo = infos[3]
String version = "${commitTime}_${gitHash}"
Logger.buildOutput("filename:$sdkDir.absolutePath git最近提交$version")
if (!TextUtils.isEmpty(version)) {
sdkSourceSet.gitVersion = version
publication.sdkVersion = version
sdkSourceSet.commitTime = commitTime
sdkSourceSet.commitUser = commitUser
sdkSourceSet.gitCommitInfo = commitInfo
}
}
}
project.fileTree(sdkDir).each {
if (FileUtil.isValidPackSource(it)) {
SourceFile sourceFile = new SourceFile()
sourceFile.path = it.path
sourceFile.lastModified = it.lastModified()
misSourceSet.lastModifiedSourceFile.put(sourceFile.path, sourceFile)
quickVerify += it.lastModified()
sdkSourceSet.lastModifiedSourceFile.put(sourceFile.path, sourceFile)
}
}
sdkSourceSet.quickVerifyModified = quickVerify
publication.misSourceSet = misSourceSet
publication.invalid = misSourceSet.lastModifiedSourceFile.isEmpty()
publication.sdkSourceSet = sdkSourceSet
publication.invalid = quickVerify == 0L
}
static void createPublishingPublication(Project project, PublicationOption publication, String publicationName) {
def publishing = project.extensions.getByName('publishing')
PublishingExtension publishing = project.extensions.getByName(Constants.PUBLISHING)
MavenPublication mavenPublication = publishing.publications.maybeCreate(publicationName, MavenPublication)
mavenPublication.groupId = publication.groupId
mavenPublication.artifactId = publication.artifactId
mavenPublication.version = publication.versionNew != null ? publication.versionNew : publication.version
mavenPublication.version = publication.versionNew != null ? publication.versionNew : publication.sdkVersion
mavenPublication.pom.packaging = 'jar'
publishing.repositories(Runtimes.sSdkOption.repositories)
File target = new File(Runtimes.sSdkDir, PublicationUtil.getJarName(publication))
def outputsDir = new File(publication.buildDir, "outputs")
mavenPublication.artifact source: new File(outputsDir, "classes.jar")
mavenPublication.artifact source: target
mavenPublication.artifact source: new File(outputsDir, "classes-source.jar"), classifier: 'sources'
if (publication.dependencies != null) {
mavenPublication.pom.withXml {
def dependenciesNode = asNode().appendNode('dependencies')
if (publication.dependencies.implementation != null) {
publication.dependencies.implementation.each {
def gav = it.split(":")
if (gav[1].startsWith(Constants.SDK_PRE)) {
PublicationOption dependencyPublication = publicationManager.getPublicationByKey(gav[1].replace(Constants.SDK_PRE, ''))
if (dependencyPublication.useLocal) {
throw new RuntimeException("component publication [$dependencyPublication.groupId:$dependencyPublication.artifactId] has not publish yet.")
}
}
def dependencyNode = dependenciesNode.appendNode('dependency')
dependencyNode.appendNode('groupId', gav[0])
dependencyNode.appendNode('artifactId', gav[1])
dependencyNode.appendNode('version', gav[2])
dependencyNode.appendNode('scope', 'implementation')
}
}
}
}
//todo 存在找不到引用问题 暂不处理
// if (publication.dependencies != null) {
// mavenPublication.pom.withXml {
// def dependenciesNode = asNode().appendNode('dependencies')
// if (publication.dependencies.implementation != null) {
// publication.dependencies.implementation.each {
// String[] gav
// def exclusion
// if (it instanceof PublicationDependencyModuleOption) {
// gav = it.path.split(":")
// exclusion = it.exclude
// } else {
// gav = it.split(":")
// }
// if (gav[1].startsWith(Constants.SDK_PRE)) {
// PublicationOption dependencyPublication = publicationManager.getPublicationByKey(gav[1].replace(Constants.SDK_PRE, ''))
// if (dependencyPublication.useLocal) {
// throw new RuntimeException("component publication [$dependencyPublication.groupId:$dependencyPublication.artifactId] has not publish yet.")
// }
// }
// if (gav.size() == 3) {
// //todo 存在本地引用的情况
// def dependencyNode = dependenciesNode.appendNode('dependency')
// dependencyNode.appendNode('groupId', gav[0])
// dependencyNode.appendNode('artifactId', gav[1])
// dependencyNode.appendNode('version', gav[2])
// dependencyNode.appendNode('scope', 'implementation')
// if (exclusion != null) {
// def exclusionsNode = dependencyNode.appendNode('exclusions')
// def exclusionNode = exclusionsNode.appendNode('exclusion')
// exclusionNode.appendNode('groupId', exclusion['group'])
// exclusionNode.appendNode('artifactId', exclusion['module'])
// }
// }
// }
// }
// }
// }
}
static void createPublishTask(Project project, PublicationOption publication) {
def taskName = 'compileMis[' + publication.artifactId + ']Source'
static Task createPublishTask(Project project, Project androidProject, PublicationOption publication) {
// for test
// TaskProvider<Task> cleanTaskProvider = project.tasks.named("clean")
// Task cleanTask = cleanTaskProvider.get()
def taskName = 'compile[' + publication.artifactId + ']Source'
def compileTask = project.getTasks().findByName(taskName)
if (compileTask == null) {
compileTask = project.getTasks().create(taskName, CompileSdkTask.class)
compileTask.publication = publication
compileTask.dependsOn 'clean'
}
// cleanTask.finalizedBy(compileTask)
def publicationName = 'component[' + publication.artifactId + ']'
def publicationName = 'Component-' + project.name + 'Sdk'
String publishTaskNamePrefix = "publish${publicationName}PublicationTo"
project.tasks.whenTaskAdded {
if (it.name.startsWith(publishTaskNamePrefix)) {
it.dependsOn compileTask
it.doLast {
new File(misDir, PublicationUtil.getJarName(publication)).delete()
publication.invalid = false
publication.useLocal = false
PublicationManager.getInstance().addPublication(publication)
}
}
}
PublicationUtil.createPublishingPublication(project, publication, publicationName)
createPublishingPublication(project, publication, publicationName)
TaskProvider<Task> publishTask = project.tasks.named("${publishTaskNamePrefix}MavenRepository")
compileTask.finalizedBy(publishTask.get())
return compileTask
}
static void createImpPublishingPublication(Project project, PublicationOption publication, String publicationName, boolean isRelease) {
def publishing = project.extensions.getByName(Constants.PUBLISHING)
MavenPublication mavenPublication = publishing.publications.maybeCreate(publicationName, MavenPublication)
File target = new File(Runtimes.sImplDir, getAarName(publication))
if (mavenPublication.getArtifacts().size() != 0) {
//fixme 这里会执行两次所以过滤一下
return
}
mavenPublication.groupId = publication.groupId
if (isRelease) {
mavenPublication.artifactId = publication.getArtifactIdString() + "-imp"
} else {
mavenPublication.artifactId = publication.getArtifactIdString() + "-imp-debug"
}
mavenPublication.version = publication.versionNew != null ? publication.versionNew : publication.implVersion
mavenPublication.pom.packaging = 'aar'
Logger.buildOutput("createImpPublishingPublication ${publicationName} Artifacts:${mavenPublication.getArtifacts().size()}")
mavenPublication.getArtifacts().clear()
mavenPublication.artifact(target.absolutePath)
publishing.repositories(Runtimes.sSdkOption.repositories)
// mavenPublication.pom.withXml {
// def dependenciesNode = asNode().appendNode('dependencies')
// def addDependency = { Dependency dep, String scope ->
// if (dep.group == null || dep.version == null || dep.name == null || dep.name == "unspecified")
// return // ignore invalid dependencies
//
// final dependencyNode = dependenciesNode.appendNode('dependency')
// dependencyNode.appendNode('groupId', dep.group)
// dependencyNode.appendNode('artifactId', dep.name)
// dependencyNode.appendNode('version', dep.version)
// dependencyNode.appendNode('scope', scope)
//
// if (!dep.transitive) {
// // If this dependency is transitive, we should force exclude all its dependencies them from the POM
// final exclusionNode = dependencyNode.appendNode('exclusions').appendNode('exclusion')
// exclusionNode.appendNode('groupId', '*')
// exclusionNode.appendNode('artifactId', '*')
// } else if (!dep.properties.excludeRules.empty) {
// // Otherwise add specified exclude rules
// final exclusionNode = dependencyNode.appendNode('exclusions').appendNode('exclusion')
// dep.properties.excludeRules.each { ExcludeRule rule ->
// exclusionNode.appendNode('groupId', rule.group ?: '*')
// exclusionNode.appendNode('artifactId', rule.module ?: '*')
// }
// }
// }
//
// project.configurations.compile.getDependencies().each { dep -> addDependency(dep, "compile") }
// project.configurations.api.getDependencies().each { dep -> addDependency(dep, "api") }
// project.configurations.implementation.getDependencies().each { dep -> addDependency(dep, "implementation") }
// }
}
/**
@@ -210,7 +441,8 @@ class PublicationUtil {
List<Object> compileOnly = new ArrayList<>()
publication.dependencies.compileOnly.each {
if (it instanceof String && it.startsWith(Constants.COMPONENT_PRE)) {
PublicationOption existPublication = PublicationManager.getInstance().getPublicationByKey(getPublicationId(publication))
// PublicationOption existPublication = PublicationManager.getInstance().getPublicationByKey(getPublicationId(publication))
PublicationOption existPublication = parseComponentDependency(it)
if (existPublication != null) {
if (existPublication.useLocal) {
compileOnly.add(getLocalGAV(existPublication))
@@ -227,13 +459,17 @@ class PublicationUtil {
if (publication.dependencies.implementation != null) {
List<Object> implementation = new ArrayList<>()
publication.dependencies.implementation.each {
// Logger.buildOutput("filterDependencies : publication:${getPublicationId(publication)} implementation: ${it}")
if (it instanceof String && it.startsWith(Constants.COMPONENT_PRE)) {
PublicationOption existPublication = PublicationManager.getInstance().getPublicationByKey(getPublicationId(publication))
// PublicationOption existPublication = PublicationManager.getInstance().getPublicationByKey(getPublicationId(publication))
PublicationOption existPublication = parseComponentDependency(it)
if (existPublication != null) {
if (existPublication.useLocal) {
implementation.add(getLocalGAV(existPublication))
// Logger.buildOutput("filterDependencies : publication:${getPublicationId(publication)} implementation useLocalGav: ${getLocalGAV(existPublication)}")
} else {
implementation.add(getMavenGAV(existPublication))
// Logger.buildOutput("filterDependencies : publication:${getPublicationId(publication)} implementation useMavenGav: ${getMavenGAV(existPublication)}")
}
}
} else {
@@ -244,4 +480,44 @@ class PublicationUtil {
}
}
}
static void handleSdkPublish(Project childProject, Project androidProject, PublicationOption publication, Task dependTask) {
if (publication.sdkVersion != null && publication.sdkNeedPublish) {
if (JarUtil.isMavenJarExists(childProject, publication)) {
publication.sdkNeedPublish = false
return
}
childProject.plugins.apply(Constants.PLUGIN_MAVEN_PUBLISH)
Logger.buildOutput("need publish sdk:${publication.name}")
Task compileTask = createPublishTask(childProject, androidProject, publication)
if (dependTask == null) {
AppExtension appExtension = androidProject.extensions.getByType(AppExtension.class)
appExtension.applicationVariants.each {
TaskProvider<Task> assembleTask = AarUtil.getAssembleTask(androidProject, it)
Logger.buildOutput("getAssembleTask:${assembleTask.name}")
dependTask = assembleTask.get()
dependTask.finalizedBy(compileTask)
}
} else {
compileTask.dependsOn(dependTask)
dependTask.finalizedBy(compileTask)
}
}
}
static void handleImplPublish(Project project, PublicationOption publication, boolean isDebug, Task dependTask) {
Logger.buildOutput("Handle ${publication.name} ImplPublish,isDebug:${isDebug}")
boolean isAarExists = AarUtil.isArrExits(project, publication, !isDebug)
if (isAarExists) {
publication.impNeedPublish = false
return
}
project.plugins.apply(Constants.PLUGIN_MAVEN_PUBLISH)
if (isDebug) {
//注册打包arr task
AarUtil.packImpAar(project, ComponentPlugin.androidProject, publication, dependTask)
} else {
AarUtil.packImpAarRelease(project, ComponentPlugin.androidProject, publication, dependTask)
}
}
}

View File

@@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.3-all.zip

View File

@@ -23,6 +23,25 @@ component {
targetCompatibility JavaVersion.VERSION_1_8
}
//组件发布相关
//是否自动化版本依赖git
// autoVersion true
//是否发布模式
// publishMode false
//maven寻址地址与下面地址一直
// mavenUrl "$ex_private_maven_repository"
//maven发布仓库配置
// repositories {
// maven {
// allowInsecureProtocol true
// credentials {
// username = "$ex_private_maven_username"
// password = "$ex_private_maven_password"
// }
// url = "$ex_private_maven_repository"
// }
// }
configuration {
'library' {
@@ -41,62 +60,64 @@ component {
implementation 'com.google.code.gson:gson:2.8.1'
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation "org.jetbrains.kotlin:kotlin-android-extensions:$kotlin_version"
implementation component(":library")//SDK依赖其他组件
}
}
}
}
pin {
configuration {
'pins' {
codeCheckEnabled true
//参与编译的模块
include ':p_base',':p_common',":p_home"
//对外把暴露的模块
export ':main'
}
}
}
//1.0.10版本暂不支持
// pin {
// configuration {
// 'pins' {
// codeCheckEnabled true
// //参与编译的模块
// include ':p_base',':p_common',":p_home"
// //对外把暴露的模块
// export ':main'
// }
// }
// }
//组件调试声明
debug {
//调试模块随意在当前项目新建一个module用于调试即可
targetModuleName 'debugModule'
//申明调试模块运行时链接组件的资源,表明运行 debugModule 时使用目录资源
targetDebugName 'library'
configuration {
'library' {
dependencies {
//只支持 implementation足够了
implementation component(':library')
}
}
'libraryKotlin' {
dependencies {
implementation component(':libraryKotlin')
}
}
'libraryWithoutPlugin' {
dependencies {
implementation project(':libraryWithoutPlugin')
}
}
'customDebug' {
dependencies {
implementation component(':library')
implementation component(':libraryKotlin')
}
}
}
}
//组件调试声明1.0.10版本暂不支持
// debug {
//
// //调试模块随意在当前项目新建一个module用于调试即可
// targetModuleName 'debugModule'
//
// //申明调试模块运行时链接组件的资源,表明运行 debugModule 时使用目录资源
// targetDebugName 'library'
//
// configuration {
//
// 'library' {
// dependencies {
// //只支持 implementation足够了
// implementation component(':library')
// }
// }
//
// 'libraryKotlin' {
// dependencies {
// implementation component(':libraryKotlin')
// }
// }
//
// 'libraryWithoutPlugin' {
// dependencies {
// implementation project(':libraryWithoutPlugin')
// }
// }
//
// 'customDebug' {
// dependencies {
// implementation component(':library')
// implementation component(':libraryKotlin')
// }
// }
//
// }
// }
}

View File

@@ -5,8 +5,8 @@
//include ':component-plugin'
//调试插件
//includeBuild './component-plugin'
includeBuild './component-plugin'
include ':app', ':pins'
include ':debugModule'
include ':app'/*, ':pins'*/
//include ':debugModule'
include ':library', ':libraryKotlin', ':libraryWithoutPlugin'