Configuration with name 'testRuntimeClasspath' not found - gradle

I am designing a plugin to return all the dependencies of the project
I tried to get dependencies from project.getConfigurations() but it is always returning the error "Configuration with name 'testRuntimeClasspath' not found". Is there any way we can apply the plugin at the Execution Phase of the build.
public void apply(Project project) {
project.getConfigurations()
.getByName("testRuntimeClasspath")
.getAllDependencies();
}

The existing configurations in a Gradle build depend on the plugin(s) applied and any configuration created by the build author.
So your plugin should either support well known plugins and derive configurations name from them or have a way for the users of your plugin to register which configurations are to be queried that way or a combination of both.
Not sure what your plugin's goal is, but y9ou should be mindful when listing dependencies as it will force resolution of configurations that may otherwise not need to be resolved.

Related

How to manually add dependencies to Gradle's MavenPom/MavenPublication?

I am working on a plugin. This plugin gets attached to a project that does not apply the java plugin nor the java-library plugin but which should functionally "look" like a Java project[1]. Which means that it should publish a POM including dependencies. The exact dependencies are known and have been collected in a Configuration.
However, I cannot figure out how to manually attach dependencies to the MavenPublication such that they make it into the published pom (aside from directly editing the pom xml).
MavenPublication shadowMavenPublication = publishingExtension.getPublications().create( "mavenShadowArtifacts", MavenPublication.class );
// `shadowPublishArtifact` is a class defined in the plugin
shadowMavenPublication.artifact(
shadowPublishArtifact.getFile(),
(mavenArtifact) -> {
mavenArtifact.setClassifier( shadowPublishArtifact.getClassifier() );
mavenArtifact.setExtension( shadowPublishArtifact.getExtension() );
}
);
So at this point I have the MavenPublication and added my custom artifact to it. Internally this MavenPublication contains a number of "dependencies" as instances of MavenDependency. E.g. DefaultMavenPublication#runtimeDependencies, DefaultMavenPublication#apiDependencies, ... But those are things defined on internal-only contracts.
Using just public APIs, how can I add dependencies to get added to the pom?
P.S. As a bonus, answer the question on the Gradle forums and get points there too! :D
P.S.S. These dependencies come from another project (hibernate-core) in a multi-project build. The user has configured those dependencies themselves. I just "consume" those dependencies with a series of "dependency substitutions". That "source project" defines some exclusions to its dependencies. How can I access those exclusions do be able to transfer them to the dependencies I am creating for this copy project (hibernate-core-jakarta)?
Thanks!
[1] Its a long back-story, but the gist is that this plugin integrates the JakartaTransformer. The project is completely generated using the transformer. The tasks added by those 2 plugins cause problems.
MavenPublication class has pom property - You need to construct (or provide in Your plugin some API for that purpose) pom with all necessary dependencies. It will be published alongside with artifact.
As far as I know, dependencies are attached to the POM by evaluating the configurations of a software component: MavenPublication.from(SoftwareComponent) (source: DefaultMavenPublication).
The idea would be to provide a customized software component. This is only possible through a custom plugin, according to Creating and publishing custom components.

Is it possible to set a dependencySet entry's classifier using Spring's Gradle dependency management plugin

