1
1
import org.gradle.api.*
2
- import org.gradle.api.file.*
3
2
import org.gradle.api.tasks.bundling.*
4
3
import org.gradle.api.tasks.compile.*
5
4
import org.gradle.kotlin.dsl.*
6
- import org.gradle.util.GUtil.*
7
5
import org.jetbrains.kotlin.gradle.dsl.*
8
- import org.jetbrains.kotlin.gradle.plugin.*
9
6
import org.jetbrains.kotlin.gradle.plugin.mpp.*
10
7
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.*
11
8
import org.jetbrains.kotlin.gradle.targets.jvm.*
@@ -26,54 +23,84 @@ object Java9Modularity {
26
23
logger.warn(" No Kotlin JVM targets found, can't configure compilation of module-info!" )
27
24
}
28
25
jvmTargets.forEach { target ->
29
- target.compilations.forEach { compilation ->
30
- configureModuleInfoForKotlinCompilation(compilation)
31
- }
32
-
33
- if (multiRelease) {
34
- tasks.getByName<Jar >(target.artifactsTaskName) {
35
- rename(" module-info.class" , " META-INF/versions/9/module-info.class" )
26
+ val artifactTask = tasks.getByName<Jar >(target.artifactsTaskName) {
27
+ if (multiRelease) {
36
28
manifest {
37
29
attributes(" Multi-Release" to true )
38
30
}
39
31
}
40
32
}
41
- }
42
- }
43
33
44
- private fun Project.configureModuleInfoForKotlinCompilation (compilation : KotlinCompilation <* >) {
45
- val defaultSourceSet = compilation.defaultSourceSet.kotlin
46
- val moduleInfoSourceFile = defaultSourceSet.find { it.name == " module-info.java" }
34
+ target.compilations.forEach { compilation ->
35
+ val compileKotlinTask = compilation.compileKotlinTask as AbstractCompile
36
+ val defaultSourceSet = compilation.defaultSourceSet
37
+
38
+ // derive the names of the source set and compile module task
39
+ val sourceSetName = defaultSourceSet.name + " Module"
40
+ val compileModuleTaskName = compileKotlinTask.name + " Module"
41
+
42
+ kotlin.sourceSets.create(sourceSetName) {
43
+ val sourceFile = this .kotlin.find { it.name == " module-info.java" }
44
+ val targetFile = compileKotlinTask.destinationDirectory.file(" ../module-info.class" ).get().asFile
47
45
48
- if (moduleInfoSourceFile == null ) {
49
- logger.info(" No module-info.java file found in ${defaultSourceSet.srcDirs} , can't configure compilation of module-info!" )
50
- } else {
51
- val targetName = toCamelCase(compilation.target.targetName)
52
- val compilationName = if (compilation.name != KotlinCompilation .MAIN_COMPILATION_NAME ) toCamelCase(compilation.name) else " "
53
- val compileModuleInfoTaskName = " compile${compilationName} ModuleInfo$targetName "
46
+ // only configure the compilation if necessary
47
+ if (sourceFile != null ) {
48
+ // the default source set depends on this new source set
49
+ defaultSourceSet.dependsOn(this )
54
50
55
- val compileKotlinTask = compilation.compileKotlinTask as AbstractCompile
56
- val modulePath = compileKotlinTask.classpath
51
+ // register a new compile module task
52
+ val compileModuleTask = registerCompileModuleTask(compileModuleTaskName, compileKotlinTask, sourceFile, targetFile)
57
53
58
- val compileModuleInfoTask = registerCompileModuleInfoTask(compileModuleInfoTaskName, modulePath, compileKotlinTask.destinationDirectory, moduleInfoSourceFile)
59
- tasks.getByName(compilation.compileAllTaskName).dependsOn(compileModuleInfoTask)
54
+ // add the resulting module descriptor to this target's artifact
55
+ artifactTask.dependsOn(compileModuleTask)
56
+ artifactTask.from(targetFile) {
57
+ if (multiRelease) {
58
+ into(" META-INF/versions/9/" )
59
+ }
60
+ }
61
+ } else {
62
+ logger.info(" No module-info.java file found in ${this .kotlin.srcDirs} , can't configure compilation of module-info!" )
63
+ // remove the source set to prevent Gradle warnings
64
+ kotlin.sourceSets.remove(this )
65
+ }
66
+ }
67
+ }
60
68
}
61
69
}
62
70
63
- private fun Project.registerCompileModuleInfoTask (taskName : String , modulePath : FileCollection , destinationDir : DirectoryProperty , moduleInfoSourceFile : File ) =
71
+ private fun Project.registerCompileModuleTask (taskName : String , compileTask : AbstractCompile , sourceFile : File , targetFile : File ) =
64
72
tasks.register(taskName, JavaCompile ::class ) {
65
- dependsOn(modulePath)
66
- source(moduleInfoSourceFile)
73
+ // Also add the module-info.java source file to the Kotlin compile task;
74
+ // the Kotlin compiler will parse and check module dependencies,
75
+ // but it currently won't compile to a module-info.class file.
76
+ compileTask.source(sourceFile)
77
+
78
+
79
+ // Configure the module compile task.
80
+ dependsOn(compileTask)
81
+ source(sourceFile)
82
+ outputs.file(targetFile)
67
83
classpath = files()
68
- destinationDirectory.set(destinationDir )
84
+ destinationDirectory.set(compileTask.destinationDirectory )
69
85
sourceCompatibility = JavaVersion .VERSION_1_9 .toString()
70
86
targetCompatibility = JavaVersion .VERSION_1_9 .toString()
87
+
71
88
doFirst {
89
+ // Provide the module path to the compiler instead of using a classpath.
90
+ // The module path should be the same as the classpath of the compiler.
72
91
options.compilerArgs = listOf (
73
92
" --release" , " 9" ,
74
- " --module-path" , modulePath .asPath,
93
+ " --module-path" , compileTask.classpath .asPath,
75
94
" -Xlint:-requires-transitive-automatic"
76
95
)
77
96
}
97
+
98
+ doLast {
99
+ // Move the compiled file out of the Kotlin compile task's destination dir,
100
+ // so it won't disturb Gradle's caching mechanisms.
101
+ val compiledFile = destinationDirectory.file(targetFile.name).get().asFile
102
+ targetFile.parentFile.mkdirs()
103
+ compiledFile.renameTo(targetFile)
104
+ }
78
105
}
79
106
}
0 commit comments