How To Create Different Flavor Of Build with Maven - maven

I wants to build my anndroid project with maven.
There are 3 projects
Project - A (jar file )
Project - B (jar file )
Project - C (sdk package)
Project C is depended on B
Project B is depended on A
With maven I wants to release two flavor of by build
1st flavor : Release JAR from B (which contain code from B & A)
2nd flavor : Release SDK from C (which contain code from C & B & A)
Can I control this behaviors from MAVEN.

For the "1st flavor", you can use the maven-assembly-plugin with the predefined desriptor jar-with-dependencies that will embed all the dependencies into your project's jar, but pay attention to the transitive dependencies that could be embedded into it also. Otherwise you can also use the maven-shade-plugin which is having options that you could be interested in like minimizeJar and an easier way to configure of includes and excludes (see doc here).
For the "2nd flavor", the use of the maven-assembly-plugin would fit well with its bin descriptor or by defining your own descriptor if you need to include other files (see the descriptor format here). You can find a few examples on how to configure and use the maven-assembly-plugin for that on SO (you can also look at the questions I already answered about this plugin)

Related

How to list all usages of a gradle module

I have a project with multiple modules (gradle modules) and some are depend on some others, for example :modules:backend:core has a project dependency on :modules:libraries:util:core and some others.
In my gitlab CI job I am able to tell when there are changes within some module (e.g. :modules:libraries:util:core) by listening to something like modules/libraries/util/core/**/*, and then triggering a build of that changed module.
Now the issue I have is how to figure out where this module is used, so that I can build the other side also (in this example I would need to build :modules:backend:core once :modules:libraries:util:core is changed).
Is there some way to list all usages of given module ?
https://github.com/vanniktech/gradle-dependency-graph-generator-plugin
You can use this plugin to create "your project module dependency graph"
./gradlew generateProjectDependencyGraph
or "whole dependency graph".
./gradlew generateDependencyGraph
You can find this file from app/build/reports/dependency-graph and app/build/reports/project-dependency-graph directory.
The folder includes three files: png, svg and dot.
In the dot file, you can get the module dependency.
":app" -> ":base" ["style"="dotted"]
":app" -> ":moduleA" ["style"="dotted"]
":moduleA" -> ":base" ["style"="dotted"]

How do I use Gradle to build a special JAR with only a subset of classes?

