Proguard ignores config file of library
Asked Answered
B

4

33

I'm facing a really weird problem for days now...

I have a Gradle app with two modules, one main module and one library module.

  • In both modules I have declared a proguard-rules.pro file path which is correct
  • In both .gradle files I have minifyEnabled true

here is the first problem: even if minifyEnabled is false in the library, it gets obfuscated. it has no effect at all and seems to depend on the main module's settings. I´m using proguard since a while now and I've never experienced such a behavior at all.

Also, the proguard-rules.pro of the library seems to be completely ignored. It doesn't matter what I declare there, it is not used and the result is always the same (always decompiled to view result). It's obfuscated with the default settings.

I've used an invalid proguard file name to see if the file is even touched, and indeed there are errors with the wrong name and it also complaines about syntax errors in the proguard file...

I don't know if it is somehow related to an update of Android Studio, as it has also recommended me to use "minifyEnabled" instead of "runProguard".

How can I manage proguard to use the proguard-rules.pro of the library too?

Edit:

I've made an sample project to clarify my problem

enter image description here

The proguard config of my library

enter image description here

The gradle of my library:

enter image description here

And finally the result I always get. It doesn't matter what I exclude/include in the proguard config

enter image description here

As you can see, the proguard rules work quite well on the main module. It does what it should. But it always fully obfuscates my library to a.a....

It also has completely deleted the Activity of the Library, which shouldn't happen at all

Busboy answered 17/11, 2014 at 22:33 Comment(0)
C
93

You typically should not enable ProGuard in the library project. ProGuard processes the application and the library together in the application project, which is the most effective approach.

In the library project, you can specify any library-specific ProGuard configuration in build.gradle, e.g.:

defaultConfig {
    consumerProguardFiles 'proguard-rules.txt'
}

This file is then packaged in the library aar as proguard.txt and automatically applied in the application project.

If you do enable ProGuard in a library project (maybe because you want to distribute the library), then you also have to add the proper configuration for processing the library. The Android Gradle build doesn't seem to do this automatically. You can:

  1. Copy android-sdk/tools/proguard/examples/library.pro to proguard-project.txt in your library project.
  2. Remove the sample input/output lines -injars, -outjars, -libraryjars, -printmapping from the file. The Gradle build process automatically provides these options.
  3. Reference the configuration from the build.gradle of the library project.

Enabling/disabling ProGuard independently for the library project and for the application project works fine for me.

Cachalot answered 21/11, 2014 at 1:26 Comment(4)
Hello Eric, first of all thank you for your fast reply. I completely took out the minifyEnabled option in the library now and it indeed solved the "The output jar is empty" I mentioned in the email, but proguard is ignoring the proguard config anywaysLowpressure
Indeed, I´ve missed the consumerProguardFiles thing. Now it works, thank you very much :)Lowpressure
consumerProguardFiles should be specified in defaultConfig rather than buildTypes/release so that it works if the consuming application proguards in both debug and release mode (e.g. to avoid the 65k dex method limit).Guizot
This is really helpful, thanks a lot! Also, is there any way to hide/obfuscate the strings.xml file in the resources folder or any file in the asset folder? I see that these are just left untouched even after ProGuard.Ravioli
B
9

Amazingly, Eric's answer is actually working for me too!

Of course Eric knows what he is talking about, but I have [on and off] been trying to find a clean way to do this automatically in gradle for over a year with no luck until I just found this post today.

I combined a few other SO threads and came up w/ this solution that works, that may also be able to be simplified. Steps 1-4 are optional, but so far it hasn't seemed to have hurt.

  1. Download Proguard 5.2 from http://sourceforge.net/projects/proguard/files/proguard/5.2/
  2. Unzip to .../android-sdk/tools/proguard5.2
  3. Rename .../android-sdk/tools/proguard to .../android-sdk/tools/proguard4.7
  4. ln -s .../android-sdk/tools/proguard5.2 .../android-sdk/tools/proguard
  5. Copy android-sdk/tools/proguard/examples/library.pro to the library project folder and rename to proguard-library.pro
  6. Edit proguard-library.pro and comment out the -injars, -outjars, -libraryjars, and -printmapping lines.
  7. Edit the library's build.gradle file to include:

    defaultConfig {
      minifyEnabled true
      shrinkResources true
      proguardFiles 'proguard-library.pro'
      consumerProguardFiles 'proguard-library-consumer.pro'
    }
    

    You can tweak this to have different behavior for release and debug builds.

  8. proguard-library-consumer.pro

    # include in this file any rules you want applied to a
    # consumer of this library when it proguards itself.
    
    -dontwarn junit.**
    -dontwarn org.junit.**
    
    # Make crash call-stacks debuggable.
    -keepnames class ** { *; }
    -keepattributes SourceFile,LineNumberTable
    
Bartley answered 6/2, 2016 at 0:29 Comment(3)
Error:Resource shrinker cannot be used for libraries.Pornography
@Swooby Why we need both consumerProguardFiles and proguardFiles in lib module?Alkalinize
@Alkalinize consumerProguardFiles are rules for other people that use your library; proguardFiles are rules for the libraries that you useBartley
U
5

The only thing that worked for me is to define both options in my library:

release {
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
consumerProguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
Usher answered 6/12, 2016 at 7:14 Comment(3)
This actually worked.. for some reason just using consumerProguardFiles kept most of what I needed but randomly just ignored the rules for a few classes.. using both work.. but WHY!??Mortmain
Unfortunately, it really worked... Spent quite some time trying to do it, now it is just left to figure out WHY it worked :)Salmonella
* What went wrong: A problem occurred configuring project ':content'. > Default file proguard-android.txt should not be used as a consumer configuration file.Teetotum
M
0

I use below in library module and resolved.

proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
consumerProguardFiles 'lib_proguard-rules.pro'
Mortal answered 4/9, 2019 at 7:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.