Никита Гучаков
05/17/2025, 2:33 PMVampire
05/17/2025, 9:43 PMНикита Гучаков
05/17/2025, 11:03 PMVampire
05/18/2025, 11:20 AMjava { withSourcesJar() }
, as that not only crates the task for creating the is jar, but also configures an outgoing variant for it and configures the component for publishing, so you can just depend on that variant by attributes it use an artifact view.
But exposing the GWT compiler output as outgoing variant should also be relatively simple. The hardest part usually is to come up with the best values for the attributes. The rest is just creating a consumable configuration, setting the attributes, and adding the artifact(s).
If you want to only share a subset of the sources, the effort is probably exactly the same.
This is the according docs: https://docs.gradle.org/current/userguide/how_to_share_outputs_between_projects.html#variant-aware-sharingНикита Гучаков
05/22/2025, 10:57 AMval gwtSourcesConfiguration = project.configurations.consumable(GWT_SOURCES_CONFIGURATION) {
attributes {
attribute(Category.CATEGORY_ATTRIBUTE, project.objects.named(Category.LIBRARY))
attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, project.objects.named(GWT_SOURCES_JAR))
}
}
val gwtImplementation = project.configurations.dependencyScope(GWT_IMPLEMENTATION) {
extendsFrom(gwtSourcesConfiguration.get())
}
project.configurations.dependencyScope(GWT_API) {
isTransitive = true
extendsFrom(
gwtImplementation.get()
)
}
project.configurations.resolvable(GWT_COMPILE_SOURCES_DEPENDENCIES_CONFIGURATION) {
description = "Dependencies for GWT compilation"
extendsFrom(
project.configurations[GWT_API],
project.configurations[GWT_IMPLEMENTATION],
)
attributes {
attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, project.objects.named(GWT_SOURCES_JAR))
}
}
When I'm calling resolve on GWT_COMPILE_SOURCES_DEPENDENCIES_CONFIGURATION, it doesn't provide transitive dependencies, despite projects added as api dependency
dependencies.add(GWT_IMPLEMENTATION, project(":libs:server")) //at service gradle
dependencies.add(GWT_API, project(":libs:gwtlib")) // at ":libs:server"
I am receiving libsserver but not libsgwtlib
Can anyone figure out the problem?Vampire
05/22/2025, 11:17 AMНикита Гучаков
05/22/2025, 11:23 AMthat it looks suspicious that a dependency scope configuration extends a consumable configuration,yeah, I have added this to check if that helps) I will remove that
Vampire
05/22/2025, 11:30 AMGWT_SOURCES_CONFIGURATION
would extend apiElements
, so that it inherits the dependencies, that could alternatively maybe also work as then the variant would have the dependencies you are after I think.Никита Гучаков
05/22/2025, 11:56 AMimplementation(project(":libs:server"))
gwtApi(project(":libs:server"))
The only thing - how to ensure that gwt sources jars will be only available for
GWT_COMPILE_SOURCES_DEPENDENCIES_CONFIGURATION
?Никита Гучаков
05/22/2025, 12:41 PMНикита Гучаков
05/22/2025, 12:56 PMMaybe you should instead us an artifact view with variant reselection to get the sources.
Because then the dependency tree is first resolved with the normal variants which have the dependency information,
and then with the artifact view you change for each the variant to the sources one and thus should also have the transitive sources.I dont get you. Maybe I am missing some part of documentation, I will check variants and configuration docs once again, but maybe you know better parts to get better understanding of this part of gradle?
Vampire
05/22/2025, 1:29 PMHm, maybe I can add variant to jvm api/implementation somehow?
api
and implementation
are configurations, you add variants to a project.
then I get rid from GWT_IMPLEMENTATION and GWT_API and project dependencies duplication
because for now I have something like this:You can also make GWT_IMPLEMENTATION extend implementation and GWT_API extend api, then all dependencies that are in implementation are automatically also in GWT_IMPLEMENTATION and all dependencies that are in api are automatically also in GWT_API. But that only makes sense if you want to add additional dependencies to GWT_*, otherwise it is just clutter and you can just use api and implementation directly.
I have tried apiElements, but now I receive all jars, not just that I neededHard to guess from just that sentence what you did exactly, what you expected, and what you got. Maybe you can share an MCVE to make it clearer.
The only thing - how to ensure that gwt sources jars will be only available forIf you request the attributes you want from a configuration or dependency or through an artifact view, then you only get those variants that match those attributes. Unless you add the necessary dependencies (directly or through
extendsFrom
) to the GWT_COMPILE_SOURCES_DEPENDENCIES_CONFIGURATION
on producer side, you would only get the directly declared dependencies when requesting the according attribute on the consumer side through dependency or configuration, as during dependency graph calculation you would only get those variants which do not have the necessary dependencies.
But if you as I said request on consumer side for example in the configuration, the normal attributes, you get the full dependency tree with transitive dependencies, and then through an artifact view where you request the attributes for the source jars with variant reselection, you would get from all those dependencies the source variant, including the transitive ones.Никита Гучаков
05/22/2025, 2:09 PMproject.configurations.consumable(GWT_SOURCES_CONFIGURATION) {
attributes {
attribute(Attribute.of("sourcesSubset", String::class.java), "gwt")
}
}
project.configurations.resolvable(GWT_COMPILE_SOURCES_DEPENDENCIES_CONFIGURATION) {
description = "Dependencies for GWT compilation"
attributes {
attribute(Attribute.of("sourcesSubset", String::class.java), "gwt")
}
}
I am adding artifacts like this:
project.afterEvaluate {
jar.configure {
from(gwtSources)
}
project.artifacts.add(GWT_SOURCES_CONFIGURATION, jar)
}
project declared as api and implementation now, if I got you correct that should be enough
though at leaf project I don't get any dependencies
val resolved = project.configurations[GWT_COMPILE_SOURCES_DEPENDENCIES_CONFIGURATION].resolve()
resolved.forEach { println("RESOLVED GWT_COMPILE: ${it.absolutePath}") }
Vampire
05/22/2025, 2:20 PMGWT_COMPILE_SOURCES_DEPENDENCIES_CONFIGURATION
which means it is already taken into account when building the dependency tree and so you miss the dependencies that are not declared for those variants currently.
With that setup you would request the normal attributes and then use an artifact view with variant reselection to get the source jars.Vampire
05/22/2025, 2:21 PMafterEvaluate
is practically always wrong.
The main earnings you get from it are timing problems, ordering problems, and race conditions.
Using it should be avoided at almost any cost.Thomas Broyer
05/22/2025, 2:58 PMНикита Гучаков
05/22/2025, 3:14 PMval resolved = project.configurations.getByName(GWT_COMPILE_SOURCES_DEPENDENCIES_CONFIGURATION)
.incoming
.artifactView {
withVariantReselection()
attributes {
attribute(gwtSourcesArtifactAttribute, GWT_SOURCES_ATTRIBUTE_VALUE)
}
}
.files
resolved.forEach { println("RESOLVED GWT_COMPILE: ${it.absolutePath}") }
Still get all jars, no just with declared with that attributeНикита Гучаков
05/22/2025, 3:21 PMVampire
05/22/2025, 3:38 PMStill get all jars, no just with declared with that attributeSo again, an MCVE might be helpful 🙂
Никита Гучаков
05/22/2025, 5:05 PM./gradlew checkGwtSources
checks invariants of :service configurations as I understand them and expected to pass
though it's not :( Maybe I understood you wrong somehowНикита Гучаков
05/22/2025, 5:23 PMVampire
05/22/2025, 6:28 PMgwtSources
instead of sources
, your checks start to become green.Никита Гучаков
05/22/2025, 8:23 PMНикита Гучаков
05/22/2025, 8:43 PMproject.configurations.consumable(GWT_SOURCES_CONFIGURATION) {
attributes {
attribute(DOCS_TYPE_ATTRIBUTE, project.objects.named("gwtSources"))
}
}
.artifactView {
withVariantReselection()
attributes {
attribute(DOCS_TYPE_ATTRIBUTE, project.objects.named("gwtSources"))
}
}
If I understand you correct. Still dont pass, also tried to add this attribute to consumable resolvableVampire
05/22/2025, 9:22 PMallprojects { ... }
, subprojects { ... }
, or any other form of cross-project configuration, for example for the repositories use dependencyResolutionManagement
in the settings script, for other common build logic, use convention plugins.
• Don't use apply()
but use the plugins { ... }
block to apply plugins.
• Don't use -all
distribution, except for 2 edge case using it is just a waste of time, disk space, and bandwidth for everyone and everything executing the build.
• Don't use confiugre<JavaPluginExtension> { ... }
and similar, but java { ... }
...
• Don't use project
at task execution time
• Don't call resolve
on a Configuration
manually
• ...Никита Гучаков
05/22/2025, 10:45 PMVampire
05/23/2025, 6:56 AM