Getting JPMS to compile + assemble jars
This commit is contained in:
parent
fcbb4c93ce
commit
6eeecf0b41
@ -24,10 +24,12 @@ import org.gradle.api.Plugin
|
|||||||
import org.gradle.api.Project
|
import org.gradle.api.Project
|
||||||
import org.gradle.api.file.DuplicatesStrategy
|
import org.gradle.api.file.DuplicatesStrategy
|
||||||
import org.gradle.api.plugins.JavaPluginConvention
|
import org.gradle.api.plugins.JavaPluginConvention
|
||||||
|
import org.gradle.api.plugins.JavaPluginExtension
|
||||||
import org.gradle.api.specs.Specs
|
import org.gradle.api.specs.Specs
|
||||||
import org.gradle.api.tasks.SourceSetContainer
|
import org.gradle.api.tasks.SourceSetContainer
|
||||||
import org.gradle.api.tasks.compile.JavaCompile
|
import org.gradle.api.tasks.compile.JavaCompile
|
||||||
import org.gradle.jvm.tasks.Jar
|
import org.gradle.jvm.tasks.Jar
|
||||||
|
import org.gradle.util.GradleVersion
|
||||||
import org.jetbrains.kotlin.gradle.dsl.KotlinJvmOptions
|
import org.jetbrains.kotlin.gradle.dsl.KotlinJvmOptions
|
||||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||||
import java.io.File
|
import java.io.File
|
||||||
@ -588,4 +590,67 @@ open class StaticMethodsAndTools(private val project: Project) {
|
|||||||
block(SourceSetContainer2(javaX))
|
block(SourceSetContainer2(javaX))
|
||||||
return javaX
|
return javaX
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Should gradle try to infer that this project is a JPMS module by analysing JARs and the classpath?
|
||||||
|
*
|
||||||
|
* Only possible for gradle >= 6.4
|
||||||
|
*/
|
||||||
|
fun inferJpmsModule() {
|
||||||
|
if (GradleVersion.current() >= GradleVersion.version("6.4")) {
|
||||||
|
project.gradle.taskGraph.whenReady {
|
||||||
|
project.convention.configure(JavaPluginExtension::class.java) {
|
||||||
|
// Should a --module-path be inferred by analysing JARs and class folders on the classpath?
|
||||||
|
it.modularity.inferModulePath.set(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fix issues where code (usually test code) needs access to **INTERNAL** scope objects.
|
||||||
|
* -- at the moment, this only fixes gradle -- not intellij
|
||||||
|
* There are also gradle 8 warnings when using this.
|
||||||
|
*
|
||||||
|
* https://stackoverflow.com/questions/59072889/how-to-test-kotlin-function-declared-internal-from-within-tests-when-java-test
|
||||||
|
* https://youtrack.jetbrains.com/issue/KT-20760
|
||||||
|
* https://youtrack.jetbrains.com/issue/KT-45787
|
||||||
|
* https://stackoverflow.com/questions/57050889/kotlin-internal-members-not-accessible-from-alternative-test-source-set-in-gradl
|
||||||
|
* https://youtrack.jetbrains.com/issue/KT-34901
|
||||||
|
*
|
||||||
|
* (related)
|
||||||
|
* https://github.com/JetBrains/kotlin/blob/master/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2JVMCompilerArguments.kt
|
||||||
|
* https://github.com/bazelbuild/rules_kotlin/pull/465
|
||||||
|
* https://github.com/bazelbuild/rules_kotlin/issues/211
|
||||||
|
*
|
||||||
|
* Two things are required for this to work
|
||||||
|
*
|
||||||
|
* 1) The kotlin module names must be the same
|
||||||
|
* 2) The kotlin modules must be associated
|
||||||
|
*/
|
||||||
|
fun allowKotlinInternalAccessForTests(moduleName: String, vararg accessGroup: AccessGroup) {
|
||||||
|
// Make sure to cleanup the any possible license file on clean
|
||||||
|
println("\tAllowing kotlin internal access for $moduleName")
|
||||||
|
|
||||||
|
project.tasks.withType(KotlinCompile::class.java).forEach {
|
||||||
|
it.kotlinOptions.moduleName = moduleName // must be the same module name for everything!
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
accessGroup.forEach {
|
||||||
|
// allow code in a *different* directory access to "internal" scope members of code.
|
||||||
|
// THIS FIXES GRADLE - BUT NOT INTELLIJ!
|
||||||
|
val kotlinExt = project.extensions.getByName("kotlin") as org.jetbrains.kotlin.gradle.dsl.KotlinJvmProjectExtension
|
||||||
|
kotlinExt.target.compilations.getByName(it.sourceName).apply {
|
||||||
|
it.targetNames.forEach { targetName ->
|
||||||
|
associateWith(target.compilations.getByName(targetName))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class AccessGroup(val sourceName: String, vararg targetNames: String) {
|
||||||
|
val targetNames: Array<out String> = targetNames
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
335
src/dorkbox/gradle/jpms/JavaXConfiguration.kt
Normal file
335
src/dorkbox/gradle/jpms/JavaXConfiguration.kt
Normal file
@ -0,0 +1,335 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2021 dorkbox, llc
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package dorkbox.gradle.jpms
|
||||||
|
|
||||||
|
import dorkbox.gradle.kotlin
|
||||||
|
import org.gradle.api.GradleException
|
||||||
|
import org.gradle.api.JavaVersion
|
||||||
|
import org.gradle.api.Project
|
||||||
|
import org.gradle.api.internal.HasConvention
|
||||||
|
import org.gradle.api.tasks.SourceSet
|
||||||
|
import org.gradle.api.tasks.SourceSetContainer
|
||||||
|
import org.gradle.api.tasks.bundling.Jar
|
||||||
|
import org.gradle.api.tasks.compile.JavaCompile
|
||||||
|
import org.gradle.api.tasks.testing.Test
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.getKotlinPluginVersion
|
||||||
|
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
// from: http://mail.openjdk.java.net/pipermail/jigsaw-dev/2017-February/011306.html
|
||||||
|
/// If you move the module-info.java to the top-level directory directory then I would expect this should work:
|
||||||
|
//
|
||||||
|
//javac --release 8 -d target/classes src/main/java/com/example/A.java src/main/java/com/example/Version.java
|
||||||
|
//javac -d target/classes src/main/java/module-info.java
|
||||||
|
//javac -d target/classes-java9 -cp target/classes src/main/java9/com/example/A.java
|
||||||
|
//jar --create --file mr.jar -C target/classes . --release 9 -C
|
||||||
|
//target/classes-java9 .
|
||||||
|
|
||||||
|
@Suppress("MemberVisibilityCanBePrivate")
|
||||||
|
class JavaXConfiguration(javaVersion: JavaVersion, private val project: Project) {
|
||||||
|
val ver: String = javaVersion.majorVersion
|
||||||
|
|
||||||
|
// this cannot be ONLY a number, there must be something else -- intellij will *not* pickup the name if it's only a number
|
||||||
|
val nameX = "_$ver"
|
||||||
|
|
||||||
|
// If kotlin files are present(meaning kotlin is used), we should setup the kotlin tasks
|
||||||
|
val hasKotlin = project.projectDir.walkTopDown().find { it.extension == "kt" }?.exists() ?: false
|
||||||
|
val hasJava = project.projectDir.walkTopDown().find {
|
||||||
|
it.extension == "java" && !(it.name == "module-info.java" ||
|
||||||
|
it.name == "package-info.java" ||
|
||||||
|
it.name == "EmptyClass.java") }?.exists() ?: false
|
||||||
|
|
||||||
|
val moduleFile = project.projectDir.walkTopDown().find { it.name == "module-info.java" }
|
||||||
|
var moduleName: String
|
||||||
|
|
||||||
|
val sourceSets = project.extensions.getByName("sourceSets") as SourceSetContainer
|
||||||
|
|
||||||
|
// standard
|
||||||
|
val main: SourceSet = sourceSets.named("main", org.gradle.api.tasks.SourceSet::class.java).get()
|
||||||
|
val test: SourceSet = sourceSets.named("test", org.gradle.api.tasks.SourceSet::class.java).get()
|
||||||
|
|
||||||
|
val compileMainJava: JavaCompile = project.tasks.named("compileJava", JavaCompile::class.java).get()
|
||||||
|
val compileTestJava: JavaCompile = project.tasks.named("compileTestJava", JavaCompile::class.java).get()
|
||||||
|
lateinit var compileMainKotlin: KotlinCompile
|
||||||
|
lateinit var compileTestKotlin: KotlinCompile
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// plugin provided
|
||||||
|
val mainX: SourceSet = sourceSets.maybeCreate("main$nameX")
|
||||||
|
val testX: SourceSet = sourceSets.maybeCreate("test$nameX")
|
||||||
|
|
||||||
|
// the compile task NAME must match the source-set name
|
||||||
|
val compileMainXJava: JavaCompile = project.tasks.named("compileMain${nameX}Java", JavaCompile::class.java).get()
|
||||||
|
val compileTestXJava: JavaCompile = project.tasks.named("compileTest${nameX}Java", JavaCompile::class.java).get()
|
||||||
|
|
||||||
|
val compileModuleInfoX: JavaCompile = project.tasks.create("compileModuleInfo$nameX", JavaCompile::class.java)
|
||||||
|
|
||||||
|
lateinit var compileMainXKotlin: KotlinCompile
|
||||||
|
lateinit var compileTestXKotlin: KotlinCompile
|
||||||
|
|
||||||
|
// have to create a task in order to the files to get "picked up" by intellij/gradle. No *test* task? Then gradle/intellij won't be able run
|
||||||
|
// the tests, even if you MANUALLY tell intellij to run a test from the sources dir
|
||||||
|
// https://docs.gradle.org/current/dsl/org.gradle.api.tasks.testing.Test.html
|
||||||
|
val runTestX: Test = project.tasks.create("test${nameX}", Test::class.java)
|
||||||
|
|
||||||
|
init {
|
||||||
|
if (moduleFile == null) {
|
||||||
|
throw GradleException("Cannot manage JPMS build without a `module-info` file.")
|
||||||
|
}
|
||||||
|
// also the source dirs have been configured/setup.
|
||||||
|
moduleName = moduleFile.readLines()[0].split(" ")[1].trimEnd('{')
|
||||||
|
if (moduleName.isEmpty()) {
|
||||||
|
throw GradleException("The module name must be specified in the module-info file! Verify file: $moduleFile")
|
||||||
|
}
|
||||||
|
|
||||||
|
val info = when {
|
||||||
|
hasJava && hasKotlin -> "Initializing [JPMS $ver] '$moduleName' -> Java/Kotlin"
|
||||||
|
hasJava -> "Initializing [JPMS $ver] '$moduleName' -> Java"
|
||||||
|
hasKotlin -> "Initializing [JPMS $ver] '$moduleName' -> Kotlin"
|
||||||
|
else -> throw GradleException("Unable to initialize unknown JPMS type, no Java or Kotlin files found.")
|
||||||
|
}
|
||||||
|
println("\t$info")
|
||||||
|
|
||||||
|
if (hasKotlin) {
|
||||||
|
// can only setup the NORMAL tasks first
|
||||||
|
compileMainKotlin = project.tasks.named("compileKotlin", KotlinCompile::class.java).get()
|
||||||
|
compileTestKotlin = project.tasks.named("compileTestKotlin", KotlinCompile::class.java).get()
|
||||||
|
}
|
||||||
|
|
||||||
|
// setup compile/runtime project dependencies
|
||||||
|
mainX.apply {
|
||||||
|
java.apply {
|
||||||
|
// I don't like the opinionated sonatype directory structure.
|
||||||
|
setSrcDirs(project.files("src$ver"))
|
||||||
|
include("**/*.java") // want to include java files for the source. 'setSrcDirs' resets includes...
|
||||||
|
exclude("**/module-info.java", "**/EmptyClass.java") // we have to compile these in a different step!
|
||||||
|
|
||||||
|
// note: if we set the destination path, that location will be DELETED when the compile for these sources starts...
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasKotlin) {
|
||||||
|
kotlin {
|
||||||
|
setSrcDirs(project.files("src$ver"))
|
||||||
|
include("**/*.kt") // want to include java files for the source. 'setSrcDirs' resets includes...
|
||||||
|
|
||||||
|
// note: if we set the destination path, that location will be DELETED when the compile for these sources starts...
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resources.setSrcDirs(project.files("resources$ver"))
|
||||||
|
|
||||||
|
compileClasspath += main.compileClasspath + main.output
|
||||||
|
runtimeClasspath += main.runtimeClasspath + main.output + compileClasspath
|
||||||
|
}
|
||||||
|
testX.apply {
|
||||||
|
java.apply {
|
||||||
|
setSrcDirs(project.files("test$ver"))
|
||||||
|
include("**/*.java") // want to include java files for the source. 'setSrcDirs' resets includes...
|
||||||
|
|
||||||
|
// note: if we set the destination path, that location will be DELETED when the compile for these sources starts...
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasKotlin) {
|
||||||
|
kotlin {
|
||||||
|
setSrcDirs(project.files("test$ver"))
|
||||||
|
include("**/*.kt") // want to include java files for the source. 'setSrcDirs' resets includes...
|
||||||
|
|
||||||
|
// note: if we set the destination path, that location will be DELETED when the compile for these sources starts...
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resources.setSrcDirs(project.files("testResources$ver"))
|
||||||
|
|
||||||
|
compileClasspath += mainX.compileClasspath + test.compileClasspath + test.output
|
||||||
|
runtimeClasspath += mainX.runtimeClasspath + test.runtimeClasspath + test.output
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// run the testX verification
|
||||||
|
runTestX.apply {
|
||||||
|
dependsOn("test")
|
||||||
|
description = "Runs Java $ver tests"
|
||||||
|
group = "verification"
|
||||||
|
|
||||||
|
outputs.upToDateWhen { false }
|
||||||
|
shouldRunAfter("test")
|
||||||
|
|
||||||
|
// The directories for the compiled test sources.
|
||||||
|
testClassesDirs = testX.output.classesDirs
|
||||||
|
classpath = testX.runtimeClasspath
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////
|
||||||
|
// done setting info for the source-sets, now we can setup configurations and other tasks
|
||||||
|
// if this is done out-of-order, things aren't configured correctly
|
||||||
|
//////////////
|
||||||
|
|
||||||
|
if (hasKotlin) {
|
||||||
|
compileMainXKotlin = project.tasks.named("compileMain${nameX}Kotlin", KotlinCompile::class.java).get()
|
||||||
|
compileTestXKotlin = project.tasks.named("compileTest${nameX}Kotlin", KotlinCompile::class.java).get()
|
||||||
|
}
|
||||||
|
|
||||||
|
// have to setup the configurations, so dependencies work correctly
|
||||||
|
val configs = project.configurations
|
||||||
|
configs.maybeCreate("main${nameX}Implementation").extendsFrom(configs.getByName("implementation")).extendsFrom(configs.getByName("compileOnly"))
|
||||||
|
configs.maybeCreate("main${nameX}Runtime").extendsFrom(configs.getByName("implementation")).extendsFrom(configs.getByName("runtimeOnly"))
|
||||||
|
|
||||||
|
configs.maybeCreate("test${nameX}Implementation").extendsFrom(configs.getByName("testImplementation")).extendsFrom(configs.getByName("testCompileOnly"))
|
||||||
|
configs.maybeCreate("test${nameX}Runtime").extendsFrom(configs.getByName("testImplementation")).extendsFrom(configs.getByName("testRuntimeOnly"))
|
||||||
|
|
||||||
|
|
||||||
|
// setup task graph and compile version
|
||||||
|
compileMainXJava.apply {
|
||||||
|
dependsOn(compileMainJava)
|
||||||
|
sourceCompatibility = ver
|
||||||
|
targetCompatibility = ver
|
||||||
|
}
|
||||||
|
compileTestXJava.apply {
|
||||||
|
dependsOn(compileTestJava)
|
||||||
|
sourceCompatibility = ver
|
||||||
|
targetCompatibility = ver
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (hasKotlin) {
|
||||||
|
compileMainXKotlin.apply {
|
||||||
|
dependsOn(compileMainKotlin)
|
||||||
|
sourceCompatibility = ver
|
||||||
|
targetCompatibility = ver
|
||||||
|
kotlinOptions.jvmTarget = ver
|
||||||
|
kotlinOptions.moduleName = compileMainKotlin.kotlinOptions.moduleName // must be the same module name
|
||||||
|
}
|
||||||
|
|
||||||
|
compileTestXKotlin.apply {
|
||||||
|
dependsOn(compileTestKotlin)
|
||||||
|
sourceCompatibility = ver
|
||||||
|
targetCompatibility = ver
|
||||||
|
kotlinOptions.jvmTarget = ver
|
||||||
|
kotlinOptions.moduleName = compileTestKotlin.kotlinOptions.moduleName // must be the same module name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
compileModuleInfoX.apply {
|
||||||
|
// we need all the compiled classes before compiling module-info.java
|
||||||
|
dependsOn(compileMainJava)
|
||||||
|
if (hasKotlin) {
|
||||||
|
dependsOn(compileMainKotlin)
|
||||||
|
}
|
||||||
|
|
||||||
|
val proj = this@JavaXConfiguration.project
|
||||||
|
|
||||||
|
val allSource = proj.files(
|
||||||
|
main.allSource.srcDirs,
|
||||||
|
mainX.allSource.srcDirs
|
||||||
|
)
|
||||||
|
|
||||||
|
val allCompiled = if (hasKotlin) {
|
||||||
|
proj.files(
|
||||||
|
compileMainJava.destinationDir,
|
||||||
|
compileMainKotlin.destinationDir
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
proj.files(
|
||||||
|
compileMainJava.destinationDir
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
source = allSource.asFileTree // the files live in this location
|
||||||
|
include("**/module-info.java")
|
||||||
|
|
||||||
|
|
||||||
|
sourceCompatibility = ver
|
||||||
|
targetCompatibility = ver
|
||||||
|
|
||||||
|
inputs.property("moduleName", moduleName)
|
||||||
|
|
||||||
|
destinationDir = compileMainXJava.destinationDir
|
||||||
|
classpath = this@JavaXConfiguration.project.files() // this resets the classpath. we use the module-path instead!
|
||||||
|
|
||||||
|
|
||||||
|
// modules require this!
|
||||||
|
doFirst {
|
||||||
|
// the SOURCE of the module-info.java file. It uses **EVERYTHING**
|
||||||
|
options.sourcepath = allSource
|
||||||
|
options.compilerArgs.addAll(listOf(
|
||||||
|
"-implicit:none",
|
||||||
|
"-Xpkginfo:always", // compile the package-info.java files as well (normally it does not)
|
||||||
|
"--module-path", main.compileClasspath.asPath,
|
||||||
|
"--patch-module", "$moduleName=" + allCompiled.asPath // add our existing, compiled classes so module-info can find them
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
doLast {
|
||||||
|
val intellijClasses = File("${this@JavaXConfiguration.project.buildDir}/classes-intellij")
|
||||||
|
if (intellijClasses.exists()) {
|
||||||
|
// copy everything to intellij also. FORTUNATELY, we know it's only going to be the `module-info` and `package-info` classes!
|
||||||
|
val moduleInfo = destinationDir.walkTopDown().filter { it.name == "module-info.class" }.toList()
|
||||||
|
val packageInfo = destinationDir.walkTopDown().filter { it.name == "package-info.class" }.toList()
|
||||||
|
|
||||||
|
val name = when {
|
||||||
|
moduleInfo.isNotEmpty() && packageInfo.isNotEmpty() -> "module-info and package-info"
|
||||||
|
moduleInfo.isNotEmpty() && packageInfo.isEmpty() -> "module-info"
|
||||||
|
else -> "package-info"
|
||||||
|
}
|
||||||
|
|
||||||
|
println("\tCopying $name files into the intellij classes location...")
|
||||||
|
|
||||||
|
moduleInfo.forEach {
|
||||||
|
val newLocation = File(intellijClasses, it.relativeTo(destinationDir).path)
|
||||||
|
it.copyTo(newLocation, overwrite = true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
project.tasks.named("jar", Jar::class.java).get().apply {
|
||||||
|
dependsOn(compileModuleInfoX)
|
||||||
|
|
||||||
|
// NOTE: This syntax screws up, and the entire contents of the jar are in the wrong place...
|
||||||
|
// from(mainX.output.classesDirs) {
|
||||||
|
// exclude("META-INF")
|
||||||
|
// into("META-INF/versions/$ver")
|
||||||
|
// }
|
||||||
|
from(mainX.output.classesDirs)
|
||||||
|
|
||||||
|
|
||||||
|
val sourcePaths = mainX.output.classesDirs.map {it.absolutePath}.toSet()
|
||||||
|
// println("SOURCE PATHS+ $sourcePaths")
|
||||||
|
|
||||||
|
doFirst {
|
||||||
|
// this is how to correctly RE-MAP the location of files in jar
|
||||||
|
eachFile { details ->
|
||||||
|
val absolutePath = details.file.absolutePath
|
||||||
|
val length = details.path.length + 1
|
||||||
|
|
||||||
|
val sourceDir = absolutePath.substring(0, absolutePath.length - length)
|
||||||
|
if (sourcePaths.contains(sourceDir)) {
|
||||||
|
// println("Moving: " + absolutePath)
|
||||||
|
// println(" : " + details.path)
|
||||||
|
details.path = "META-INF/versions/${ver}/${details.path}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// this is required for making the java 9+ multi-release version possible
|
||||||
|
manifest.attributes["Multi-Release"] = "true"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
29
src/dorkbox/gradle/jpms/SourceSetContainer2.kt
Normal file
29
src/dorkbox/gradle/jpms/SourceSetContainer2.kt
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2021 dorkbox, llc
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package dorkbox.gradle.jpms
|
||||||
|
|
||||||
|
import org.gradle.api.tasks.SourceSet
|
||||||
|
|
||||||
|
class SourceSetContainer2(private val javaX: JavaXConfiguration) {
|
||||||
|
fun main(block: SourceSet.() -> Unit) {
|
||||||
|
block(javaX.mainX)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test(block: SourceSet.() -> Unit) {
|
||||||
|
block(javaX.testX)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user