I'm looking for information about Gradle dependencies, similar to this question:
What is the Gradle artifact dependency graph command?
but with a narrower scope. I'm wondering about functionality that Maven has for analyzing dependencies, and whether or not Gradle includes something similar. Specifically, Maven can scan your source code and then compare that to your declared dependencies, and determine (roughly) if you have dependencies declared that you aren't using and/or if you're using dependencies that you haven't declared (due to issues related to Turing completeness, this analysis may include false positives/negatives, but I generally find it to be incredibly useful regardless). Does Gradle have anything similar? So far I haven't been able to find anything.
Such a thing is not shipped with Gradle at least as far as I know.
You best bet is to search through Google and / or plugins.gradle.org for finding a plugin that does what you want.
I for a short period did this for you and found this one which might be what you want: https://plugins.gradle.org/plugin/com.intershop.gradle.dependencyanalysis
I have no idea about its quality or anything, I just searched through plugins.gradle.org, I don't know or ever used that plugin.
Related
I am working on migrating multi module java project into maven. Now for most of them i migrated to maven.
Finally i am aware my project have lot of unnecessary jars included, and i want to clean them up.
I know maven has plugin command, mvn dependency:analyze. Which works very well.
dependency:analyze analyzes the dependencies of this project and determines which are: used and declared; used and undeclared; unused and declared. based on static code analysis.
Now my question is that, how can i remove reported unused and declared dependency for cleanup purpose. It could be possible those jars were getting used at runtime and my code will compile perfectly fine after removing but blow up at runtime.
An example: mycode compile with one of opensource library antisamy.jar but it require batik.jar at runtime. And mvn dependency:analyze reports me to remove batik.jar.
IS my understanding correct or i need expert inputs here.
Your understanding seems to be correct.
But I'm not sure why you'd think that there is a tool that could cover all the bases.
Yes, if you use stuff by reflection, no tool can reliably detect the fact that you depend on this class or the other.
For example consider this snippet:
String myClassName = "com." + "example." + "SomeClass";
Class.forName(myClassName);
I don't think you can build a tool that can crawl through the code and extract all such references.
I'd use a try-and-fail approach instead, which would consist of:
remove all dependencies that dependency:analyze says are superfluous
whenever you find one that was actually used, you just add it back
This could work well because I expect that the number of dependencies that are actually used by reflection to be extremely small.
I am using Maven to build my project. There are lot of dependencies which are in provided and runtime scope. The build size is large and I want to remove the unwanted dependencies. So is there any way in which I can check which dependencies are unwanted.
The best way to minimize dependencies to the ones you really need is to not embed that dependencies. If you simply use the maven-bundle-plugin on your code it will create Import-Package statements for the code you really need. This might even give you a good hint on what dependencies you might be able to exclude for embedding.
In general in OSGi the goal should be to not have that many dependencies in the first place. If you use libraries with extensive dependencies then your should question the quality of these.
The project I'm working on has dependencies on a few well known and big libraries. Things are working well, the transitive dependencies are playing nice with each other, for now. But unfortunately the total bundle size is around 100 megs.
I'm not sure if this is too large or not, but is there a way in maven to effectively remove dependencies, without making pom.xml very verbose and long?
And pointers to help me in the right direction would be awesome!
You can remove dependencies by declaring exclusions. The question I would post to first though is .. why do you want to remove them?
Unless you know that the dependencies are not needed, it might not make sense to try to remove them. Especially not if there are no issues e.g. in terms of application performance or startup times.
The Maven Dependency Plugin as well as the Eclipse integration have tools that allow you to understand the dependencies better with tools like the dependency:tree goal or the Dependnecy Hierarchy view of the POM.
Don't try to fix something that is not broken.
BUT ..
if you really know what is needed at runtime and use the tooling from Maven and M2e you can potentially remove a lot of bulk of your final artifact. However you will have to configure it in the pom using dependency exclusions. Newer Maven versions even allow patterns being used.
Another thing you can do is use a tool like proguard that removes all unused classes from the final artifact. This can be considerably complex but also VERY effective.
It will really be up to you to find the right balance between effort and benefit of outcome.
I'm setting up a (java) maven project that depends on a library (Jettison, among others) that is in the Maven repo. Jettison, in turn, depends on stax. I need to run a tool (Jar Jar Links) on stax (to change the namespace). How do I alter the rules for a transitive dependency in a maven project? My transitive dependencies are being included in my target folder using the copy-dependencies goal (I assume this is how things are usually done). I assume that this is the point where the plugin would be run on the transitively-generated artifact.
Extra question: I don't need this at this point but how would I go about altering the source in the transitive dependency? I can get the jar of the source with mvn dependency:sources but, from there, I'm not sure what the right approach is.
Victory!
Seems at least two people are even more clueless about Maven than me so let me explain what I'm doing before I report the fix at the bottom of this post (spoiler alert: it looks to be a bug in JarJar).
Android uses Java but its missing a lot of the java core (specifically, javax classes). The Android DEX compiler (which converts .jars to Android .dex files) won't even allow you to compile things in the java.* or javax.* namespace because it'll (usually) break stuff. However, in some (many) cases, there are routines that you might want to include -- specifically because they are used by existing libraries. The most legendary is StAX, which is why Google posted an example of how to include it here in the Dalvik repo's wiki. The example uses JarJar... with ant. Transitive dependencies are not really an issue when you aren't using a repo so they are not addressed in the wiki.
I was able to get JarJar to run on my source with Maven but without changing the namespaces in the dependencies (and transitive dependencies), that's worthless. Hence my question.
I thought that the copy-dependencies plugin might be useful for... copying the dependencies and running a transforming plugin in the process. Copying dependencies is mentioned as a step in the official "Maven in 5 minutes" doc so it seemed like a good start but maybe the the people who wrote the official docs don't know how to use it :-) . Either way, it it didn't help -- there is no simple way I could see to transform the jars as it copies.
Using the verbose spew from Maven, I was able to see that Jar Jar was in fact processing my jars properly... and then throwing out the result. It would have packaged the converted classes from the transitive dependencies in my artifact with the rest of my code but, instead, it "Excluded" them. Jar Jar parameters are basically undocumented and most of the tags aren't even listed in the docs but all of the examples I could find use a section with wild-cards that tell it what classes to hold onto. At least I thought (think?) that's what the section is for. Instead, it seems to randomly throw out stuff. Basically, the section is busted. For example, I had:
<keep>
<pattern>com.example.**</pattern>
</keep>
...thinking that this would keep classes that began with com.example. Wrong. It keeps whatever the hell it wants. I tried a million things in that spot until one worked:
<keep>
<pattern>*.**</pattern>
</keep>
This only keeps the classes I wanted -- the classes it updated and the originals of the ones that it didnt touch. Note that ** doesn't even work. This is version 1.8 of the JarJar plugin (the version most poms Ive found use).
Back to work.
A problem that relates to basic maven concepts:
Once released I would like to have a guarantee that the project build is fully reproducible. So all project and plugin dependencies, including transitive one, should be always resolved the same way.
Unfortunately it is not the case, if dependencies are expressed in terms of version ranges. It can happen that even though direct dependencies of a project are set (using versions:use-releases), the transitive dependencies can still be resolved in some other way in the future.
How to address the problem? Is there a known solution?
I was thinking (just an idea), about creating a plugin, which on release time would dump all dependencies of the project to a separate file, and then once building in the future, the dependencies read from the file would take precedence over the standard way maven uses to resolve dependencies. But I'm afraid that there is no plugin api for that. So it would require some hacking, which I would like to avoid. Is there another way?
Thanks,
Lukasz
Freeze artifacts versions using <dependencyManagement>. Even if you don't use version ranges (as you said), but rather 3rd party libs (your dependencies) do, your <dependencyManagement> will have higher priority in specifying version of any artifacts.
The simple solution is: Do not use version-ranges. This is bad practice cause it will result in the described problems.