gradle combining multiple build script dependecies - gradle

gradle multiple build script dependencies
We am in the process from transacting my our build scripts from ant to gradle. The ant build is configured the old way without using ivy and getting the dependencies from a lib folder.
We have a number of custom ant tasks packaged in jar. To run the tasks in that jar we also need some other third parties dependencies from the same lib folder.
Being a complex build we cannot afford to move everything in one go and would rather move one bit at a time as we find some time to do it.
I was able to run those custom ant tasks from the gradle build but I am having problems accessing classes from or tasks jars in my gradle build scripts.
In the build script section we have a class path entry needed for artifactory plugin and I tried to add some more class path entries to make our local libs available.
buildscript {
….
dependencies {
// This dependency below is needed by artifactory plugin which we download
classpath "org.jfrog.buildinfo:build-info-extractor-gradle:3.0.1"
}
….
}
I tried lots of combinations but I could not get it to work. What we want is to be able to do something like below:
buildscript {
…
dependencies {
classpath {
["org.jfrog.buildinfo:build-info-extractor-gradle:3.0.1",
fileset(dir: "${antBuildDir}/customTasks", includes: 'myTasks.jar'),
fileset(dir: "${antBuildDir}/lib", includes: '*.jar')]
}
}
…
}
Any idea about how can I address this or any other suggestions if you think I am on the wrong path.
Thank you in advance.
Julian

Related

Gradle: Depend on artifacts from ant legacy build

I am wondering how to declare a dependency on artifact produced by a legacy Ant build.
I have a Gradle build that consists of 2 modules: 'legacy' and 'backend'.
The 'legacy' module is quite old, requires an Ant to generate a 'legacy/dist' directory. I cannot convert this build to Gradle, unfortunately. This build takes a lot of time. For convenience, the Ant build is wrapped as a Gradle build.
The 'backend' module uses the 'war' plugin. It needs to package 'legacy/dist' directory into the war.
legacy/build.grade:
ant.importBuild 'build.xml'
current backend/build.grade:
plugins {
id 'war'
}
dependecies {
?
}
war {
dependsOn ':legacy:dist'
from('../legacy/dist')
}
This solution works, but has several drawbacks. To force Gradle to build 'legacy' before 'backend', I stated that the :backend:war task depends on the :legacy:dist task (not recommended). Every time I build backend, Gradle cannot know if legacy was build and calls :legacy:dist task, triggering unnecessarily the legacy build that takes a lot of time.
How should I declare on legacy/build.grade that it generates the dist directory and that the backend/build.grade depends on this dist directory? Without depending on tasks and without mentioning directory explicitly? I could figure out how to accomplish this from the documentation. Thanks.

What is supposed to happen to dependencies after gradle build?

I am trying out Gradle, and am wondering, what is supposed to happen to a project's dependencies after you run gradle build? For example, my sample projects don't run on the command line after they are built, because they are missing dependencies. They seem to compile fine, as gradle doesn't give me errors or warnings about finding the dependencies.
Gradle projects I've made in IntelliJ Idea have the same problem. They compile and run inside the IDE, but are missing dependencies and can't run on the command line.
So what is supposed to happen to the dependencies I declare in the build.gradle file? Shouldn't they be output somewhere together with my .class files? Otherwise, what is the point of gradle when I could manage this by editing my classpath?
Edit: Here is my build.gradle file:
apply plugin: 'java'
jar {
manifest {
attributes('Main-Class': 'Animals')
}
}
repositories {
flatDir{
dirs "D:\\libs\\gradleRepo"
}
}
dependencies {
compile name: "AnimalTypes-1.0-SNAPSHOT"
}
sourceSets{
main{
java {
srcDirs=['src']
}
}
}
Your Gradle build only takes care of the compile time and allows you to use the specified dependencies in your code (it adds them to the compile classpath). But it does not take care of the runtime. Once the JAR is build, you need to specify the runtime classpath and provide all required dependencies.
You may think, that this is bad or a disadvantage, but actually it is totally fine and intended, because if you build a Java library, you won't need to execute it, you just want to specify it as a dependency for another project. If you would distribute your library to a Maven repository, all dependencies from Maven repositories (module dependencies) would end up in a POM descriptor as transitive dependencies.
Now, if you want to build a runnable Java application, simply use the Gradle Application Plugin (apply plugin: 'application'), which will create a ZIP file containing the dependencies and start scripts providing your runtime classpath for execution.
Third-party plugins can also produce so-called fat JARs, which are JAR files with all dependencies included. It depends on your use case if you should use them, because often dependency management via repositories is the better way to go.

