Collect build artifacts from subprojects into RPM with Gradle - gradle

I have the following project structure:
Root
+---Sub1
|
+---Sub2
Sub1 project produces JAR, Sub2 creates WAR.
Root project goal is to produce RPM that contains both the Sub1 and Sub2 output.
I'm trying to use ospackage Gradle plugin to build RPM. Here is part of root build.gradle:
ospackage {
from subprojects.collect { it.tasks.withType(Zip) } into 'lib'
}
It works but for Sub2 both JAR and WAR are created, which is undesirable.
What configuration should be applied in order to collect appropriate jars and wars into RPM?
UPDATE
I'm searching for some generic solution, i.e. iteration over subprojects is preferable to specifying behaviour for each subproject.

The solution is to add WAR plugin in Sub2 project's build.gradle:
apply plugin: 'war'
make buildRpm task dependent on all subprojects build tasks in the root build file:
buildRpm.dependsOn getTasksByName('build', true)
and finally configure ospackage plugin to collect the artifacts into the target RPM:
ospackage {
from(subprojects.collect { "${it.buildDir}/libs" }) {
into 'bin'
}
}

Related

Specifying common plugin for all the subprojects in Gradle Multi Project Build

I have an empty root project and one subproject
rootProject.name = "worder"
include("worder-core")
I want to make kotlin.jvm plugin to be common for all subprojects, build.gradle.kts(worder):
plugins {
id("org.jetbrains.kotlin.jvm") version "1.3.61" apply false
id("idea")
}
subprojects {
apply(plugin = "kotlin")
}
And then I'm trying to add dependencies to subproject, build.gradle.kts(worder-core):
dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.3")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-jdk8:1.3.3")
}
Okay, lets test it:
cd worder
gradle tasks // OK
cd worder-core
gradle tasks // FAILED -> Unresolved reference: implementation
So, why do I have worder-core project configuration failed ? IDEA doesn't complain at all.
full root build script
full subproject build sript

How to generate a war file based on two subprojects

I have a project which is splitted into two subprojects.
/project
/sub-project-a (backend with JAVA source which is compiled into JAR file)
/sub-project-b (frontend sources which are compiled with grunt via gradle call)
build.gradle
settings.gradle (contains include 'sub-project-a', 'sub-project-b')
My Question is how can I create a War file with sub-projects and external lib dependencies? The following code snipped is my current build.gradle:
apply plugin: 'war'
version '1.0.0'
repositories {
mavenCentral()
}
dependencies {
compile project(':sub-project-a')
compile project(':sub-project-b')
compile 'com.google.code.gson:gson:2.2.4'
}
task copy(type: Copy) {
from 'sub-project-a/build', 'sub-project-b/build'
into 'build'
}
build.dependsOn clean, copy
war {
archiveName 'project.war'
}
One detail is important. The java context listener (deep inside project code) work with compiled backend as jar file from WEB-INF/lib folder. This means that all class files can't be easily used from WEB-INF/classes folder.
As you can see I played with dependencies and a custom copy task. I'm not sure what is right gradle way. How should I do this?
SOLUTION
Define with war.from methode, where you get your static sources.
gradle docu
from(sourcePaths) -
Specifies source files or directories for a copy. The given paths are
evaluated as per Project.files().
My changed build.gradle
apply plugin: 'war'
version '1.0.0'
repositories {
mavenCentral()
}
dependencies {
compile 'com.google.code.gson:gson:2.2.4'
}
war {
archiveName 'project.war'
from 'sub-project-a/build/dist', 'sub-project-b/build/dist'
}
SOLUTION (for cleanly closing this question) shamefully taken from the question's originator ;-)
Define subproject dependencies with the "war.from" method, where you get your static sources.
gradle documentation excerpt: from(sourcePaths) - Specifies source files or directories
for a copy. The given paths are evaluated as per Project.files().
Ronny's changed build.gradle
apply plugin: 'war'
version '1.0.0'
repositories {
mavenCentral()
}
dependencies {
compile 'com.google.code.gson:gson:2.2.4'
}
war {
archiveName 'project.war'
from 'sub-project-a/build/dist', 'sub-project-b/build/dist'
}

Why is Gradle ignoring groupId/artifactId?

