Sharing code between build.gradle from different projects - gradle

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.

Related

Gradle includeBuild vs implementation project

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

How to implement a Maven base pom file concept using 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.

Parent pom usage in build.gradle

I have a need to convert the maven project to gradle project. All is going fine, but there is one problem that I faced, in the current project we are using dependency management throw parent pom of maven and in gradle as long as I researched there is no possibility to do so. I was thinking to convert somehow parent pom to maven bom and use in build.gradle because I know that gradle can use maven boms.
Do anyone have better ideas how to accoplish that ?
Or may be someone also had this kind of problem, can suggest best ways to do it ?
Regards
You could use my gradle-maven-transform plugin to transform your pom.xmls into gradle scripts.
You can use the DependencyAggregator to find versions which are common across all projects and generate a root build.gradle containing the common versions.
Each project script can then reference a version variable from the root project instead of hard coding
You might choose to use nebula dependency recomnender plugin to manage common versions. The maven-transform plugin can generate scripts to support this style of declaration too
Whilst you are evaluating the gradle build you "apply" the generated gradle scripts in your gradle build. During this time both maven and gradle builds will work in parallel. Once your happy with the gradle build you copy paste the generated scripts into your build.gradle files and ditch maven for ever! Yay!

Gradle - Single build.gradle with dynamic dependencies

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.

Gradle: Who should declare multiproject dependencies: root or subproject

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.

Resources