improved aggregated javadoc generation

This commit is contained in:
Steve Ebersole 2021-09-27 07:09:29 -05:00
parent e422d913db
commit 7bc1d55cdd
9 changed files with 248 additions and 202 deletions

View File

@ -32,8 +32,6 @@ plugins {
id 'idea'
id 'org.jetbrains.gradle.plugin.idea-ext' version '1.0'
id 'eclipse'
id 'biz.aQute.bnd' version '5.1.1' apply false
}
allprojects {

View File

@ -11,27 +11,6 @@ plugins {
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
def projectsToIncludeInAggregatedJavadoc = [
':hibernate-core',
':hibernate-testing',
':hibernate-envers',
':hibernate-agroal',
':hibernate-c3p0',
':hibernate-graalvm',
':hibernate-hikaricp',
// ':hibernate-jcache',
':hibernate-micrometer',
':hibernate-proxool',
':hibernate-spatial',
':hibernate-vibur',
':hibernate-gradle-plugin',
':hibernate-enhance-maven-plugin',
':hibernate-jpamodelgen',
]
projectsToIncludeInAggregatedJavadoc.each {projectPath ->
evaluationDependsOn projectPath
}
apply from: rootProject.file( 'gradle/java-module.gradle' )
apply plugin: 'org.hibernate.matrix-test'
@ -89,82 +68,6 @@ task buildDocsForPublishing {
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// aggregated JavaDoc
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
final File javadocDir = mkdir( new File( (File) project.buildDir, 'javadocs' ) );
/**
* Builds the JavaDocs aggregated (unified) across all the sub-projects
*/
task aggregateJavadocs(type: Javadoc) {
description = 'Builds an aggregated JavaDoc across all ORM sub-projects'
final int currentYear = new GregorianCalendar().get( Calendar.YEAR )
// exclude any generated sources and internal packages
exclude( '**/generated-src/**' )
exclude( '**/internal/**' )
// apply standard config
maxMemory = '512m'
destinationDir = javadocDir
configure( options ) {
overview = 'src/main/javadoc/overview.html'
windowTitle = 'Hibernate JavaDocs'
docTitle = "Hibernate JavaDoc ($project.version)"
bottom = "Copyright &copy; 2001-$currentYear <a href=\"https://redhat.com\">Red Hat, Inc.</a> All Rights Reserved."
use = true
options.encoding = 'UTF-8'
links = [
'https://docs.oracle.com/javase/8/docs/api/',
'https://docs.jboss.org/hibernate/beanvalidation/spec/2.0/api/',
'https://docs.jboss.org/cdi/api/2.0/',
'https://javaee.github.io/javaee-spec/javadocs/'
]
if ( gradle.ext.javaVersions.main.compiler.asInt() >= 11 ) {
//The need to set `--source 1.8` applies to all JVMs after 11, and also to 11
// but after excluding the first two builds; see also specific comments on
// https://bugs.openjdk.java.net/browse/JDK-8212233?focusedCommentId=14245762
// For now, let's be compatible with JDK 11.0.3+. We can improve on it if people
// complain they cannot build with JDK 11.0.0, 11.0.1 and 11.0.2.
logger.lifecycle "Forcing Javadoc in Java 8 compatible mode"
options.source = gradle.ext.baselineJavaVersion
}
options.addStringOption( 'Xdoclint:none', '-quiet' )
if ( gradle.ext.javaToolchainEnabled ) {
options.setJFlags( getProperty( 'toolchain.javadoc.jvmargs' ).toString().
split( ' ' ).toList().findAll( { !it.isEmpty() } ) )
}
}
if ( gradle.ext.javaToolchainEnabled ) {
// Display version of Java tools
doFirst {
logger.lifecycle "Aggregating javadoc with '${javadocTool.get().metadata.installationPath}'"
}
}
// process each project, building up:
// 1) appropriate sources
// 2) classpath
projectsToIncludeInAggregatedJavadoc.each {projectPath ->
def includeProject = parent.project(projectPath)
// we only care about the main SourceSet...
source includeProject.sourceSets.main.java
classpath += ( includeProject.sourceSets.main.output + includeProject.sourceSets.main.compileClasspath )
}
}
asciidoctorj {
attributes icons: 'font',
experimental: true,
@ -178,8 +81,10 @@ asciidoctorj {
// Topical Guides ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
task renderTopicalGuides(type: AsciidoctorTask, group: 'Documentation') {
task renderTopicalGuides(type: AsciidoctorTask, group: 'Documentation') {task->
description = 'Renders the Topical Guides in HTML format using Asciidoctor.'
tasks.buildDocs.dependsOn task
tasks.buildDocsForPublishing.dependsOn task
sourceDir = file( 'src/main/asciidoc/topical' )
outputDir = new File("$buildDir/asciidoc/topical/html_single")
@ -194,8 +99,10 @@ task renderTopicalGuides(type: AsciidoctorTask, group: 'Documentation') {
// Getting Started Guides (quick starts) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
task renderGettingStartedGuides(type: AsciidoctorTask, group: 'Documentation') {
task renderGettingStartedGuides(type: AsciidoctorTask, group: 'Documentation') {task->
description = 'Renders the Getting Started Guides (quick starts) in HTML format using Asciidoctor.'
tasks.buildDocs.dependsOn task
tasks.buildDocsForPublishing.dependsOn task
sourceDir = file( 'src/main/asciidoc/quickstart/guides' )
sources {
@ -205,7 +112,7 @@ task renderGettingStartedGuides(type: AsciidoctorTask, group: 'Documentation') {
}
task buildTutorialZip(type: Zip) {
task buildTutorialZip(type: Zip) {task->
from 'src/main/asciidoc/quickstart/tutorials'
destinationDirectory = tasks.renderGettingStartedGuides.outputDir
archiveBaseName = 'hibernate-tutorials.zip'
@ -215,14 +122,16 @@ task buildTutorialZip(type: Zip) {
junit: project.junitVersion,
h2: project.h2Version
)
tasks.renderGettingStartedGuides.dependsOn task
}
renderGettingStartedGuides.dependsOn buildTutorialZip
// User Guide ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
task renderUserGuide(type: AsciidoctorTask, group: 'Documentation') {
task renderUserGuide(type: AsciidoctorTask, group: 'Documentation') {task->
description = 'Renders the User Guides in HTML format using Asciidoctor.'
tasks.buildDocs.dependsOn task
tasks.buildDocsForPublishing.dependsOn task
sourceDir = file( 'src/main/asciidoc/userguide' )
sources {
@ -253,8 +162,10 @@ task renderUserGuide(type: AsciidoctorTask, group: 'Documentation') {
// Integration Guide ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
task renderIntegrationGuide(type: AsciidoctorTask, group: 'Documentation') {
task renderIntegrationGuide(type: AsciidoctorTask, group: 'Documentation') {task->
description = 'Renders the User Guides in HTML format using Asciidoctor.'
tasks.buildDocs.dependsOn task
tasks.buildDocsForPublishing.dependsOn task
sourceDir = file( 'src/main/asciidoc/integrationguide' )
sources {
@ -303,13 +214,11 @@ sourceSets.test.resources {
// grouping tasks
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
buildDocs.dependsOn aggregateJavadocs
buildDocs.dependsOn renderTopicalGuides
buildDocs.dependsOn renderGettingStartedGuides
buildDocs.dependsOn renderUserGuide
buildDocs.dependsOn renderIntegrationGuide
buildDocsForPublishing.dependsOn aggregateJavadocs
buildDocsForPublishing.dependsOn renderTopicalGuides
buildDocsForPublishing.dependsOn renderGettingStartedGuides
buildDocsForPublishing.dependsOn renderUserGuide

View File

@ -26,7 +26,6 @@ apply from: rootProject.file( 'gradle/databases.gradle' )
apply plugin: 'java-library'
apply plugin: 'org.hibernate.orm.database-service'
apply plugin: 'biz.aQute.bnd.builder'
apply plugin: 'checkstyle'
apply plugin: 'build-dashboard'

View File

@ -10,6 +10,20 @@ apply plugin : 'java'
apply from: rootProject.file( 'gradle/base-information.gradle' )
configurations {
javadocSources {
canBeConsumed = true
canBeResolved = false
description = 'Configuration for accessing the sources that should be included in the javadoc for the project'
}
}
artifacts {
sourceSets.main.allJava.srcDirs.each { srcDir ->
javadocSources srcDir
}
}
javadoc {
exclude( "**/internal/*" )
exclude( "**/generated-src/**" )
@ -77,4 +91,4 @@ task javadocJar(type: Jar) {
)
}
archiveClassifier.set( 'javadoc' )
}
}

View File

@ -89,6 +89,7 @@ ext {
jboss_tx_spi_jakarta: "org.jboss:jboss-transaction-spi-jakarta:7.6.1.Final",
jakarta_validator: "org.hibernate.validator:hibernate-validator:${hibernateValidatorJakartaVersion}",
jakarta_el: 'org.glassfish:jakarta.el:4.0.1',
jakarta_inject: 'jakarta.inject:jakarta.inject-api:2.0.0',
// javax
jpa: "javax.persistence:javax.persistence-api:${project.jpaVersion}",

View File

@ -21,23 +21,24 @@ configurations {
tests {
description = 'Configuration for the produced test jar'
}
implementation {
extendsFrom antlr
}
}
dependencies {
api libraries.jakarta_jpa
api libraries.jakarta_jta
api libraries.jakarta_activation
api libraries.jakarta_jaxb_api
api libraries.jakarta_jaxb_runtime
api libraries.jandex
api libraries.classmate
api libraries.commons_annotations
implementation libraries.byteBuddy
implementation libraries.activation
implementation libraries.jaxb_runtime
implementation libraries.antlr
implementation libraries.jakarta_activation
implementation libraries.jakarta_jaxb_api
implementation libraries.jakarta_jaxb_runtime
implementation libraries.jakarta_inject
compileOnly libraries.jakarta_jacc
compileOnly libraries.jakarta_validation
@ -56,21 +57,14 @@ dependencies {
// for test runtime
transitive = true
}
testImplementation libraries.jakarta_cdi
testImplementation libraries.mockito
testImplementation libraries.mockito_inline
testImplementation libraries.jodaTime
testImplementation libraries.assertj
testImplementation libraries.jakarta_cdi
// testImplementation libraries.jboss_ejb_spec_jar
// testImplementation libraries.jboss_annotation_spec_jar
// testRuntimeOnly "org.jboss.spec.javax.ejb:jboss-ejb-api_3.2_spec:1.0.0.Final"
testRuntimeOnly libraries.jakarta_el
// testRuntimeOnly 'jaxen:jaxen:1.1'
testRuntimeOnly libraries.byteBuddy
testRuntimeOnly libraries.jakarta_weld
// testRuntimeOnly libraries.atomikos
// testRuntimeOnly libraries.atomikos_jta
testRuntimeOnly libraries.wildfly_transaction_client
testAnnotationProcessor project( ':hibernate-jpamodelgen' )
@ -85,53 +79,7 @@ dependencies {
jar {
manifest {
attributes(
'Main-Class': 'org.hibernate.Version',
// // BND Plugin instructions (for OSGi):
// 'Import-Package': [
// 'javax.security.auth;resolution:=optional',
// // Make javax.security.jacc optional and do not reference a version range (because that's what we used to do)
// 'javax.security.jacc;resolution:=optional;version=!',
// // Make javax.validation optional and do not reference a version range (because that's what we used to do)
// 'javax.validation;resolution:=optional;version=!',
// 'javax.validation.constraints;resolution:=optional;version=!',
// 'javax.validation.groups;resolution:=optional;version=!',
// 'javax.validation.metadata;resolution:=optional;version=!',
// // Make javax.enterprise optional and do not reference a version range (because that's what we used to do)
// '!javax.enterprise*',
// 'javax.enterprise.context.spi;resolution:=optional;version=!',
// 'javax.enterprise.inject.spi;resolution:=optional;version=!',
// // For JPA, we don't want to target the automatically generated range, but a specific version
// "javax.persistence;version=\"${project.jpaVersion.osgiName}\"",
// // optionals
// 'jakarta.persistence.spi;resolution:=optional',
// 'javax.management;resolution:=optional',
// 'javax.naming.event;resolution:=optional',
// 'javax.naming.spi;resolution:=optional',
// 'org.apache.tools.ant;resolution:=optional',
// 'org.apache.tools.ant.taskdefs;resolution:=optional',
// 'org.apache.tools.ant.types;resolution:=optional',
// 'javax.inject;resolution:=optional',
// 'net.bytebuddy.*;resolution:=optional',
// 'org.objectweb.jonas_tm;resolution:=optional',
// 'com.ibm.websphere.jtaextensions;resolution:=optional',
// // We must specify the version explicitly to allow Karaf
// // to use an older version of JAXB (the only one we can use in Karaf)
// "javax.xml.bind.*;version=\"${project.jaxbApiVersionOsgiRange}\"",
// // Temporarily support JTA 1.1 -- Karaf and other frameworks still
// // use it. Without this, the plugin generates [1.2,2).
// 'javax.transaction;version="[1.1,2)"',
// // Also import every package referenced in the code
// '*'
// ].join( ',' ),
'-exportcontents': [
// Legacy resource packages containing XSDs that were traditionally not exported
"!org.hibernate.xsd.cfg",
"!org.hibernate.xsd.mapping",
// TODO: Uncomment once EntityManagerFactoryBuilderImpl no longer uses ClassLoaderServiceImpl.
//'org.hibernate.boot.registry.classloading.internal',
"*;version=${project.version}"
].join( ',' ),
'Main-Class': 'org.hibernate.Version'
)
}
}

View File

@ -1,4 +1,5 @@
import java.nio.charset.StandardCharsets
import java.util.function.Function
import groovy.json.JsonSlurper
@ -9,20 +10,18 @@ import groovy.json.JsonSlurper
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
apply from: rootProject.file( 'gradle/base-information.gradle' )
apply from: rootProject.file( 'gradle/libraries.gradle' )
apply plugin: 'idea'
apply plugin: 'distribution'
//apply plugin: 'java-library-distribution'
idea.module {
}
//def documentationDir = project.layout.buildDirectory.dir('documentation')
configurations {
core
// testing
testing
envers
spatial
@ -36,21 +35,218 @@ configurations {
jcache
jpamodelgen
javadocClasspath {
description = 'Class files for the javadoc to be built'
resolutionStrategy.capabilitiesResolution.withCapability('org.junit.jupiter:junit-jupiter-params:5.7.1') { details ->
details.select( details.candidates.first() ).because( 'first' )
}
extendsFrom core
extendsFrom testing
extendsFrom envers
extendsFrom spatial
extendsFrom agroal
extendsFrom c3p0
extendsFrom hikaricp
extendsFrom proxool
extendsFrom vibur
extendsFrom jcache
extendsFrom jpamodelgen
}
javadocSources {
description = 'Source files to be built by the javadoc tool'
}
}
dependencies {
attributesSchema { schema ->
schema.attribute(Bundling.BUNDLING_ATTRIBUTE) { matchStrategy ->
final def nameComparator = Comparator.comparing(
new Function<Bundling,String>() {
@Override
String apply(Bundling o) {
return o.name
}
}
)
matchStrategy.ordered(new Comparator<Bundling>() {
@Override
int compare(Bundling o1, Bundling o2) {
if ( Objects.equals( o1, o2 ) ) {
return 0;
}
if ( o1 == null ) {
return 1;
}
if ( o2 == null ) {
return -1;
}
if ( o1.name == Bundling.EMBEDDED ) {
return -1;
}
if ( o2.name == Bundling.EMBEDDED ) {
return 1;
}
return nameComparator.compare(o1,o2)
}
} )
}
}
core project( ':hibernate-core' )
// testing project( ':hibernate-testing' )
javadocSources project( path: ':hibernate-core', configuration: 'javadocSources' )
testing project( ':hibernate-testing' )
javadocSources project( path: ':hibernate-testing', configuration: 'javadocSources' )
envers project( ':hibernate-envers' )
javadocSources project( path: ':hibernate-envers', configuration: 'javadocSources' )
spatial project( ':hibernate-spatial' )
javadocSources project( path: ':hibernate-spatial', configuration: 'javadocSources' )
agroal project( ':hibernate-agroal' )
javadocSources project( path: ':hibernate-agroal', configuration: 'javadocSources' )
c3p0 project( ':hibernate-c3p0' )
javadocSources project( path: ':hibernate-c3p0', configuration: 'javadocSources' )
hikaricp project( ':hibernate-hikaricp' )
javadocSources project( path: ':hibernate-hikaricp', configuration: 'javadocSources' )
proxool project( ':hibernate-proxool' )
javadocSources project( path: ':hibernate-proxool', configuration: 'javadocSources' )
vibur project( ':hibernate-vibur' )
javadocSources project( path: ':hibernate-vibur', configuration: 'javadocSources' )
// jcache project( ':hibernate-jcache' )
// javadocSources project( path: ':hibernate-jcache', configuration: 'javadocSources' )
jpamodelgen project( ':hibernate-jpamodelgen' )
javadocSources project( path: ':hibernate-jpamodelgen', configuration: 'javadocSources' )
javadocClasspath libraries.logging_annotations
javadocClasspath libraries.jakarta_validation
javadocClasspath libraries.jakarta_cdi
javadocClasspath libraries.jakarta_jacc
javadocClasspath libraries.ant
javadocClasspath gradleApi()
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// aggregated JavaDoc
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
final File javadocDir = mkdir( new File( (File) project.buildDir, 'documentation/javadocs' ) );
/**
* Builds the JavaDocs aggregated (unified) across all the sub-projects
*/
task aggregateJavadocs(type: Javadoc) {
description = 'Builds an aggregated JavaDoc across all ORM sub-projects'
final int currentYear = new GregorianCalendar().get( Calendar.YEAR )
source configurations.javadocSources
classpath += configurations.javadocClasspath
// exclude any generated sources and internal packages
exclude '**/generated-src/**'
exclude '**/internal/**'
include '**/*.java'
// apply standard config
maxMemory = '512m'
destinationDir = javadocDir
configure( options ) {
overview = 'src/release/javadoc/overview.html'
windowTitle = 'Hibernate JavaDocs'
docTitle = "Hibernate JavaDoc ($project.version)"
bottom = "Copyright &copy; 2001-$currentYear <a href=\"https://redhat.com\">Red Hat, Inc.</a> All Rights Reserved."
use = true
options.encoding = 'UTF-8'
links = [
'https://docs.oracle.com/javase/8/docs/api/',
'https://docs.jboss.org/hibernate/beanvalidation/spec/2.0/api/',
'https://docs.jboss.org/cdi/api/2.0/',
'https://javaee.github.io/javaee-spec/javadocs/'
]
if ( gradle.ext.javaVersions.main.compiler.asInt() >= 11 ) {
//The need to set `--source 1.8` applies to all JVMs after 11, and also to 11
// but after excluding the first two builds; see also specific comments on
// https://bugs.openjdk.java.net/browse/JDK-8212233?focusedCommentId=14245762
// For now, let's be compatible with JDK 11.0.3+. We can improve on it if people
// complain they cannot build with JDK 11.0.0, 11.0.1 and 11.0.2.
logger.lifecycle "Forcing Javadoc in Java 8 compatible mode"
options.source = gradle.ext.baselineJavaVersion
}
options.addStringOption( 'Xdoclint:none', '-quiet' )
if ( gradle.ext.javaToolchainEnabled ) {
options.setJFlags( getProperty( 'toolchain.javadoc.jvmargs' ).toString().
split( ' ' ).toList().findAll( { !it.isEmpty() } ) )
}
}
if ( gradle.ext.javaToolchainEnabled ) {
// Display version of Java tools
doFirst {
logger.lifecycle "Aggregating javadoc with '${javadocTool.get().metadata.installationPath}'"
}
}
}
task stageIntegrationGuide(type: Copy) {
group 'Release'
dependsOn ':documentation:buildDocsForPublishing'
from "${project( ':documentation' ).buildDir}/asciidoc/integrationguide"
into "${buildDir}/documentation/integrationguide"
}
task stageQuickstart(type: Copy) {
group 'Release'
dependsOn ':documentation:buildDocsForPublishing'
from "${project( ':documentation' ).buildDir}/asciidoc/quickstart"
into "${buildDir}/documentation/quickstart"
}
task stageTopicalGuide(type: Copy) {
group 'Release'
dependsOn ':documentation:buildDocsForPublishing'
from "${project( ':documentation' ).buildDir}/asciidoc/topical"
into "${buildDir}/documentation/topical"
}
task stageUserGuide(type: Copy) {
group 'Release'
dependsOn ':documentation:buildDocsForPublishing'
from "${project( ':documentation' ).buildDir}/asciidoc/userguide"
into "${buildDir}/documentation/userguide"
}
/**
@ -58,35 +254,16 @@ dependencies {
*
* Depends on building the docs
*/
task assembleDocumentation(type: Copy) {
task assembleDocumentation {
group 'Release'
description 'Assembles all documentation into the {buildDir}/documentation directory'
dependsOn ':documentation:buildDocsForPublishing'
// copy documentation outputs into target/documentation.
// * this is used in building the dist bundles
// * it is also used as a base to build a staged directory for documentation upload
// Integrations Guide
from "${rootProject.project( 'documentation' ).buildDir}/asciidoc/integrationguide"
into "${buildDir}/documentation/integrationguide"
// Getting-started Guide
from "${rootProject.project( 'documentation' ).buildDir}/asciidoc/quickstart"
into "${buildDir}/documentation/quickstart"
// Topical Guide
from "${rootProject.project( 'documentation' ).buildDir}/asciidoc/topical"
into "${buildDir}/documentation/topical"
// User Guide
from "${rootProject.project( 'documentation' ).buildDir}/asciidoc/userguide"
into "${buildDir}/documentation/userguide"
// Aggregated JavaDoc
from "${rootProject.project( 'documentation' ).buildDir}/javadocs"
into "${buildDir}/documentation/javadocs"
dependsOn tasks.aggregateJavadocs
dependsOn tasks.stageIntegrationGuide
dependsOn tasks.stageTopicalGuide
dependsOn tasks.stageQuickstart
dependsOn tasks.stageUserGuide
}
//task assembleProjectTemplates(type:Copy, dependsOn: project( ":project-template" ).tasks.assembleDist) {

View File

@ -28,7 +28,7 @@ dependencies {
implementation libraries.byteBuddy
implementation gradleApi()
// for Gradle
implementation 'jakarta.inject:jakarta.inject-api:2.0.0'
implementation libraries.jakarta_inject
implementation localGroovy()
}