#0 升级1.0.10版本
This commit is contained in:
@@ -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')
|
||||
}
|
||||
|
||||
|
||||
10
build.gradle
10
build.gradle
@@ -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'
|
||||
|
||||
@@ -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'
|
||||
//}
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
"""
|
||||
}
|
||||
@@ -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"
|
||||
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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提交时间
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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 + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
@@ -28,7 +28,7 @@ class BasePlugin extends AbsPlugin {
|
||||
}
|
||||
|
||||
@Override
|
||||
void afterEvaluateAfterAndroidPlugin(Project project) {
|
||||
void afterEvaluateAfterAndroidPlugin(Project project, Project androidProject) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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 aar:project: $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())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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 "";
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -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
|
||||
|
||||
@@ -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')
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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'
|
||||
|
||||
Reference in New Issue
Block a user