Gradle multi-project configuration - java

I'm looking at migrating from ant to Gradle because we want to speed up builds by running projects in parallel and to simplify configuration, however it seems to me that these goals are mutually exclusive for Gradle builds. Hopefully I'm missing something.
So I'd like a nice example of a multi-project Gradle setup compiling 3 java projects such that A and B can be compiled in parallel and C depends on both. Also such that some properties can be configured (dynamically) and used in all three projects, perhaps configured in an additional root project.

What do you mean by configuring properties "dynamically"? in general you should be able to get a parallel executed build for a project with three subprojects as you have described. I pushed a sample skeleton project setup at https://github.com/breskeby/gradle-snippets/tree/master/multiparallel
hope that helps,
cheers,
René

here is an example app I built a week or two ago that covers this usecase: https://github.com/jadekler/git-java-websiteskeleton. Check out the settings.gradle in particular, as well as the application package which bundles all the other components (an individual java app, each) into one.

Related

Simple Versioning of a Gradle Project

I have a simple Java project that creates a JAR using gradle. The project is centrally managed in a gitlab repo and built with Gitlab CI. I'm okay if every commit in a certain branch is considered "released" (ie not SNAPSHOT).
Most plugins try to do a lot and add a lot of complexity and confusion. I just need something really simple and clean. I'm okay with just using gradle.properties to manage the major and minor versions and Gitlab's CI_PIPELINE_IID as the "patch". I'm also ok with something easier than this, if possible.
Does anyone have a sample project that can easily manage versions?
I found a way to put it all together...
gradle.properties:
majorVersion=1
minorVersion=2
build.gradle
..
version "${majorVersion}.${minorVersion}.${System.env.CI_PIPELINE_IID?:'dev'}"
..
I'm using Spring Boot, so I can just do a gradle bootJar and a properly versioned JAR shows up in build/libs. If the build was outside of Gitlab CI, the JAR ends in dev instead of the CI_PIPELINE_IID value. Of course, CI_PIPELINE_IID can be set to anything on the dev machine.

Maven Parallel Build - Sequence some modules

I have a multi-module maven project and looking to leverage the parallel build feature in Maven 3. But some of the modules lay the groundwork for future modules (when built sequentially, like creating some directories, downloading some non-maven jars etc). Is there a way for me to control the parallelism partially so that the build starts of sequentially and then goes parallel and eventually converge to a final module that does aggregation and cannot be run before the others?
Thanks in advance
Just add a dependency on the pom (pom) we use this to order our docker builds (images depend on base images that need to built earlier)
I haven't tested this, but I think it should be possible. The downside is you will have to control that branch/join logic yourself by running mvn multiple times.
First, check out this article for how to do parallel builds: https://cwiki.apache.org/confluence/display/MAVEN/Parallel+builds+in+Maven+3
Now when it comes to building individual modules, you should use this command line option:
-pl,--projects <arg> Comma-delimited list of specified
reactor projects to build instead
of all projects. A project can be
specified by [groupId]:artifactId
or by its relative path.
I think you will need to run the mvn command multiple times. Let me know if you need more info.
Side Note: Consider this line
This build-mode analyzes your project's dependency graph and schedules modules that can be built in parallel according to the dependency graph of your project.
You may not need to do any branch/join logic. See if it works without it.

Build multiple java projects with dynamic dependencies