I have been given a project A that needs access to class files from another project B. More precisely, A only needs classes compiled from the B/ejb/C/src portion of the B/ tree:
B/ejb/C/src/com/company/admin/Foo.java
B/ejb/C/src/com/company/admin/FooHome.java
B/ejb/C/src/com/company/admin/FooBean.java
B/ejb/NOTNEEDED/src/com/company/data/...
The person who had this A project before used JBuilder and included in the source definition pointers to the parallel project's B/ejb/C/src. The A project builds a jar which includes classes compiled from this other tree. I'm trying to figure out how to do this using Gradle. I want to make a B/build.gradle in the B project that will create a B-C-version.jar of .class files compiled from these sources:
B/ejb/C/src/com/company/admin/Foo.java
B/ejb/C/src/com/company/admin/FooHome.java
B/ejb/C/src/com/company/admin/FooBean.java
that I would then publish to Maven and access from the A project.
i.e., the B-C-version.jar would ideally only have these classes:
com/company/admin/Foo.class
com/company/admin/FooHome.class
but if B-C-version.jar had these classes:
com/company/admin/*.class
that would also be OK. How can I make such a thing using a build.gradle in the B project?
You can simply declare a custom Jar task like
task cJar(type: Jar) {
baseName = project.name + '-C'
from sourceSets.main.output
include 'com/company/admin/Foo.class', 'com/company/admin/FooHome.class'
}
or you can make a dedicated sourceset for your api that you then use from your other B code and from your A code, then you don't need to work with includes and update the include if you need to add files, but you just place them in the source folder of the source set and you are done, something like
sourceSets { c }
task cJar(type: Jar) {
baseName = project.name + '-C'
from sourceSets.c.output
}
Then you could also declare dependencies separately and get the correct ones drawn in transitively and so on. But it might be overkill in your situation.

Gradle dependency on module of another project failing

I realize there are a lot of posts online regarding Gradle setup. That being said, I have researched heavily and not found exactly what I'm looking for, or I'm using incorrect terms to do so. I'm using Gradle version 3.3.
So I've got multiple Gradle projects, each of which is maintained separately. There is no master Gradle project. Each projects has its own modules, build, and settings file. The structure of this is as so:
Projects
A
a1
build.gradle
a2
build.gradle
build.gradle
settings.gradle
B
b1
build.gradle
b2
build.gradle
build.gradle
settings.gradle
What I'm attempting to do is make B dependent on A's modules. Let's assume one of the modules in B is dependent on a1. In B's settings, I've done the following:
rootProject.name = 'B'
rootProject.setProjectDir(new File(".")
include 'a1'
project(':a1').setProjectDir(new File(settingsDir.getParentFile(), "/A/a1"))
The way I'm storing version numbers is through each project's build.gradle file in the ext closure. I then access them through the project. Here's how B's build file looks:
ext {
freemarkerVersion = '2.3.19'
}
dependencies {
compile project(':a1')
compile group: 'org.freemarker', name: 'freemarker', version: rootProject.properties.get('freemarkerVersion')
}
What I'm seeing is B is able to resolve its dependencies and is attempting to compile project a1, but it is using B's version numbers instead of A's. I verified this by putting a common dependency in both projects with different version numbers. The dependency showed up using B's version. I also changed the version number in B and further confirmed this. So if I could get any help for using project-appropriate versions in each of their own build.gradle files, that would be great!
EDIT: Updated post, figured out previous problem was from relative path not resolving.
Not to toot my own horn or anything, but I'm posting the solution I came up with, as I had no other answers knocking down my door.
The first thing I did was moved all of my version properties to an external gradle.properties file, instead of in an ext closure in the project's build.gradle file. Doing this, the project will load the properties file by default when compiled from its own context. It will of course be overridden from the user.home gradle.properties file, so keep this in mind. Example gradle.properties:
a_freemarkerVersion = 2.3.19
When using one project's modules from another project, you'll need a way to separately link the two so Gradle can resolve the dependency's properties. I achieved this by defining a method to load in the desired project's properties file. This method looks like so:
def addConfig(String parent, String filename) {
Properties props = new Properties()
props.load(new FileInputStream(new File(project.projectDir.getParent(), "/${parent}/${filename}")))
props.each { prop ->
project.ext.set(prop.key, prop.value)
}
}
addConfig("A", "gradle.properties")
All this method does is goes up one directory, goes into the project specified, and retrieves its gradle.properties file and loads these variables into the current project's properties. With that being said, there's one thing to note here: if you define the same variable in both, one of them will be overridden. To avoid this, I just prefixed all variables with the project name and then an underscore. This will guarantee they'll never conflict with one another.
I accessed the variables in all projects with this syntax:
dependencies {
compile group: 'org.freemarker', name: 'freemarker', version: "${a_freemarkerVersion}"
}
The rest of the setup is the same as I defined in my initial post. Just make sure to include the dependent module, specify its project directory, and compile that project from within the project's dependencies.

Buildr Manifest generate class-path from EAR package

I am using (and learning) Buildr to build and package my projects. I would like to auto generate the class-path attribute in an EJB projects MANIFEST file. Currently I am doing:
manifest_cp = compile.dependencies.map { |d|
"#{File.basename(d.name)}"
}.join(" ")
package(:jar).with :manifest=>manifest.merge('Class-Path'=>manifest_cp)
I am new to Ruby and Buildr so there probably is a better way to do this. However I was actually hoping to be able to generate the jars I define and package in my EAR as opposed to getting the compile dependencies in my JAR.
I package my ear project like:
package(:ear).include(ANTLR, AOP_ALLIANCE, ...
Is it possible in my EJB project build when packaging the jar and modifying the manifest I create the Class-Path attribute with all the dependencies packaged in the EAR? On top of that I would also like to exclude one or two dependencies?
thanks
UPDATE
I tried a different approach that seems better (but still probably there are much better ways than what I have). I created a constant that held all my artifacts I want to include in my EAR and then built up the classpath string:
EARLIBS = [ANTLR, AOP_ALLIANCE, ... ]
manifest_cp = Buildr.artifacts(EARLIBS).each { |artifact| artifact.invoke }.map{ |d|
"#{File.basename(d.to_s)}"
}.join(" ")
When I package the EJB I specify the manifest_cp that was created above:
package(:jar).with :manifest=>manifest.merge('Class-Path'=>manifest_cp)
When I package the EAR I reference the constant declared with all the artifacts:
package(:ear).include(EARLIBS)
Even though this works for what I want I would appreciate it if anyone has a better way of doing it
thanks,
The builds doc for the EarTask contains the solution I believe:
All specified libraries are added to the EAR archive and the Class-Path manifiest entry is modified for each EAR component.

Can Gradle handle local dependencies to other than sub-directories?

I don't know if I totally got the concept wrong, but I want to create several projects with dependencies to other projects which are not part of the directory structure of a parent project. I know that the normal way of doing this would be to use an external dependency which fetches from some external repository. But in this case, where let's say in project called 'F' a framework is developed, which is used in project 'P'., then P uses F, but F should IMO not necessarily be a sub-project of P as P is only used to test-drive the development of F (but it's not only a unit test). Later in the process, when F is stable, F is separated and can be consumed by other projects via a repository. But during development of F with P as it's test case, it would be nice if that round-trip through the repository could be omitted.
To make matters worse, for the initial development there is more than one test-driving consumer project, which all need to have a dependency to F, but not via an external repository.
My idea is to develop F in some place on the disk with it's own git reposity. The other P like projects reside somewhere else on the disk and have a local file system based dependency to F. Would such a construct be possible in Gradle? If so, where do I start? I scanned the Java examples but couldn't find an appropriate example.
Any ideas?
The Gradle project hierarchy is fully virtual. It just has the default that the physical location corresponds to the virtual hierarchy. But you have complete control over this. See: http://gradle.org/0.9-rc-1/docs/userguide/build_lifecycle.html#sec:settings_file
Regarding your other ideas have a look at the following Jira: http://jira.codehaus.org/browse/GRADLE-1014
You could consider a folder hierarchy like this one:
Main folder
|- F folder
| |- .git
| |- sources
| |- build.gradle (with parts specific to F)
|- P folder
| |- sources
| |- build.gradle (with part specific to P)
|- build.gradle (with common parts)
|- settings.gradle
So you can always decide to run gradle on either the F project, the P project or the two alltoegether. It will also allows you to promote you F project alone without the P or any other side projects.
For more up-to-date information, check the Multi Project Builds chapter of the Gradle documentation.

Resources