mirror of
https://github.com/apache/lucene.git
synced 2025-02-11 04:25:40 +00:00
* Try to fix the gradle compilation in idea * Try to detect sync and build phases within intellij and act accordingly to support both modes of compilation (gradle and intellij).
562 lines
23 KiB
Groovy
562 lines
23 KiB
Groovy
/*
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
* contributor license agreements. See the NOTICE file distributed with
|
|
* this work for additional information regarding copyright ownership.
|
|
* The ASF licenses this file to You 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.
|
|
*/
|
|
|
|
|
|
import java.nio.charset.StandardCharsets
|
|
import java.nio.file.Files
|
|
import java.nio.file.Path
|
|
|
|
// Configure miscellaneous aspects required for supporting the java module system layer.
|
|
|
|
// Debugging utilities.
|
|
apply from: buildscript.sourceFile.toPath().resolveSibling("modules-debugging.gradle")
|
|
|
|
allprojects {
|
|
plugins.withType(JavaPlugin) {
|
|
// We won't be using gradle's built-in automatic module finder.
|
|
java {
|
|
modularity.inferModulePath.set(false)
|
|
}
|
|
|
|
//
|
|
// Configure modular extensions for each source set.
|
|
//
|
|
project.sourceSets.all { SourceSet sourceSet ->
|
|
// Create and register a source set extension for manipulating classpath/ module-path
|
|
ModularPathsExtension modularPaths = new ModularPathsExtension(project, sourceSet)
|
|
sourceSet.extensions.add("modularPaths", modularPaths)
|
|
|
|
// LUCENE-10344: We have to provide a special-case extension for ECJ because it does not
|
|
// support all of the module-specific javac options.
|
|
ModularPathsExtension modularPathsForEcj = modularPaths
|
|
if (sourceSet.name == SourceSet.TEST_SOURCE_SET_NAME && project.path in [
|
|
":lucene:spatial-extras",
|
|
":lucene:spatial3d",
|
|
]) {
|
|
modularPathsForEcj = modularPaths.cloneWithMode(ModularPathsExtension.Mode.CLASSPATH_ONLY)
|
|
}
|
|
sourceSet.extensions.add("modularPathsForEcj", modularPathsForEcj)
|
|
|
|
// TODO: the tests of these projects currently don't compile or work in
|
|
// module-path mode. Make the modular paths extension use class path only.
|
|
if (sourceSet.name == SourceSet.TEST_SOURCE_SET_NAME && project.path in [
|
|
// Circular dependency between artifacts or source set outputs,
|
|
// causing package split issues at runtime.
|
|
":lucene:core",
|
|
":lucene:codecs",
|
|
":lucene:test-framework",
|
|
]) {
|
|
modularPaths.mode = ModularPathsExtension.Mode.CLASSPATH_ONLY
|
|
}
|
|
|
|
// Configure the JavaCompile task associated with this source set.
|
|
tasks.named(sourceSet.getCompileJavaTaskName()).configure({ JavaCompile task ->
|
|
task.dependsOn modularPaths.compileModulePathConfiguration
|
|
|
|
// LUCENE-10327: don't allow gradle to emit an empty sourcepath as it would break
|
|
// compilation of modules.
|
|
task.options.setSourcepath(sourceSet.java.sourceDirectories)
|
|
|
|
// Add modular dependencies and their transitive dependencies to module path.
|
|
task.options.compilerArgumentProviders.add(modularPaths.compilationArguments)
|
|
|
|
// LUCENE-10304: if we modify the classpath here, IntelliJ no longer sees the dependencies as compile-time
|
|
// dependencies, don't know why.
|
|
if (!rootProject.ext.isIdeaSync) {
|
|
task.classpath = modularPaths.compilationClasspath
|
|
}
|
|
|
|
doFirst {
|
|
modularPaths.logCompilationPaths(logger)
|
|
}
|
|
})
|
|
|
|
// For source sets that contain a module descriptor, configure a jar task that combines
|
|
// classes and resources into a single module.
|
|
if (sourceSet.name != SourceSet.MAIN_SOURCE_SET_NAME) {
|
|
tasks.maybeCreate(sourceSet.getJarTaskName(), org.gradle.jvm.tasks.Jar).configure({
|
|
archiveClassifier = sourceSet.name
|
|
from(sourceSet.output)
|
|
})
|
|
}
|
|
}
|
|
|
|
// Connect modular configurations between their "test" and "main" source sets, this reflects
|
|
// the conventions set by the Java plugin.
|
|
project.configurations {
|
|
moduleTestApi.extendsFrom moduleApi
|
|
moduleTestImplementation.extendsFrom moduleImplementation
|
|
moduleTestRuntimeOnly.extendsFrom moduleRuntimeOnly
|
|
moduleTestCompileOnly.extendsFrom moduleCompileOnly
|
|
}
|
|
|
|
// Gradle's java plugin sets the compile and runtime classpath to be a combination
|
|
// of configuration dependencies and source set's outputs. For source sets with modules,
|
|
// this leads to split class and resource folders.
|
|
//
|
|
// We tweak the default source set path configurations here by assembling jar task outputs
|
|
// of the respective source set, instead of their source set output folders. We also attach
|
|
// the main source set's jar to the modular test implementation configuration.
|
|
SourceSet mainSourceSet = project.sourceSets.getByName(SourceSet.MAIN_SOURCE_SET_NAME)
|
|
boolean mainIsModular = mainSourceSet.modularPaths.hasModuleDescriptor()
|
|
boolean mainIsEmpty = mainSourceSet.allJava.isEmpty()
|
|
SourceSet testSourceSet = project.sourceSets.getByName(SourceSet.TEST_SOURCE_SET_NAME)
|
|
boolean testIsModular = testSourceSet.modularPaths.hasModuleDescriptor()
|
|
|
|
// LUCENE-10304: if we modify the classpath here, IntelliJ no longer sees the dependencies as compile-time
|
|
// dependencies, don't know why.
|
|
if (!rootProject.ext.isIdeaSync) {
|
|
def jarTask = project.tasks.getByName(mainSourceSet.getJarTaskName())
|
|
def testJarTask = project.tasks.getByName(testSourceSet.getJarTaskName())
|
|
|
|
// Consider various combinations of module/classpath configuration between the main and test source set.
|
|
if (testIsModular) {
|
|
if (mainIsModular || mainIsEmpty) {
|
|
// If the main source set is empty, skip the jar task.
|
|
def jarTaskOutputs = mainIsEmpty ? [] : jarTask.outputs
|
|
|
|
// Fully modular tests - must have no split packages, proper access, etc.
|
|
// Work around the split classes/resources problem by adjusting classpaths to
|
|
// rely on JARs rather than source set output folders.
|
|
testSourceSet.compileClasspath = project.objects.fileCollection().from(
|
|
jarTaskOutputs,
|
|
project.configurations.getByName(testSourceSet.getCompileClasspathConfigurationName()),
|
|
)
|
|
testSourceSet.runtimeClasspath = project.objects.fileCollection().from(
|
|
jarTaskOutputs,
|
|
testJarTask.outputs,
|
|
project.configurations.getByName(testSourceSet.getRuntimeClasspathConfigurationName()),
|
|
)
|
|
|
|
project.dependencies {
|
|
moduleTestImplementation files(jarTaskOutputs)
|
|
moduleTestRuntimeOnly files(testJarTask.outputs)
|
|
}
|
|
} else {
|
|
// This combination simply does not make any sense (in my opinion).
|
|
throw GradleException("Test source set is modular and main source set is class-based, this makes no sense: " + project.path)
|
|
}
|
|
} else {
|
|
if (mainIsModular) {
|
|
// This combination is a potential candidate for patching the main sourceset's module with test classes. I could
|
|
// not resolve all the difficulties that arise when you try to do it though:
|
|
// - either a separate module descriptor is needed that opens test packages, adds dependencies via requires clauses
|
|
// or a series of jvm arguments (--add-reads, --add-opens, etc.) has to be generated and maintained. This is
|
|
// very low-level (ECJ doesn't support a full set of these instructions, for example).
|
|
//
|
|
// Fall back to classpath mode.
|
|
} else {
|
|
// This is the 'plain old classpath' mode: neither the main source set nor the test set are modular.
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Configures a Test task associated with the provided source set to use module paths.
|
|
//
|
|
// There is no explicit connection between source sets and test tasks so there is no way (?)
|
|
// to do this automatically, convention-style.
|
|
//
|
|
// This closure can be used to configure a different task, with a different source set, should we
|
|
// have the need for it.
|
|
Closure<Void> configureTestTaskForSourceSet = { Test task, SourceSet sourceSet ->
|
|
task.configure {
|
|
def forkProperties = file("${task.temporaryDir}/jvm-forking.properties")
|
|
|
|
ModularPathsExtension modularPaths = sourceSet.modularPaths
|
|
|
|
dependsOn modularPaths
|
|
|
|
// Add modular dependencies and their transitive dependencies to module path.
|
|
jvmArgumentProviders.add(modularPaths.runtimeArguments)
|
|
|
|
// Modify the default classpath.
|
|
classpath = modularPaths.runtimeClasspath
|
|
|
|
doFirst {
|
|
modularPaths.logRuntimePaths(logger)
|
|
}
|
|
|
|
// Pass all the required properties for tests which fork the JVM. We don't use
|
|
// regular system properties here because this could affect task up-to-date checks.
|
|
jvmArgumentProviders.add(new CommandLineArgumentProvider() {
|
|
@Override
|
|
Iterable<String> asArguments() {
|
|
return ["-Dtests.jvmForkArgsFile=" + forkProperties.absolutePath]
|
|
}
|
|
})
|
|
doFirst {
|
|
List<String> args = new ArrayList<>(modularPaths.runtimeArguments.asArguments().collect())
|
|
def cp = modularPaths.runtimeClasspath.asPath
|
|
if (!cp.isBlank()) {
|
|
args.addAll(["-cp", cp])
|
|
}
|
|
|
|
// Sanity check.
|
|
args.forEach(s -> {
|
|
if (s.contains("\n")) {
|
|
throw new RuntimeException("LF in forked jvm property?: " + s)
|
|
}
|
|
})
|
|
|
|
Files.createDirectories(forkProperties.toPath().getParent())
|
|
Files.writeString(forkProperties.toPath(), String.join("\n", args), StandardCharsets.UTF_8)
|
|
}
|
|
}
|
|
}
|
|
|
|
// Configure (tasks.test, sourceSets.test)
|
|
tasks.matching { it.name ==~ /test(_[0-9]+)?/ }.all { Test task ->
|
|
configureTestTaskForSourceSet(task, task.project.sourceSets.test)
|
|
}
|
|
|
|
// Configure module versions.
|
|
tasks.withType(JavaCompile).configureEach { task ->
|
|
// TODO: LUCENE-10267: workaround for gradle bug. Remove when the corresponding issue is fixed.
|
|
task.options.compilerArgumentProviders.add((CommandLineArgumentProvider) { ->
|
|
if (task.getClasspath().isEmpty()) {
|
|
return ["--module-version", project.version.toString()]
|
|
} else {
|
|
return []
|
|
}
|
|
})
|
|
|
|
task.options.javaModuleVersion.set(provider {
|
|
return project.version.toString()
|
|
})
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// For a source set, create explicit configurations for declaring modular dependencies.
|
|
//
|
|
// These "modular" configurations correspond 1:1 to Gradle's conventions but have a 'module' prefix
|
|
// and a capitalized remaining part of the conventional name. For example, an 'api' configuration in
|
|
// the main source set would have a corresponding 'moduleApi' configuration for declaring modular
|
|
// dependencies.
|
|
//
|
|
// Gradle's java plugin "convention" configurations extend from their modular counterparts
|
|
// so all dependencies end up on classpath by default for backward compatibility with other
|
|
// tasks and gradle infrastructure.
|
|
//
|
|
// At the same time, we also know which dependencies (and their transitive graph of dependencies!)
|
|
// should be placed on module-path only.
|
|
//
|
|
// Note that an explicit configuration of modular dependencies also opens up the possibility of automatically
|
|
// validating whether the dependency configuration for a gradle project is consistent with the information in
|
|
// the module-info descriptor because there is a (nearly?) direct correspondence between the two:
|
|
//
|
|
// moduleApi - 'requires transitive'
|
|
// moduleImplementation - 'requires'
|
|
// moduleCompileOnly - 'requires static'
|
|
//
|
|
class ModularPathsExtension implements Cloneable, Iterable<Object> {
|
|
/**
|
|
* Determines how paths are split between module path and classpath.
|
|
*/
|
|
enum Mode {
|
|
/**
|
|
* Dependencies and source set outputs are placed on classpath, even if declared on modular
|
|
* configurations. This would be the 'default' backward-compatible mode.
|
|
*/
|
|
CLASSPATH_ONLY,
|
|
|
|
/**
|
|
* Dependencies from modular configurations are placed on module path. Source set outputs
|
|
* are placed on classpath.
|
|
*/
|
|
DEPENDENCIES_ON_MODULE_PATH
|
|
}
|
|
|
|
Project project
|
|
SourceSet sourceSet
|
|
Configuration compileModulePathConfiguration
|
|
Configuration runtimeModulePathConfiguration
|
|
Configuration modulePatchOnlyConfiguration
|
|
|
|
// The mode of splitting paths for this source set.
|
|
Mode mode = Mode.DEPENDENCIES_ON_MODULE_PATH
|
|
|
|
// More verbose debugging for paths.
|
|
private boolean debugPaths
|
|
|
|
/**
|
|
* A list of module name - path provider entries that will be converted
|
|
* into {@code --patch-module} options.
|
|
*/
|
|
private List<Map.Entry<String, Provider<Path>>> modulePatches = new ArrayList<>()
|
|
|
|
ModularPathsExtension(Project project, SourceSet sourceSet) {
|
|
this.project = project
|
|
this.sourceSet = sourceSet
|
|
|
|
debugPaths = Boolean.parseBoolean(project.propertyOrDefault('build.debug.paths', 'false'))
|
|
|
|
ConfigurationContainer configurations = project.configurations
|
|
|
|
// Create modular configurations for gradle's java plugin convention configurations.
|
|
Configuration moduleApi = createModuleConfigurationForConvention(sourceSet.apiConfigurationName)
|
|
Configuration moduleImplementation = createModuleConfigurationForConvention(sourceSet.implementationConfigurationName)
|
|
Configuration moduleRuntimeOnly = createModuleConfigurationForConvention(sourceSet.runtimeOnlyConfigurationName)
|
|
Configuration moduleCompileOnly = createModuleConfigurationForConvention(sourceSet.compileOnlyConfigurationName)
|
|
|
|
|
|
// Apply hierarchy relationships to modular configurations.
|
|
moduleImplementation.extendsFrom(moduleApi)
|
|
|
|
// Patched modules have to end up in the implementation configuration for IDEs, which
|
|
// otherwise get terribly confused.
|
|
Configuration modulePatchOnly = createModuleConfigurationForConvention(
|
|
SourceSet.isMain(sourceSet) ? "patchOnly" : sourceSet.name + "PatchOnly")
|
|
modulePatchOnly.canBeResolved(true)
|
|
moduleImplementation.extendsFrom(modulePatchOnly)
|
|
this.modulePatchOnlyConfiguration = modulePatchOnly
|
|
|
|
// This part of convention configurations seems like a very esoteric use case, leave out for now.
|
|
// sourceSet.compileOnlyApiConfigurationName
|
|
|
|
// We have to ensure configurations are using assembled resources and classes (jar variant) as a single
|
|
// module can't be expanded into multiple folders.
|
|
Closure<Void> ensureJarVariant = { Configuration c ->
|
|
c.attributes.attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, project.objects.named(LibraryElements, LibraryElements.JAR))
|
|
}
|
|
|
|
// Set up compilation module path configuration combining corresponding convention configurations.
|
|
Closure<Configuration> createResolvableModuleConfiguration = { String configurationName ->
|
|
Configuration conventionConfiguration = configurations.maybeCreate(configurationName)
|
|
Configuration moduleConfiguration = configurations.maybeCreate(moduleConfigurationNameFor(conventionConfiguration.name))
|
|
moduleConfiguration.canBeConsumed(false)
|
|
moduleConfiguration.canBeResolved(true)
|
|
ensureJarVariant(moduleConfiguration)
|
|
|
|
project.logger.info("Created resolvable module configuration for '${conventionConfiguration.name}': ${moduleConfiguration.name}")
|
|
return moduleConfiguration
|
|
}
|
|
|
|
ensureJarVariant(configurations.maybeCreate(sourceSet.compileClasspathConfigurationName))
|
|
ensureJarVariant(configurations.maybeCreate(sourceSet.runtimeClasspathConfigurationName))
|
|
|
|
this.compileModulePathConfiguration = createResolvableModuleConfiguration(sourceSet.compileClasspathConfigurationName)
|
|
compileModulePathConfiguration.extendsFrom(moduleCompileOnly, moduleImplementation)
|
|
|
|
this.runtimeModulePathConfiguration = createResolvableModuleConfiguration(sourceSet.runtimeClasspathConfigurationName)
|
|
runtimeModulePathConfiguration.extendsFrom(moduleRuntimeOnly, moduleImplementation)
|
|
}
|
|
|
|
/**
|
|
* Adds {@code --patch-module} option for the provided module name and the provider of a
|
|
* folder or JAR file.
|
|
*
|
|
* @param moduleName
|
|
* @param pathProvider
|
|
*/
|
|
void patchModule(String moduleName, Provider<Path> pathProvider) {
|
|
modulePatches.add(Map.entry(moduleName, pathProvider));
|
|
}
|
|
|
|
private FileCollection getCompilationModulePath() {
|
|
if (mode == Mode.CLASSPATH_ONLY) {
|
|
return project.files()
|
|
}
|
|
return compileModulePathConfiguration - modulePatchOnlyConfiguration
|
|
}
|
|
|
|
private FileCollection getRuntimeModulePath() {
|
|
if (mode == Mode.CLASSPATH_ONLY) {
|
|
if (hasModuleDescriptor()) {
|
|
// The source set is itself a module.
|
|
throw new GradleException("Source set contains a module but classpath-only" +
|
|
" dependencies requested: ${project.path}, source set '${sourceSet.name}'")
|
|
}
|
|
|
|
return project.files()
|
|
}
|
|
|
|
return runtimeModulePathConfiguration - modulePatchOnlyConfiguration
|
|
}
|
|
|
|
FileCollection getCompilationClasspath() {
|
|
if (mode == Mode.CLASSPATH_ONLY) {
|
|
return sourceSet.compileClasspath
|
|
}
|
|
|
|
// Modify the default classpath by removing anything already placed on module path.
|
|
// Use a lazy provider to delay computation.
|
|
project.files({ ->
|
|
return sourceSet.compileClasspath - compileModulePathConfiguration - modulePatchOnlyConfiguration
|
|
})
|
|
}
|
|
|
|
CommandLineArgumentProvider getCompilationArguments() {
|
|
return new CommandLineArgumentProvider() {
|
|
@Override
|
|
Iterable<String> asArguments() {
|
|
FileCollection modulePath = ModularPathsExtension.this.compilationModulePath
|
|
|
|
if (modulePath.isEmpty()) {
|
|
return []
|
|
}
|
|
|
|
ArrayList<String> extraArgs = []
|
|
extraArgs += ["--module-path", modulePath.join(File.pathSeparator)]
|
|
|
|
if (!hasModuleDescriptor()) {
|
|
// We're compiling what appears to be a non-module source set so we'll
|
|
// bring everything on module path in the resolution graph,
|
|
// otherwise modular dependencies wouldn't be part of the resolved module graph and this
|
|
// would result in class-not-found compilation problems.
|
|
extraArgs += ["--add-modules", "ALL-MODULE-PATH"]
|
|
}
|
|
|
|
// Add module-patching.
|
|
extraArgs += getPatchModuleArguments(modulePatches)
|
|
|
|
return extraArgs
|
|
}
|
|
}
|
|
}
|
|
|
|
FileCollection getRuntimeClasspath() {
|
|
if (mode == Mode.CLASSPATH_ONLY) {
|
|
return sourceSet.runtimeClasspath
|
|
}
|
|
|
|
// Modify the default classpath by removing anything already placed on module path.
|
|
// Use a lazy provider to delay computation.
|
|
project.files({ ->
|
|
return sourceSet.runtimeClasspath - runtimeModulePath - modulePatchOnlyConfiguration
|
|
})
|
|
}
|
|
|
|
CommandLineArgumentProvider getRuntimeArguments() {
|
|
return new CommandLineArgumentProvider() {
|
|
@Override
|
|
Iterable<String> asArguments() {
|
|
FileCollection modulePath = ModularPathsExtension.this.runtimeModulePath
|
|
|
|
if (modulePath.isEmpty()) {
|
|
return []
|
|
}
|
|
|
|
def extraArgs = []
|
|
|
|
// Add source set outputs to module path.
|
|
extraArgs += ["--module-path", modulePath.files.join(File.pathSeparator)]
|
|
|
|
// Ideally, we should only add the sourceset's module here, everything else would be resolved via the
|
|
// module descriptor. But this would require parsing the module descriptor and may cause JVM version conflicts
|
|
// so keeping it simple.
|
|
extraArgs += ["--add-modules", "ALL-MODULE-PATH"]
|
|
|
|
// Add module-patching.
|
|
extraArgs += getPatchModuleArguments(modulePatches)
|
|
|
|
return extraArgs
|
|
}
|
|
}
|
|
}
|
|
|
|
boolean hasModuleDescriptor() {
|
|
return sourceSet.allJava.srcDirs.stream()
|
|
.map(dir -> new File(dir, "module-info.java"))
|
|
.anyMatch(file -> file.exists())
|
|
}
|
|
|
|
private List<String> getPatchModuleArguments(List<Map.Entry<String, Provider<Path>>> patches) {
|
|
def args = []
|
|
patches.each {
|
|
args.add("--patch-module");
|
|
args.add(it.key + "=" + it.value.get())
|
|
}
|
|
return args
|
|
}
|
|
|
|
private static String toList(FileCollection files) {
|
|
return files.isEmpty() ? " [empty]" : ("\n " + files.sort().join("\n "))
|
|
}
|
|
|
|
private static String toList(List<Map.Entry<String, Provider<Path>>> patches) {
|
|
return patches.isEmpty() ? " [empty]" : ("\n " + patches.collect {"${it.key}=${it.value.get()}"}.join("\n "))
|
|
}
|
|
|
|
public void logCompilationPaths(Logger logger) {
|
|
def value = "Modular extension, compilation paths, source set=${sourceSet.name}${hasModuleDescriptor() ? " (module)" : ""}, mode=${mode}:\n" +
|
|
" Module path:${toList(compilationModulePath)}\n" +
|
|
" Class path: ${toList(compilationClasspath)}\n" +
|
|
" Patches: ${toList(modulePatches)}"
|
|
|
|
if (debugPaths) {
|
|
logger.lifecycle(value)
|
|
} else {
|
|
logger.info(value)
|
|
}
|
|
}
|
|
|
|
public void logRuntimePaths(Logger logger) {
|
|
def value = "Modular extension, runtime paths, source set=${sourceSet.name}${hasModuleDescriptor() ? " (module)" : ""}, mode=${mode}:\n" +
|
|
" Module path:${toList(runtimeModulePath)}\n" +
|
|
" Class path: ${toList(runtimeClasspath)}\n" +
|
|
" Patches : ${toList(modulePatches)}"
|
|
|
|
if (debugPaths) {
|
|
logger.lifecycle(value)
|
|
} else {
|
|
logger.info(value)
|
|
}
|
|
}
|
|
|
|
public ModularPathsExtension clone() {
|
|
return (ModularPathsExtension) super.clone()
|
|
}
|
|
|
|
ModularPathsExtension cloneWithMode(Mode newMode) {
|
|
def cloned = this.clone()
|
|
cloned.mode = newMode
|
|
return cloned
|
|
}
|
|
|
|
// Map convention configuration names to "modular" corresponding configurations.
|
|
static String moduleConfigurationNameFor(String configurationName) {
|
|
return "module" + configurationName.capitalize().replace("Classpath", "Path")
|
|
}
|
|
|
|
// Create module configuration for the corresponding convention configuration.
|
|
private Configuration createModuleConfigurationForConvention(String configurationName) {
|
|
ConfigurationContainer configurations = project.configurations
|
|
Configuration conventionConfiguration = configurations.maybeCreate(configurationName)
|
|
Configuration moduleConfiguration = configurations.maybeCreate(moduleConfigurationNameFor(configurationName))
|
|
moduleConfiguration.canBeConsumed(false)
|
|
moduleConfiguration.canBeResolved(false)
|
|
conventionConfiguration.extendsFrom(moduleConfiguration)
|
|
|
|
project.logger.info("Created module configuration for '${conventionConfiguration.name}': ${moduleConfiguration.name}")
|
|
return moduleConfiguration
|
|
}
|
|
|
|
/**
|
|
* Provide internal dependencies for tasks willing to depend on this modular paths object.
|
|
*/
|
|
@Override
|
|
Iterator<Object> iterator() {
|
|
return [
|
|
compileModulePathConfiguration,
|
|
runtimeModulePathConfiguration
|
|
].iterator()
|
|
}
|
|
} |