I have a project that uses the Spring Dependency Management Plugin in a multi-project Gradle build to specify consistent dependency versions for the projects.
Per the documentation, when multiple dependencies share the same group & version, a dependency set should be used:
When you want to provide dependency management for multiple modules with the same group and version you should use a dependency set. Using a dependency set removes the need to specify the same group and version multiple times, as shown in the following example:
dependencyManagement {
dependencies {
dependencySet(group:'org.slf4j', version: '1.7.7') {
entry 'slf4j-api'
entry 'slf4j-simple'
}
}
}
The project uses two dependencies that share a group and version, but one of the items also specifies a classifier:
dependencies {
annotationProcessor 'com.querydsl:querydsl-apt:4.2.2:general'
implementation 'com.querydsl:querydsl-mongodb:4.2.2'
}
If there's a way to use a dependencySet in this case, I haven't found it in the documentation or an online search:
dependencyManagement {
dependencies {
dependencySet(group:'com.querydsl', version: '4.2.2') {
entry 'querydsl-apt' // Can I specify that this uses the "general" classifier?
entry 'querydsl-mongodb'
}
}
}
So in short, is there a way to use a dependencySet when one of the dependencies requires a classifier, and what is the syntax for doing so?
Issue #67 for the Dependency Management Plugin requests this feature. The issue was closed by the maintainers with a status of "declined" by the plugin maintainers:
It's impossible to implement this while classifiers remain a second class citizen in Gradle. I don't expect that will change any time soon (things haven't improved in Gradle 3.0) so, with some regret, I'm going to close this.
Follow-up conversation in that issue suggest that the underlying Gradle issue is still not resolved in Gradle 6.
This means that not only can classifiers not be specified using dependencySet, they cannot be specified using dependency entries within the dependencyManagement section either:
dependencyManagement {
dependencies {
dependency 'com.querydsl:querydsl-apt:4.2.2:general' // INVALID
dependency 'com.querydsl:querydsl-mongodb:4.2.2'
}
}
What's worse, there is no warning or failure emitted, so the fact that it's not using the specified version with a classifier is not made clear to the user.
So to answer the question, the usage of classifiers in the dependencyManagement plugin is not supported since Gradle does not provide an API for the plugin to access the classifier. Therefore, dependency versions with classifiers cannot be specified in the dependencyManagement section either directly using dependency or as a group using dependencySet.

Collect Gradle project's dependency constraints

I am looking for a way to collect all the dependency constraints (enforced with a regular platform and/or enforcedPlatform and/or "manually") for a given project from a custom Gradle plugin.
In Maven world, you can resolve an "artifact descriptor" that will give access to the effective list of all the managed dependencies enforced on the artifact. I couldn't find so far how this kind of info could be collected in Gradle.
Any advice? Thanks!
based on the clarification of the question - below can be a start (requires more work - for some reason my local shows configuration as default - not the compile/runtime)
allprojects {
afterEvaluate {
configurations.findAll {it.canBeResolved==true}.each { println it + "\n" ; it.allDependencies.each { println it } }
}
}
The question (appears to me) is sharing the test code across modules in a multi-module project
Short answer - No - there is direct test dependency share across modules.
To share test code between modules internally via build settings
Official gradle route https://docs.gradle.org/current/userguide/java_testing.html#sec:java_test_fixtures
Simple hack
testImplementation files(project(':core-module').sourceSets.test.output.classesDirs)
add the above line either individually where you need or in root with subprojects() with appropriate condition
*there are other possible routes as well *
ex: via configuration child.testImplementation extends parent.testImplementation (or runtime)

Gradle - Adding new configuration to classpath throws error

I have created a custom Gradle plugin which creates a new configuration for some dependencies that I want to treat separately. Since these used to be in the compile configuration I have added the new configuration to the classpath (from the Java plugin) like so:
project.sourceSets.all { sourceSet ->
sourceSet.compileClasspath += myConfiguration
}
My configuration extends the compile configuration. My reasoning for this was that if there were any other 3rd party plugins that did "something" to the compile configuration then it would also affect my new configuration, since it is also an instance of compile.
It seems that later on another plugin, the Spring PropDeps Plugin, also modifies the classpath and the build fails with:
Failed to apply plugin [class 'org.springframework.build.gradle.propdep.PropDepsPlugin']
Cannot change dependencies of configuration ':my-project:compile' after it has been resolved.
Looking at the source code for that plugin they are doing the same steps that I am in my custom plugin to create a configuration, namely create the configuration and add it to the classpath as soon as the plugin is applied, see here.
It would seem crazy if only one plugin could add a new configuration to the classpath. What am I doing wrong here?
Note that my custom plugin is applied in the allprojects block whereas the Spring plugin is applied in the subprojects block - not sure if this matters.
Hmmm ... as I was writing the question something struck me about both extending the compile configuration and adding to the compile classpath. This seemed like I was adding a circular dependency. Low and behold, when I did not extend the configuration the build worked!

Gradle - specifying configuration based dependency

While reading this gradle document, I came across this wordings saying that dependencies for each configuration. Here what does this configuration meant to be. Because I usually used to specify the dependencies in such a vague way like
dependencies {
compile 'org.springframework:spring-core:4.0.5.RELEASE',
'org.hibernate:hibernate-core:3.6.7.Final'
}
Is there any other possible way to specify the dependencies(based on configuration)?. I am little curious to know about that.
If yes, what is advantage of specifying dependencies like that. Can someone able to throw some light here?
Also how the below command will be useful?
gradle -q dependencies api:dependencies webapp:dependencies
In Gradle dependencies are grouped into configurations. Configurations have a name, a number of other properties, and they can extend each other. Many Gradle plugins add pre-defined configurations to your project.
These are the configurations added by Java plugin. As you can see, compile is a configuration, it is extended by many other configurations. You can create your own configuration:
configurations {
myConfig {
description = 'my config'
transitive = true
extendsFrom compile
}
}
Also how the below command will be useful?
This command prints the dependencies of main project and api and webapp subprojects.

Resources