-
Notifications
You must be signed in to change notification settings - Fork 23
/
settings.gradle.kts
140 lines (122 loc) · 4.76 KB
/
settings.gradle.kts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
includeBuild("./buildPlugin")
include(
":lib-dimen",
":lib-utils",
":lib-screenadapter",
)
includeModules(
":lib-eventbus",
":lib-http",
":lib-imageloader",
":lib-scan",
":lib-uikit",
":lib-router",
)
/**=================================================================================================
* 将容器module中的子module导入到项目中
* 核心代码是:
* <code>
* // 将module添加到项目构建中
* include([modulePath])
* // 设置module所在的文件目录
* project([modulePath]).projectDir = File([module的目录])
* </code>
* 使用上述代码,可将指定的module导入项目中,例如导入项目外部的module到本项目中
*================================================================================================*/
fun includeModules(vararg paths: String, with: (ModuleSpec.() -> Unit)? = null) {
if (the<ExtraPropertiesExtension>().properties["mavenDep"] == "true" && paths.contains(":module-dynamic")
.not()
) return
paths.forEach {
includeModule(it, with)
}
}
fun includeModule(path: String, with: (ModuleSpec.() -> Unit)? = null) {
val moduleSpec = ModuleSpec()
with?.invoke(moduleSpec)
// 容器module的目录路径
val moduleDir = File(rootDir, path.replace(':', '/'))
if (moduleDir.exists()) {
include(path)
val containerModule = project(path)
// 设置容器module的目录路径,这一步一定要有
containerModule.projectDir = moduleDir
// 获取settings.gradle文件,此文件中配置了哪些module需要被include
// 注意:此处设置文件名为settings.gradle,必须module中的文件名必须与其一致,不能使用其Kotlin格式的settings.gradle.kts
val settingsFile = File(moduleDir, "settings.gradle")
if (settingsFile.exists()) {
// 从settingsFile中提取include()方法信息,转到SettingsProxy中处理
// containerModule只是一个容器,containerModule内部的子module才是真正有用的module
apply {
from(settingsFile)
to(SettingsProxy(settings, containerModule, moduleSpec))
}
}
moduleDir.walk().maxDepth(1).filter { it.isDirectory && it != moduleDir }.forEach {
val settingsFileInternal = File(it, "settings.gradle")
if (settingsFileInternal.exists()) {
val moduleInternal = settings.findProject("$path:${it.name}")
if (moduleInternal != null) {
moduleInternal.projectDir = it
apply {
from(settingsFileInternal)
to(SettingsProxy(settings, moduleInternal, moduleSpec))
}
}
}
}
}
}
/**
* 容器module的配置类,例如哪些子module需要被过滤或排除
*/
class ModuleSpec {
private val mExcludes = mutableSetOf<String>()
private var mFilter: ((String) -> Boolean)? = null
fun exclude(vararg paths: String) {
mExcludes.addAll(paths)
}
fun filter(predicate: (String) -> Boolean) {
mFilter = predicate
}
fun accept(path: String): Boolean {
if (mExcludes.contains(path)) {
return false
}
if (mFilter?.invoke(path) == true) {
return false
}
return true
}
}
class SettingsProxy(
private var mSettings: Settings, // Settings对象
private var mModule: ProjectDescriptor, // 容器module
private var mModuleSpec: ModuleSpec // 容器module的配置
) {
fun getRootProject(): ProjectDescriptor {
return mModule
}
/**
* 此方法名必须与settings.gradle中定义的方法名一致,即include
*/
fun include(vararg paths: String) {
paths.forEach {
if (mModuleSpec.accept(it.replace(":", ""))) {
val descendantPath = generateDescendantPath(it)
mSettings.include(descendantPath)
val descendantProjectDir = File(mModule.projectDir, it.replace(':', '/'))
mSettings.project(descendantPath).projectDir = descendantProjectDir
}
}
}
fun project(path: String): ProjectDescriptor {
return mSettings.project("${mModule.path}$path")
}
private fun generateDescendantPath(path: String): String {
// 此处使用"${parentModule.path}${path}"而不是"${path}"是因为如果有很多子module时,直接导入短时间内会分不清它来自哪个容器module,
// 在前面加上容器module的path,则可以让我们清晰知道当前子module从属于哪个容器module,如[:libs:lib-data]
return "${mModule.path}$path"
}
}
include(":lib-router:sample")