Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JAR minimization #198

Closed
alicederyn opened this issue Mar 30, 2016 · 21 comments
Closed

JAR minimization #198

alicederyn opened this issue Mar 30, 2016 · 21 comments
Milestone

Comments

@alicederyn
Copy link
Contributor

Maven's shade plugin has the option to minimize the generated JAR, which is superb for behemoths like Guava. Is this feature a possibility?

@johnrengelman
Copy link
Collaborator

If someone would like to provide a PR, sure.
I hope it'll be something that will be including in v2, which I'm going to start thinking about/working on this summer. (yeah, that's out there, but I want to make Shadow more tightly integrated with Gradle without cracking into their internal APIs, so I need to do some work with them)

@magicgoose
Copy link

FYI, android gradle plugin does integrate with proguard, I guess it's possible to look how they did it.

@lbergelson
Copy link

@johnrengelman Is there any estimated timeline for this? I'm working on a project that's running into jar size issues and it would be ideal if we could use shadow to deal with them.

@johnrengelman
Copy link
Collaborator

No timeline on my side. Again if the community wants to take a crack at it that would be great.

@janschaefer janschaefer mentioned this issue Nov 9, 2016
@tcurdt
Copy link

tcurdt commented Nov 9, 2016

I am the original author of the minimize functionality. It should really not be that hard to add.

@lethevimlet
Copy link

lethevimlet commented Nov 27, 2016

This would be such a nice future I'm willing to implement it myself, I'll give it a shot @tcurdt could you post a step by step list of what the minimizeJar should do so I dont miss any optimizations, my intial idea is to recursively check class imports through reflection and exclude/include them on the shadowJar task.

meanwhile we can use proguard as a gradle task that depends on shadowJar
http://proguard.sourceforge.net/manual/gradle.html

@tcurdt
Copy link

tcurdt commented Nov 27, 2016

@josevimlet Sure, happy to help. Reflection is not the way to go though.

The way it works is to build a dependency tree of all classes through byte code introspection. With that available you can find the sum of all transitive class dependencies - which you want to keep. The rest you can safely remove.

Something along the lines of:

final File jar1 = ...
final File jar2 = ...
final Clazzpath cp = new Clazzpath();
final ClazzpathUnit artifact = cp.addClazzpathUnit(jar1, "artifact.jar");
cp.addClazzpathUnit(jar2, "dependency.jar");

final Set<Clazz> removable = cp.getClazzes();
removable.removeAll(artifact.getClazzes());
removable.removeAll(artifact.getTransitiveDependencies());

for(Clazz clazz : removable) {
  System.out.println("class " + clazz + " is not required");
}

The maven plugin code is pretty readable, too.

@lethevimlet
Copy link

lethevimlet commented Nov 28, 2016

Great I've been testing out proguard and I managed to make it work under gradle but I've realised you have to keep adding project specific stuff in its config to make things work, because its shrinking algorithm fails by default on advanced stuff, annotations etc if you don't add the proper config.

Therefore I'm afraid its going to be though to implement a general purpose minification, still I'll give it a try and will report any progress here.

Thanks a lot @tcurdt <3

@johnrengelman
Copy link
Collaborator

This was added 4.0.0

@johnrengelman johnrengelman modified the milestones: 5.0.0, 4.0.0 Oct 27, 2018
@gildor
Copy link

gildor commented Dec 7, 2018

I see this task closed and build in way to minimize is great, but some comment here and in #225 also mention Proguard and maybe we should reopen it. Because Proguard provides much more advanced minimization, configs. Just, for example, I have a small project, shadowed version of it about 2.2 Mb, minimized shadowed 1.1 Mb, but simple config of Proguard with minimization and obfuscation is only 300 Kb

So I believe it's still worth to reopen issue request with Proguard integration

@tcurdt
Copy link

tcurdt commented Dec 7, 2018

@gildor be aware that for some people the proguard license is a problem.

@gildor
Copy link

gildor commented Dec 8, 2018

Sure, I understand this,
Also, I don't expect that minimize() option of shadow plugin will cover all proguard features maybe additional plugin would be a better solution for this, like shadow-proguard
This can be a very powerful integrated tool for JVM application distribution

@netomi
Copy link
Contributor

netomi commented Apr 20, 2020

I found it a very nice use-case to use a full blown shrinker like ProGuard for the minimize feature. Due to the license problem as ProGuard is GPL software, I decided to use R8 which has similar capabilities wrt shrinking as ProGuard. I opened a new ticket: #565 and added a pull request for a proof of concept implementation. Feedback is welcome!

@Miha-x64
Copy link

There's no problem with ProGuard license.

ProGuard is free. You can use it freely for processing your applications, commercial or not. Your code obviously remains yours after having been processed, and its license can remain unchanged.

ProGuard itself is licensed under restrictive GNU GPL v2, and it becomes a problem only if you redistribute it. But you don't, you just add a dependency on it.
https://www.guardsquare.com/en/products/proguard/manual/license

@netomi
Copy link
Contributor

netomi commented May 31, 2020

well, linking Apache licensed software with GPL software (as for ProGuard) is not possible, see https://www.apache.org/licenses/GPL-compatibility.html

@Miha-x64
Copy link

Interesting. But

In addition, as a special exception, Guardsquare NV gives permission to link the code of this program with the following stand-alone applications:

  • Gradle,

https://www.guardsquare.com/en/products/proguard/manual/license/GPL-exception

Android Gradle Plugin have been using ProGuard for decades…

@netomi
Copy link
Contributor

netomi commented May 31, 2020

you should read up on the GPL and its implications before adding a GPL licensed library as dependency. The exception of ProGuard for certain applications does not apply for a gradle plugin imho, see also here:

https://github.com/Guardsquare/proguard/blob/master/core/src/proguard/GPL.java

only if gradle itself would use ProGuard code directly it would be allowed, any other code using it would violate the GPL and I am sure the FSF would be keen to investigate.

@LouisCAD
Copy link
Member

Woule make sense to open a new issue about supporting proguard specifically, with the links for the licensing info that show it's possible without violating proguard's license.

@johnrengelman
Copy link
Collaborator

johnrengelman commented May 31, 2020

Agreed. Let’s not keep this thread going.
My input on this is this:

  1. I don’t have the time to deal with licensing problems, so I’m not going to go down that road.
  2. Someone can author the proguard integration as a separate library that a user would need to add to their classpath to use
  3. I’m happy to accept PRs to open additional integration points to make 2 viable but that don’t pull the ProGuard code into Shadow.

@netomi
Copy link
Contributor

netomi commented May 31, 2020

I am not sure how the discussion diverted to the licensing issue. To avoid any licensing discussions I added a PR #566 to use R8 which is licensed under Apache but having the same capabilities as ProGuard wrt shrinking.

@johnrengelman
Copy link
Collaborator

Yup that’s fine and that PR will be given its own attention.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

10 participants