5
5
import org.gradle.api.*
6
6
import org.gradle.api.attributes.*
7
7
import org.gradle.api.file.*
8
- import org.gradle.api.provider.*
9
- import org.gradle.api.specs.*
8
+ import org.gradle.api.tasks.*
10
9
import org.gradle.api.tasks.bundling.*
11
10
import org.gradle.api.tasks.compile.*
12
11
import org.gradle.jvm.toolchain.*
13
12
import org.gradle.kotlin.dsl.*
14
- import org.gradle.api.logging.Logger
13
+ import org.gradle.work.*
15
14
import org.jetbrains.kotlin.gradle.dsl.*
16
- import java.io.*
17
15
18
16
/* *
19
17
* This object configures the Java compilation of a JPMS (aka Jigsaw) module descriptor.
@@ -27,30 +25,40 @@ import java.io.*
27
25
*/
28
26
object Java9Modularity {
29
27
30
- private class ModuleInfoFilter (
31
- private val compileKotlinTaskPath : String ,
32
- private val javaVersionProvider : Provider <JavaVersion >,
33
- private val moduleInfoFile : File ,
34
- private val logger : Logger
35
- ) : Spec<FileTreeElement> {
36
- private val isJava9Compatible
37
- get() = javaVersionProvider.orNull?.isJava9Compatible == true
38
- private var logged = false
39
-
40
- private fun logStatusOnce () {
41
- if (logged) return
42
- if (isJava9Compatible) {
43
- logger.info(" Module-info checking is enabled; $compileKotlinTaskPath is compiled using Java ${javaVersionProvider.get()} " )
44
- } else {
45
- logger.info(" Module-info checking is disabled" )
28
+ /* *
29
+ * Task that patches `module-info.java` and removes `requires kotlinx.atomicfu` directive.
30
+ *
31
+ * To have JPMS properly supported, Kotlin compiler **must** be supplied with the correct `module-info.java`.
32
+ * The correct module info has to contain `atomicfu` requirement because atomicfu plugin kicks-in **after**
33
+ * the compilation process. But `atomicfu` is compile-only dependency that shouldn't be present in the final
34
+ * `module-info.java` and that's exactly what this task ensures.
35
+ */
36
+ abstract class ProcessModuleInfoFile : DefaultTask () {
37
+ @get:InputFile
38
+ @get:NormalizeLineEndings
39
+ abstract val moduleInfoFile: RegularFileProperty
40
+
41
+ @get:OutputFile
42
+ abstract val processedModuleInfoFile: RegularFileProperty
43
+
44
+ private val projectPath = project.path
45
+
46
+ @TaskAction
47
+ fun process () {
48
+ val sourceFile = moduleInfoFile.get().asFile
49
+ if (! sourceFile.exists()) {
50
+ throw IllegalStateException (" $sourceFile not found in $projectPath " )
51
+ }
52
+ val outputFile = processedModuleInfoFile.get().asFile
53
+ sourceFile.useLines { lines ->
54
+ outputFile.outputStream().bufferedWriter().use { writer ->
55
+ for (line in lines) {
56
+ if (" kotlinx.atomicfu" in line) continue
57
+ writer.write(line)
58
+ writer.newLine()
59
+ }
60
+ }
46
61
}
47
- logged = true
48
- }
49
-
50
- override fun isSatisfiedBy (element : FileTreeElement ): Boolean {
51
- logStatusOnce()
52
- if (isJava9Compatible) return false
53
- return element.file == moduleInfoFile
54
62
}
55
63
}
56
64
@@ -74,12 +82,13 @@ object Java9Modularity {
74
82
)
75
83
}
76
84
85
+ val processModuleInfoFile by tasks.registering(ProcessModuleInfoFile ::class ) {
86
+ moduleInfoFile.set(file(" ${target.name.ifEmpty { " ." }} /src/module-info.java" ))
87
+ processedModuleInfoFile.set(project.layout.buildDirectory.file(" generated-sources/module-info-processor/module-info.java" ))
88
+ }
89
+
77
90
val compileJavaModuleInfo = tasks.register(" compileModuleInfoJava" , JavaCompile ::class .java) {
78
91
val moduleName = project.name.replace(' -' , ' .' ) // this module's name
79
- val sourceFile = file(" ${target.name.ifEmpty { " ." }} /src/module-info.java" )
80
- if (! sourceFile.exists()) {
81
- throw IllegalStateException (" $sourceFile not found in $project " )
82
- }
83
92
val compileKotlinTask =
84
93
compilation.compileTaskProvider.get() as ? org.jetbrains.kotlin.gradle.tasks.KotlinCompile
85
94
? : error(" Cannot access Kotlin compile task ${compilation.compileKotlinTaskName} " )
@@ -97,15 +106,9 @@ object Java9Modularity {
97
106
// Note that we use the parent dir and an include filter,
98
107
// this is needed for Gradle's module detection to work in
99
108
// org.gradle.api.tasks.compile.JavaCompile.createSpec
100
- source(sourceFile.parentFile)
101
- include { it.file == sourceFile }
102
-
103
- // The Kotlin compiler will parse and check module dependencies,
104
- // but it currently won't compile to a module-info.class file.
105
- // Note that module checking only works on JDK 9+,
106
- // because the JDK built-in base modules are not available in earlier versions.
107
- val javaVersionProvider = compileKotlinTask.kotlinJavaToolchain.javaVersion
108
- compileKotlinTask.exclude(ModuleInfoFilter (compileKotlinTask.path, javaVersionProvider, sourceFile, logger))
109
+ source(processModuleInfoFile.map { it.processedModuleInfoFile.asFile.get().parentFile })
110
+ val generatedModuleInfoFile = processModuleInfoFile.flatMap { it.processedModuleInfoFile.asFile }
111
+ include { it.file == generatedModuleInfoFile.get() }
109
112
110
113
// Set the task outputs and destination directory
111
114
outputs.dir(targetDir)
0 commit comments