Composite Builds for libraries dependencies Hello...
# community-support
a
Composite Builds for libraries dependencies Hello Gradle team. I have a question regarding composite builds. I am trying to setup a repository using different builds, where one of the build depends on the other. To keep it simple lets say I have module1 and module2. Now in module1 I build custom plugins but also java libraries, these will be published and used in other repositories, BUT in this repository I also want to test these publications in module2, hence "composite builds" seem to be a good match. In module2 I add a dependency to module1 with includeBuild, to get plugins I add it in the pluginManagement scop in the settings file, and this work well. I can import the plugins and use them in my different subprojects in module2. However, when it comes to regular libraries I have a hard time to get the imports to work, The documentation regarding this scenario is quite shallow we not many examples, could you please help me understand how this is meant to be applied? UPDATE: Ok I got something working however it is a bit cumbersome, it seems like I need to configure "substitution rules" for the libraries to be accessed. Like this:
Copy code
includeBuild("../core") {
    name = "core"
    dependencySubstitution {
        substitute(module("se.vermiculus.veriprimer:veriprimer-platform-common"))
                .using(project(":platform:common"))
        substitute(module("se.vermiculus.veriprimer:veriprimer-testing-infrastructure-test-execution"))
                .using(project(":testing:infrastructure:test-execution"))
        substitute(module("se.vermiculus.veriprimer:veriprimer-testing-utilities-request-execution"))
                .using(project(":testing:utilities:request-execution"))
    }
}
It is not possible to not have to specify each module like this? With the plugins this was not needed.
v
Simple rule is, If you need manual substitution rules, your projects are misconfigured. 🙂
Make sure their group and project names are set properly and not manipulated in the publication configuration.
And for dependencies make sure the
includeBuild
is also outside
pluginManagement { ... }
additionally.
a
Ah nice! Now when you mention it I am setting the group in my publication plugin as input for maven! That should do it!
t
artifactId should be set as the project name in the settings script group should be set on the project If you set any of them on the MavenPublication, then Gradle won't be able to match "groupId:artifactId" to the included project (and you can work around it with a manual substitution rule, but as Vampire said, this is rather a symptom that you should fix your included build configuration)
👍 1
a
When you say that artifactId is set as the project name in the settings script, what do you mean. I know that I set the project name there with
Copy code
rootProject.name = "..."
But if I have a multiproject, each subproject gets different names, and as default the name is the directory name (if I do not mistaken). So if I have two directories on different paths but with the same name they will clash. Can I not set the artifactId for a subproject in its build.gradle.kts script? @Thomas Broyer
v
You can, but it's a bad idea, as you have seen. Use the artifact ID you want as project name in the
include
call and then set the project's project directory in the next line.
a
Alright, thank you. I did as you said, and now things work as intended! Very good! To not have to write the extra line for every new include, I created a recursive function that sets the subproject name dynamically according to some pattern:
Copy code
// Add this in the bottom of your settings.file
fun renameRecursively(p: ProjectDescriptor) {
    if (p != rootProject) {
        p.name = p.path
                .removePrefix(":")
                .replace(":", "-")
    }
    // Recurse on child descriptors
    p.children.forEach { renameRecursively(it) }
}

renameRecursively(rootProject)
(Might be useful for anyone else that runs into this issue in the future)
@Vampire Another question related to composite builds. Is there some way to execute a task for all composites? For example
./gradlew build
If I execute this command in a wrapping directory "root" and the idea is to execute the build task for all composite builds within the root folder?
v
Only if you make the task in the main build depend on those tasks in the "sub"-builds
Or by listing the included builds manually on the commandline
a
Update: Using the fix above, i.e., changing the names of the sub-projects works fine but adds an interesting side-effect: When adding project-specific dependencies, the Gradle path uses the same name that we updated, so you will get quite annoying paths. For example:
Copy code
// Before
implementation(project(":platform:messagebus:common")) 

// With the name change
implementation(project(":platform:platform-messagebus:platform-messagebus-common"))
It would have been great if it was possible to distinguish between these configurations. The path remains the same but the subproject name could be changed - I realize that the data model might not allow for it but it seems like a few changes would make this more "generic". 🙂
v
If the
platform
and
platform-messagebus
are just an empty projects like I assume and you don't need them as a matter of organization, just leave them out and have
:platform-messagebus-common
. Already in the settings script of course, not only in the dependency declaration.
a
Yea, it is a matter of organization. The repository is quite large and we need different "sub-domains" otherwise it is hard to work with. I am working on an alternative approach that adds manual substitution rules based on a provided version-catalog. That should solve all my issues.
v
But you could name it
:p:m:platform-messagebus-common
if it is just for the organization 😄