Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Proguard, keep all referenced classes

Assume I have structure:

import some.other.Clazz;

public class A {

    Clazz clazz;
    B b;

    public class B {
        C c;
        //...
    }

    public static class C {
        //...
    }
}

Is there some nifty proguard trick that would allow me to recursively keep all classes that are used by my class A? So also all classes that are referenced internally by B, C and Clazz?

like image 292
Bartek Lipinski Avatar asked Sep 18 '17 13:09

Bartek Lipinski


People also ask

How do you keep a class in ProGuard?

-keepclassmembernames. This is the most permissive keep directive; it lets ProGuard do almost all of its work. Unused classes are removed, the remaining classes are renamed, unused members of those classes are removed, but then the remaining members keep their original names.

Does ProGuard remove unused classes?

Shrinking Options By default, ProGuard shrinks the code: it removes all unused classes and class members.

What does ProGuard keep do?

-keep Specifies classes and class members (fields and methods) to be preserved as entry points to your code. For example, in order to keep an application, you can specify the main class along with its main method. In order to process a library, you should specify all publicly accessible elements.

What is Dontwarn in ProGuard?

If your code works fine without the missing classes, you can suppress the warnings with '-dontwarn' options. ( http://proguard.sourceforge.net/manual/troubleshooting.html#unresolvedclass)


1 Answers

I dont think you can do that with proguard only and I really doubt there is a straightforward solution (plugin you can use) with mvn\gradle\sbt\whatever for this.

If you're ok with running code or shell commands during your build I can recommend you some building blocks but, since putting them together really depend on how you build your project I can only give basic suggestions on how to glue them together.


The general idea is:

(1) Use jdeps (part of and distributed with jdk) to fetch dependencies (including transitive) from compiled .class files of interest.

In your case outputting recursive dependencies of some.class (limited to root_package) should be something like:

jdeps -v -R -e "root_package.*" some.class

(2) grab jdeps output and transform it into proguard config (list of classes to -keep).

(3) In your main proguard config file include config file you generated in (2).


Step (2) requires most legwork and can be approached differently.

My suggestion is to use whatever scripting capabilities your build system has to run jdeps and do output transformation.

Maven, for example, has plugin that allows groovy scripts to be executed during build.

If you are more comfortable with running shell scripts you can do the following:

  1. pipe jdeps output into something like:

    grep -Po classname_regex

    ... to keep only class names you want to keep (you can use zero-length assertions to build classname_regex).

  2. pipe output of grep into something like:

    awk '{print "-keep class " $0}

    ... to get proguard config and save output to file.

like image 50
Eugene Loy Avatar answered Sep 23 '22 14:09

Eugene Loy