blob: 148309f02b5205bbea99ca3456b9631e12968237 [file] [log] [blame]
/*
* 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.
*/
plugins {
id 'java-library'
id 'org.apache.geode.gradle.geode-dependency-constraints'
}
compileJava.options.encoding = 'UTF-8'
dependencies {
// log4j-core has an annotation processor that is passed on the compile-classpath via geode-core and others.
// Fix Gradle warning here until we clean up our own classpath
annotationProcessor 'org.apache.logging.log4j:log4j-core:' + DependencyConstraints.get('log4j.version')
}
String javaVersion = System.properties['java.version']
def versionMajor = JavaVersion.current().majorVersion.toInteger()
if (versionMajor < 17) {
throw new GradleException("Java version 17 or later required, but was " + javaVersion)
}
// apply compiler options
gradle.taskGraph.whenReady({ graph ->
tasks.withType(JavaCompile).each { javac ->
javac.configure {
options.encoding = 'UTF-8'
options.compilerArgs.addAll([
'--add-exports=java.management/com.sun.jmx.remote.security=ALL-UNNAMED',
'--add-exports=java.base/sun.nio.ch=ALL-UNNAMED',
'--add-exports=jdk.unsupported/sun.misc=ALL-UNNAMED',
'--add-exports=jdk.unsupported/sun.reflect=ALL-UNNAMED',
'-Xlint:-removal',
'-Xlint:-deprecation'
])
}
javac.options.incremental = true
javac.options.fork = true
javac.options.forkOptions.with({
memoryMaximumSize = "768m"
})
if (project.hasProperty('compileJVM') && !compileJVM.trim().isEmpty()) {
javac.options.forkOptions.executable = compileJVM + "/bin/javac"
}
}
})
Collection<String> getConfigurationNamesFor(Project proj, String configName) {
def configList = new HashSet<String>()
def configFromName = proj.configurations.getByName(configName)
configList.addAll(configFromName.extendsFrom.collectMany {
getConfigurationNamesFor(proj, it.name).flatten().unique()
})
configList.add(configName)
return configList
}
Collection<Configuration> getConfigurationsFor(Project proj, String configName) {
def configNames = getConfigurationNamesFor(proj, configName)
return configNames.collect { proj.configurations.getByName(it) }
}
// apply default manifest
gradle.taskGraph.whenReady({ graph ->
tasks.withType(Jar).each { jar ->
def projectDependencies = []
def runtimeSet = new HashSet<String>()
def allProjectDeps = []
def runtimeConfigNameList = getConfigurationNamesFor(project, 'runtimeClasspath')
runtimeConfigNameList.each { conf ->
allProjectDeps.addAll(project.configurations.getByName(conf).getDependencies())
}
jar.doFirst {
// Iterate over runtime classpath dependencies and separate project dependencies from library
// dependencies.
allProjectDeps.each { dependency ->
if ( dependency instanceof ProjectDependency ) {
def platformAttribute = Attribute.of("org.gradle.category", org.gradle.api.attributes.Category.class)
def foundAttribute = dependency.attributes.getAttribute(platformAttribute)
if (foundAttribute == null) {
projectDependencies.add(dependency)
} else if ('platform'.equals(foundAttribute)) {
projectDependencies.add(dependency)
}
} else {
project.configurations.runtimeClasspath.files(dependency).each { depJar ->
runtimeSet.add(depJar.name)
}
}
}
// Iterate over project (parent) dependencies and remove its runtime library dependencies from
// the current project's runtime library dependencies.
// Also removes all parent project's runtime project dependencies from the current project.
// This returns a unique set of parent project and library dependencies that are not found
// within it's parent's project dependencies.
def upstreamDeps = []
projectDependencies.clone().each { ProjectDependency projectDependency ->
Project geodeProject = projectDependency.getDependencyProject()
Map depMap = new HashMap<Object,Object>()
def runtimeConfigList = getConfigurationsFor(geodeProject, 'runtimeClasspath')
runtimeConfigList.each { eachConfig ->
depMap.putAll(geodeProject.configurations.getByName(eachConfig.name).dependencies.collectEntries {eachDep ->
[eachDep.name, eachDep]
}.findAll { !(it.value?.hasProperty('optional') && it.value.optional)})
}
// NOTE: Previously this logic resolved the upstream project's runtimeClasspath via
// geodeProject.configurations.runtimeClasspath.getIncoming().getResolutionResult().
// That constitutes cross-project configuration resolution (executed while configuring
// the current project's Jar task) and triggers Gradle's deprecation warning:
// "Resolution of the configuration :otherProject:runtimeClasspath was attempted from a context different than the project context"
// To avoid that, we derive the first-level runtime dependency jar names directly from
// the dependency metadata (depMap) we already collected, without forcing resolution of
// the upstream configuration here. This yields the same set that was formerly filtered
// against the resolved components because depMap only contains declared (first-level)
// non-optional dependencies of the upstream project.
depMap.values()
.findAll { dep -> !(dep instanceof ProjectDependency) }
.each { dep ->
if (dep.hasProperty('version') && dep.version) {
upstreamDeps.add("${dep.name}-${dep.version}.jar")
} else {
// Log warning about missing version but don't add to upstreamDeps (preserves original behavior)
logger.warn("Dependency '${dep.name}' has no version information in project '${geodeProject.name}' and will be skipped from upstream exclusion")
}
}
}
// TODO: can we put our projects on the ClassPath line still?
runtimeSet.removeAll(upstreamDeps)
def upstreamClasspath = manifest.attributes.get('Class-Path')
if (upstreamClasspath) {
runtimeSet.addAll(upstreamClasspath.split(' '))
}
// runtimeSet.removeAll(upstreamDeps)
manifest {
attributes.put("Manifest-Version", "1.0")
attributes.put("Created-By", System.getProperty("user.name"))
attributes.put("Title", rootProject.name)
attributes.put("Version", archiveVersion)
attributes.put("Organization", productOrg)
attributes.put("Class-Path", runtimeSet.join(' '))
attributes.put("Dependent-Modules", projectDependencies.collect({ "${it.name}-${it.version}" }).join(' '))
attributes.put("Module-Name", project.name)
}
}
jar.metaInf {
from("$rootDir/geode-assembly/src/main/dist/LICENSE")
if (jar.source.filter({ it.name.contains('NOTICE') }).empty) {
from("$rootDir/NOTICE")
}
}
}
})
configurations {
testOutput {
extendsFrom testImplementation
description 'a dependency that exposes test artifacts'
}
}
// This ensures that javadoc and source jars also have any prefix paths stripped and will
// be created as libs/foo-sources.jar instead of libs/extensions/foo-sources.jar for example.
tasks.all { task ->
if (task instanceof Jar) {
archiveBaseName = project.name
}
}
tasks.register('jarTest', Jar) {
dependsOn testClasses
description 'Assembles a jar archive of test classes.'
from sourceSets.test.output
classifier 'test'
}
artifacts {
testOutput (jarTest)
}
javadoc {
destinationDir = file("$buildDir/javadoc")
// Disabled strict HTML checking for Java 17 compatibility
options.addStringOption('Xdoclint:none', '-quiet')
options.encoding = 'UTF-8'
exclude "**/internal/**"
classpath += configurations.compileClasspath
}