I have multiple java projects in a folder. Also there is a second folder with libraries, that might be used as build dependencies from the projects. The projects may also have dependencies to other Projects. What's the best approach to build all projects ?
In other words I want to build the projects without explicit telling their dependencies.I think the biggest problem is the dependecy between the projects.
There are multiple build systems that are available that you may use. Maven has a complete dependency system built into it. Almost all third party open source jars are directly accessible via the World Wide Maven repository system. Basically, you describe the jar you need (groupId, artifactId, and version) and Maven will automatically fetch it for you. Not only that, but Maven also will build your project without having to create a build file. Instead, you have to describe your project in a project object model (a pom.xml file) and Maven will download everything you need, including all compilers, etc.
Almost all new projects use Maven, but Maven has a few downsides:
Since you don't control a build process, it can sometimes feel like poking a prodding a black box to get the build to work the way you want.
Documentation can be scant -- especially if you're moving beyond basic Java compiles.
You usually have to arrange your project in a specific layout. For example, source files should go under src/main/java while JUnit tests are under src/test/java. You don't have to follow the recommended layout, but then you'd have to modify the pom.xml file this way and that to get your build to work. That defeats the whole purpose of the pom.xml in the first place.
If you already have another build system setup (like Ant), you lose everything. There's no easy way to move from Ant to Maven.
The other is called Ant with Ivy. Ivy uses Ant for building, but can access Maven's world wide repository system for third party dependencies. It's a great compromise if you already are heavily invested in Ant. I also find Ant with Ivy to be better documented than Maven (although that's not too difficult). There's an excellent chapter going over the basics of Ivy in Manning Publication's Ant in Action.
With either process, I would recommend that you build a company wide Maven repository using either Nexus or Artifactory. This way, any proprietary third party jars (like Oracle jars) can also be stored in your company wide Maven repository since they won't be in the standard World Wide Maven repository.
By the way, if this is a company wide effort, and you are moving multiple Ant projects into Ivy, I have an Ivy project I use in Github that makes things easier.
Oh, there's a third possibility called Gradle which I know nothing about. I also believe it can use the World Wide Maven repository. It's based on Groovy which is based on Java syntax, and that's about all I can say. Maybe others can fill you in on the details. The Gradle group contends it solves a lot of problems of both Ant/Ivy and Maven.
Whatever tool you use, if you have various projects interdependent, you need to be clear on the independent ones which will be built first before building the dependent projects. You need to have a clear dependency structure for your projects.
You can do this with Apache Ivy. You can lay out the locations for you common libraries, define published artifacts and inter-dependencies in an ivy.xml document in each project, and let a top-level Ant build with the Ivy tasks figure out what the build order should be based on those dependencies.

Maven: Does project inheritance or aggregation better support this scenario?

I am porting a project from ant to maven. The project consists of a core set of classes which gets jar'd and used by 3-4 other subprojects. Importantly (I think?), the core jar has its own configuration that gets set at build time, and each subproject also has configuration set at build time. In the old ant system, anytime I built one of the subprojects with something like...
ant -Dconfiguration=stage clean dist
...it would build the core jar using the same (stage) configuration, and copy it into the classes dir of the subproject's build. I'd like to duplicate this functionality using maven. From the reading I've done, it seems like Maven can handle this using either project inheritance or aggregation. What are the chief differences between the two methods, and which would you recommend for the use case I've described?
Inheritance is used for sharing common things between your projects, such as 3rd party library dependency or properties, or scm locations. Aggregation is used to build your projects as a group. You want aggregation, but that doesn't mean that you won't also be using inheritance to factor out common stuff.
Update: also keep in mind that maven is not just about building (unlike ant), it is about dependency management, so you could just create dependencies on your core and not use aggregation at all. You would depend on a particular version of your core. This however doesn't satisfy your requirement of building everything at once.

Maven replacement?

What would you suggest as a replacement to the Maven Java build toolset? Just plain Ant scripts? SCons?
It depends on what you use anyway. Maven 1? Maven 2? I find Maven 2 decently documented, and quite powerful, when used in combination with Ant tasks and some home baked Java plugins.
There are Ant tasks to use Maven features from Ant: http://maven.apache.org/ant-tasks/index.html . So you don't really need to write your own "library".
And you can call Ant from Maven: http://maven.apache.org/plugins/maven-antrun-plugin/ .
You can also script things using Groovy for example: http://groovy.codehaus.org/GMaven+-+Executing+Groovy+Code .
Or just write Java code for the custom bits you need: http://maven.apache.org/guides/plugin/guide-java-plugin-development.html .
There's no reason not to mix and match, when you can do it ;)
While I like the idea of Maven, I always find myself fighting it for anything but the simplest configurations. Its architecture is plugin-based, and the quality of the plugins varies widely. Documentation is sketchy at best; half the time I can't figure out if the doc I'm reading is for Maven 1 or 2. And how often have you had to resort to using the maven-ant-plugin to do something basic?
I've been using Apache Ivy for about a year now, and I'm pretty happy with it. There is a bit of a learning curve though. But there's an active mailing list, and the author is very responsive.
What I ended up doing was writing a "library" of a few simple Ant targets such as "resolve", "compile", "install", etc. that expect things to be in standard Maven places (such as src/main/java) and then <import> the targets into my various projects. This way you get the best of both worlds- Maven-style configuration, and all the power of Ant.
I'm fond of using Ant with Ivy. Ivy uses Maven repositories to fetch library dependencies without forcing you to change your entire build system to suit Maven.
I've been using buildr for some of my projects. Very terse and readable build scripts (no xml) and it uses maven repos (with trivial effort, maven 1 and maven 2).
I was looking for something post-maven1 to work on for some projects and m2 wasn't all that appealing. Maven had already left all m1 users high and dry with the need to redo all of their build systems (and some of mine cannot be expressed in m2 as far as I can tell).
I really like using ant4eclipse - you set up your project dependencies in eclipse as normal and you can write a single ant script that'll build all the projects in the right order.
For third-party libs, you can either set up a single eclipse project containing (and exporting) all of your jars [I DON'T RECOMMEND THIS], or a separate project for each third-party lib, exporting the jar. [I recommend the latter b/c you can track project->third-party deps and upgrade parts when needed.]
I would go with buildr, if i am expecting complex build targets in my build. The benefit is, you are not dependent on any particular library at all. You have all the APIs from Ruby to do whatever you want; unlike Ivy in which case you are still tied up to ANT. Effort of migration to Ivy is worth if you want to introduce library dependency to an already established ANT based build mechanism which does all the operations you want to do.
There are at least three different parts of Maven: the repository, the implementation independent lifecyle and the conventions for a default project. Using Ivy provides only the repository.
I've not used it but I think that easyant is designed to be a more complete replacement to Maven. It uses Ivy as the repository but then adds conventions and standard modules.

Categories

Resources