Run task before repositories are added and dependencies are resolved

I'm working on compiling python bindings using gradle.
There is a plugin by linkedin that facilitates that.
They also include a project called the pivy-importer that converts python dependencies into an ivy repository.
I've created a gradle plugin that wraps the pivy-importer so that it can run as a python task.
My repositories are declared like this:
repositories {
pyGradlePyPi()
ivy {
name 'pypi-local' //optional, but nice
url "${project.buildDir.path}/pythonIvy"
layout "pattern", {
ivy "[organisation]/[module]/[revision]/[module]-[revision].ivy"
artifact "[organisation]/[module]/[revision]/[artifact]-[revision](-[classifier]).[ext]"
m2compatible = true
}
}
}
The problem, however, is that the repositories are being loaded before the plugin executes.
The first task that the python task runs is pinRequirements so I was adding my cusom pythonImporter task before that like this:
pinRequirements.dependsOn pythonImporter
However, even when I do that, the console shows that the pythonImporter task is running before but as soon as it tries to assemble the dependencies, it can't find them even though they do exist in the file system.
If you rerun the task again, however, it passes because the first run added the repository to the file system.
TL;DR
I need a way to run a task before dependencies are looked up under using a project's configured repositories are loaded.
I moved the tasks execution to my buildSrc subproject and made the build task depend upon its execution.
This works because the buildSrc project is always evaluated before the rest of the projects so you can do "before build" logic there.

Add dynamic dependencies via command line

Is it possible to use CLI to add a jar with Gradle plugin (or task) to the build classpath without modifying build.gradle? Can the add JAR be resolved from Maven repository?
Is buildscript { dependencies { classpath }} controllable from CLI? And can I use CLI to make Gradle to resolve the JAR from Maven?
Basically I need to achieve the same situation as with Maven, which allows invoking any plugin by
mvn <plugin-group-id>:<plugin-artifact-id>:<plugin-version>:<plugin-goal>
I'm writing a pair of Maven and Gradle plugins to extract information about projects and their dependencies into JSON file, which can be later processed programatically. The idea is to be able to apply it on a large number of OSS projects and, therefore, without modifying them.
I think I get it now
myinit-script.gradle
if (hasProperty('extraDependencies')) {
def extraDeps = property('extraDependencies').split(',')
allprojects {
buildscript {
dependencies {
classpath extraDeps
}
}
}
}
command line
gradlew --init-script myinit-script.gradle -PextraDependencies=org.foo:bar:1.0,org.foo:baz:1.2 build

Gradle include jar produced by another project in war

Currently I have two projects with gradle build.gradle. The first is going to create a fat jar file, which I would like to include in a war file. I thought compiling it would be enough, but it doesn't seem to be ending up in the /lib directory of my war file. Anyone have thoughts I am quite new to gradle.
dependencies {
compile project(':JarProject')
providedCompile 'javax.servlet:javax.servlet-api:3.1.0'
providedCompile 'org.apache.tomcat:tomcat-jsp-api:7.0.55'
}
war {
archiveName 'WarProject.war'
from 'JarProject/build/libs'
webXml = file('src/web.xml')
}
Does the second project war need to be in providedRuntime? Or should I publish the jar from the other project in the local maven repo and include it that way?
The War task essentially behaves like a CopyTask with regards to stuff it packs in the war, so the documentation on working with files is useful. In essence, I think you need something like (untested):
from fileTree('JarProject/build/libs') {
into("lib")
}
That being said, using mavenLocal() and publishing there also works, but it can lead to unexpected results when the war includes some old version from local, picking up the jar explicitly from the file system like above is better.
I think the elegant solution would be to use multi project builds and project level dependencies. You would have the two builds as separate projects of the same Gradle build and add the "jar project" as a regular compile dependency.
How have you declared the dependency? I assume you have a multi-project build with subprojects A and B, both using the War plugin. I made an experiment using Gradle 2.4 and if I declare B/build.gradle like this:
apply plugin: 'war'
dependencies {
compile project(':A')
}
then B.war contains WEB-INF/lib/A.jar. If you correctly follow conventions of Gradle War plugin (place web resources in A/src/main/webapp/ and code-related resources in A/src/main/resources/), then A.jar should contain what you want.
see this

Resources