Here is my Gradle build:
apply plugin: 'groovy'
apply plugin: 'maven'
group = 'myorg'
repositories {
mavenCentral()
}
dependencies {
compile 'org.codehaus.groovy:groovy-all:2.3.3'
compile 'org.apache.httpcomponents:httpclient:4.3.5'
compile 'org.slf4j:slf4j-api:1.7.5'
testCompile 'junit:junit:4.11'
}
task sourcesJar(type: Jar, dependsOn: classes) {
classifier = 'sources'
from sourceSets.main.allSource
}
artifacts {
archives sourcesJar
}
task createPom << {
pom {
project {
groupId group
artifactId "myapp"
version version
}
}.writeTo("build/libs/pom.xml")
}
And the build invocation I am using:
gradle clean build groovydoc sourcesJar createPom -Pversion=SNAPSHOT
When I run this:
The POM file is created with groupId, artifactId and version all appearing correctly inside the XML; but
The name of the resultant JAR is whatever folder the project is rooted under. For instance, if the name of my project root is "fizz", and the buildfile above is located at fizz/build.gradle, then the build invocation above produces fizz-<version>.jar (where <version> is whatever value I specify on the command line). If I now rename the fizz/ directory to buzz/ and re-run the same build invocation, a buzz-<version>.jar will be produced.
My question: how/where (what file) do I hardcode groupId and artifactId inside so that myapp-<version>.jar gets built, regardless of the name of the project root directory?
You need a settings.gradle in the project root and inside you set the rootProject.name = 'artifactId' this will fix the name of the project.
The groupId and version can be set in the build.gradle file via the group and version properties.

How to add a war build to a distribution

We have a gradle project that does a distTar to create a tar distribution file.
Each dependency project builds good placing all the dependencies and project jar files into the distribution libs folder.
We need to add a project that builds a war file. By adding the project as a dependency it adds all the war dependencies ... we need just the war file from the project war task.
Also the war project war task is not being executed.
Instead the jar task is being executed from distTar of the distribution project.
How do we execute the project war task and add just the war file to a "gui" folder in the tar distribution?
To get the built war file into the distribution add a task which the distTar depends. Have the depends on task depend on the other project war task. Take the output files and put them in the distribution. The key is to do the into/from in a doLast so the depends on other project war completes before the into/from for the distribution.
// create a task depends on other project war
// put into the distribution gui folder the war.output.files
// the doLast gives visibility to the war.outputs.files
// after the depends on is complete
task otherProjectWar(dependsOn: ':OtherProject:war') {
doLast {
applicationDistribution.into("gui") {
from( project(':OtherProject').war.outputs.files )
}
}
}
// add depends on for distTar
distTar {
dependsOn otherProjectWar
...
}
I believe the proper approach is to include desired task outputs to the distribution. Here is sample script that adds jar built by the project to the main distribution (for war use war outputs instead of jar outputs).
apply plugin: 'java'
apply plugin: 'distribution'
distributions {
main {
contents {
from jar.outputs
}
}
}
Running the distribution task then correctly resolves dependencies for both zip and tar.
> gradlew distTar
:clean
:compileJava
:processResources NO-SOURCE
:classes
:jar
:distTar
You'll need to add a dependency to the output of the war task. By default, ProjectDependency simply adds a dependency to the default configuration of that project.
dependencies {
compile project(':myproject').war.outputs.files
}
Edit: To clarify, compile probably isn't the best configuration to add this dependency to, this is just an example. If indeed all this project is doing is aggregating dependencies into a single distribution archive then the configuration is likely irrelevant.

How to add other projects in current project in Gradle?

I have two projects ProjA and ProjB, here ProjB is depends on ProjA. So, how to include ProjA in ProjB?
And please let me know in case change in the ProjA build.gradle file?
Okay, so you have two projects, whereas ProjA depends on ProjB.
If you have already set up a gradle build for those, both of them will have a file settings.gradle, which at least defines the project name and build.gradle, where you can specify the dependencies.
Example:
settings.gradle
rootProject.name = 'ProjA'
build.gradle
group = 'mygroup'
version = '1.0'
By further adding one of Gradle's publishing plugins (see Maven publishing or Ivy publishing), you can configure a publication. A publication in turn contains artifacts, that is the files you want to upload (and usually some repositories).
Example for a minimal Maven publication:
apply plugin: 'maven-publish'
publishing {
publications {
core(MavenPublication) {
from components.java
}
}
}
The maven-publish plugin will add the task publishToMavenLocal (among others) to your project which installs the jar somewhere to ~/.gradle/caches/.
In build.gradle of ProjB you can then define a compile time dependency on ProjA like so:
dependencies {
compile(group: 'mygroup', name: 'ProjA', version: '1.0')
}
If your projects are co-located, you could have a multi build project.
Say you have a root folder with these contents:
some root directory
project-a
project-a.gradle
src
project-b
project-b.gradle
src
build.gradle
settings.gradle
settings.gradle contains:
include 'project-a', 'project-b'
project-b.gradle then depends on project A:
dependencies {
compile project(':project-a')
}
After this, project a will always compile and assemble before project-b and the jar file for project-a jar will be on the classpath when compiling project-b.

Resources