11@file:Suppress(" unused" )
22
3+ package buildsrc
4+
35import org.gradle.api.Project
4- import org.gradle.api.artifacts.Dependency
5- import org.gradle.api.artifacts.dsl.DependencyHandler
66import org.gradle.api.tasks.SourceSet
77import org.gradle.api.tasks.SourceSetContainer
88import org.gradle.kotlin.dsl.dependencies
99import org.gradle.kotlin.dsl.kotlin
1010import org.gradle.kotlin.dsl.project
1111
1212@DslMarker
13- annotation class ModuleBuilderMarker
13+ internal annotation class ModuleBuilderMarker
1414
1515@ModuleBuilderMarker
16- class ModuleScope (val moduleId : String , val project : Project , val sourceSet : SourceSet ) {
16+ internal class ModuleScope (val moduleId : String , val project : Project , val sourceSet : SourceSet ) {
1717 val exposedConfigurationName get() = sourceSet.apiConfigurationName.replace(" Api" , " Exposed" )
1818
19- fun DependencyHandler. dependsOnModule (module : String , project : Project = this@ModuleScope .project): Dependency ? {
19+ fun dependsOnModule (module : String , project : Project = this.project) {
2020 val sourceSet = project.sourceSets.getByName(mapIdToSourceSetName(module))
21- return dependsOn(ModuleScope (module, project, sourceSet))
21+ dependsOn(ModuleScope (module, project, sourceSet))
2222 }
2323
24- fun DependencyHandler.dependsOn (module : ModuleScope ): Dependency ? {
25- return add(sourceSet.apiConfigurationName, project(module.project.path, module.exposedConfigurationName))
24+ fun dependsOn (module : ModuleScope ) {
25+ project.dependencies {
26+ add(
27+ sourceSet.apiConfigurationName,
28+ project(module.project.path, module.exposedConfigurationName)
29+ )
30+ }
2631 }
2732
28- fun DependencyHandler. api (dep : Any ) = add(sourceSet.apiConfigurationName, dep)
29- fun DependencyHandler. implementation (dep : Any ) = add(sourceSet.implementationConfigurationName, dep)
33+ fun api (dep : Any ) = project.dependencies. add(sourceSet.apiConfigurationName, dep)
34+ fun implementation (dep : Any ) = project.dependencies. add(sourceSet.implementationConfigurationName, dep)
3035}
3136
3237private fun mapIdToSourceSetName (id : String ) = id.replace(' /' , ' .' )
3338
34- @ModuleBuilderMarker
35- fun Project.defineModule (
39+ // Child directories with their own `.metadata` become standalone modules,
40+ // so the parent source set should exclude them from compilation.
41+ private fun Project.excludeNestedMetadataModules (moduleId : String , sourceSet : SourceSet ) {
42+ val moduleDir = projectDir.resolve(moduleId)
43+ if (! moduleDir.isDirectory) return
44+
45+ moduleDir.walkTopDown()
46+ .filter { it.isDirectory && it != moduleDir && it.resolve(" .metadata" ).isFile }
47+ .forEach { childDir ->
48+ val relative = childDir.relativeTo(moduleDir).invariantSeparatorsPath
49+ sourceSet.java.exclude(" $relative /**" )
50+ }
51+ }
52+
53+ // Create the backing SourceSet and base configurations for a script module.
54+ internal fun Project.createModule (
3655 name : String ,
3756 onlyLibrary : Boolean = false,
38- body : ModuleScope .() -> Unit ,
39- ) {
57+ ): ModuleScope {
4058 val sourceSet = sourceSets.create(mapIdToSourceSetName(name)) {
41- if (! onlyLibrary){
59+ if (! onlyLibrary) {
4260 java.srcDir(name)
4361 java.exclude(" lib/**" )
4462 }
4563 // 独立设置成srcDir,这样可以自定义package,不需要包含lib前缀。
4664 java.srcDir(" $name /lib" )
4765 }
48- ModuleScope (name, project, sourceSet).apply {
66+ excludeNestedMetadataModules(name, sourceSet)
67+ return ModuleScope (name, project, sourceSet).apply {
4968 configurations.create(exposedConfigurationName) {
5069 extendsFrom(configurations.getByName(sourceSet.apiConfigurationName))
5170 isCanBeConsumed = true
@@ -56,30 +75,15 @@ fun Project.defineModule(
5675 implementation(rootProject)
5776 add(exposedConfigurationName, sourceSet.output)
5877 }
59- body()
6078 }
6179}
6280
63- @ModuleBuilderMarker
64- fun ModuleScope.subModule (
65- name : String ,
66- onlyLibrary : Boolean = false,
67- body : ModuleScope .() -> Unit ,
68- ) {
69- val parent = this @subModule
70- val project = parent.project
71-
72- val id = " ${parent.moduleId} /$name "
73- parent.sourceSet.java.exclude(" $name /**" )
74- project.dependencies {
75- project.defineModule(id, onlyLibrary = onlyLibrary) {
76- dependsOn(parent)
77- body()
78- }
79- }
81+ // Apply additional module wiring after all dependent SourceSets are available.
82+ internal fun configureModule (scope : ModuleScope , body : ModuleScope .() -> Unit ) {
83+ scope.body()
8084}
8185
8286private val Project .sourceSets
8387 get() = project.extensions.getByType(
8488 SourceSetContainer ::class .java
85- )
89+ )
0 commit comments