I like to setup a usual multi project build with gradle. The project structure looks like the following:
root/
build.gradle
settings.gradle
share/
build.gradle
domain/
build.gradle
web/
build.gradle
As you might guess, domain depends on share and web depends on share and domain.
There are two ways to descripe this dependenies:
specify the dependencies for all sub projects in root/build.gradle
specify the dependencies per sub project in root/{sub_project}/build.gradle
I prefer the second option because a project should know its dependencies. Is there anything wrong about this approach? I ask because the most examples found in the internet and in the gradle documentation uses approach 1.
Both are correct approaches, the project we're building using gradle uses the second approach, keeps the knowledge of the domain localized and easy to change.
Related
What is the key difference between includeBuild(...) and implementation(project(...)) in the Gradle build system? I cannot really see the usecase difference after reading the documentation:
https://docs.gradle.org/current/userguide/declaring_dependencies.html#sub:project_dependencies
https://docs.gradle.org/current/userguide/composite_builds.html#separate_composite
What I am trying to do: Share same codebase for two separate projects: data classes (kotlix.serialization), external database dao, interfaces. It is not a full library but just some code snippets.
How can I connect the two projects in Intellij so that type hinting works?
Composite Build (by using includeBuild) is a way to create a dependency between autonomous Gradle Projects.
Project import, is a way to create a dependency between two modules within a same Gradle Project.
Composite Build is far more powerful and is also meant to be the new way of factorizing gradle configuration between multiple projects that you traditionally do with the buildSrc technique.
I found this "Structuring Large Projects" article to be easier to read than the "Composite Builds" doc.
An excellent sample project that demonstrates the power of Composite Builds can be found in Gradle sample_structuring_software_projects.
Project dependency case
The tree would look like this:
settings.gradle.kts
module1/build.gradle.kts
module2/build.gradle.kts
And you are declaring a dependency in module1/build.gradle.kts like this:
dependencies {
implementation(project("com.domain:module2"))
}
The dependency will be resolved only if both projects are declared as sub-modules of a common root project.
It means you have a root settings.gradle.kts like this:
rootProject.name = "rootProject"
include(":module1")
include(":module2")
Composite build case
The projects do not need to have common "umbrella" root project.
Each project is a totally independent project.
One project can simply declare a dependency on the other project (without even the target project knowing about it).
Tree:
project1/build.gradle.kts
project1/settings.gradle.kts
project2/build.gradle.kts
project2/settings.gradle.kts
In project1/settings.gradle.kts:
rootProject.name = "project1"
includeBuild("../project2") //No more ':' as it is not a module
In project2/settings.gradle.kts:
rootProject.name = "project2"
In project1/build.gradle.kts like this:
dependencies {
implementation("com.domain:project2")
}
I have the same problem. Reading on the first link, the next para says:
Local forks of module dependencies
A module dependency can be substituted by a dependency to a local fork
of the sources of that module, if the module itself is built with
Gradle. This can be done by utilising composite builds. This allows
you, for example, to fix an issue in a library you use in an
application by using, and building, a locally patched version instead
of the published binary version. The details of this are described in
the section on composite builds.
So, it should be implementation project according to me.
P.S. The code completion is working on one of my sub project but not on the other. I am still trying to figure that out
java-project1
--- build.gradle
java-project2
--- build.gradle
We've 2 different web projects and both use gradle to build artifacts. There's a lot of code that is repeated between these the build.gradle files. Is there a way to achieve this by abstracting out the common code in groovy files and "importing" them in actual projects' build.gradle?
We tried putting the common code under src/main/groovy... but that too will be repeated across these two projects.
We are thinking about creating a 3rd project now where all these common groovy scripts will live and both project1 and project2 can declare a dependency on that project.
Any pointers?
Thank you!
The third project should be a custom Gradle plugin. More info here: https://docs.gradle.org/current/userguide/custom_plugins.html
You can use gradle init to quickly bootstrap the Gradle plugin project: https://docs.gradle.org/current/userguide/build_init_plugin.html
Once you have extracted the common Gradle/build logic, tested, simply publish the plugin to either an internal/private repository or a public one such as Artifactory.
Then simply apply the newly created Gradle plugin to both projects.
Suppose I have a gradle project named Xenon, and several modules there like Xenon-Task, Xenon-API, something like that.
Which style should be preferred. One means only one global project level gradle file VS every single module has their own gradle file respectively, project level only has module info, but no details which works inside module.
The answer is: it depends. There is no "preferred" style, you're the one who choose.
General advice is to put all common logic in the higher level build files, in allprojects / subprojects blocks. Good candidates are repositories as they are the same for all the submodules or publishing configs.
However, there are plugins, like The Application Plugin that will have different configs in different modules (main classes). A set of particular submodule's dependencies will be different for each submodule as well. So put that in module's build.gradle.
In Maven one can use the base pom file concept(https://www.atlassian.com/blog/archives/maven_in_our_development_proce_3) - the file everyone would then reuse
Is it a similar concept in Gradle? We use Gradle to build Java projects
You should take a look at this answer
Basically, the parent project can hold the role of "parent POM" and thanks to Gradle's allprojects, subprojects and extra properties mechanisms, you can reproduce Maven's main behavior. Also you can split your configuration in several .gradle files and include them with apply from. Finally, regular and custom plugins can be defined in the parent project, for target or all sub-projects.
So we have a huge multi-project codebase with structure like below:
C:\Eclipse\Workspace->
AR
DC
CI
..
..
Each project has a build.gradle file which has 80% of the code same with only dependencies section changing for all the projects.
What I want to achieve:
I want to create a parent project named "BuildAllProjects" which would be the ONLY project having build.gradle, settings.gradle and gradle.properties and propose to have a properties file for mentioning the dependencies of each project, something like:
AR=j2ee,commons-lang,FW,DA,Common
DC=commons-codec,FW,DA,Common,spring-core
and then use the gradle expand[] properties to dynamically fill the dependencies for the project which I am building, so for instance, if I am building AR, I may want to run:
gradle -PAR build
which will read dependencies for "AR" from the properties and expand in the form :
dependencies {
compile name 'j2ee'
compile name 'commons-lang'
}
Do you guys think this is possible or is this the WORST way of achieving it? I am new to GRADLE overall and information provided above is based on knowledge that I have acquired in a weeks time. Please provide your suggestions to implement this at the BEST of gradle.
Thanks,
Yogendra
Layering a properties file based build language on top of Gradle's build language doesn't strike me as desirable. Instead, I recommend to focus on writing clean and DRY Gradle build scripts. You can learn more about Gradle's powerful abstraction capabilities (configuration injection, script plugins, buildSrc, custom plugins and extensions, etc.) in the Gradle User Guide.
In a typical multi-project build, subproject build scripts mostly contain dependency declarations, whereas most other configuration happens in the root build script and/or script plugins.