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

Clarify meaning of "present" for -if option #344

Open
Marcono1234 opened this issue Jun 17, 2023 · 5 comments
Open

Clarify meaning of "present" for -if option #344

Marcono1234 opened this issue Jun 17, 2023 · 5 comments

Comments

@Marcono1234
Copy link

The documentation for the -if option currently says:

Specifies classes and class members that must be present to activate the subsequent keep option

Could you please clarify what "present" here means? I assume it means "present after the shrinking phase" (in that case please adjust the documentation). Because for example in the context of R8 (and I assume the same applies to ProGuard) I saw usages like -if class *, and without this "after shrinking", that option -if class * would seem like a no-op / be always true.

As side note: The Dagger and Butterknife examples referenced from the -if documentation and various other places don't seem to exist anymore.

@mrjameshamilton
Copy link
Collaborator

Hi @Marcono1234 ,

These kind of rules are normally used where some library/tool generates classes based on the name of other classes e.g. some Foo_TypeAdapter class is generated for a class named Foo; then you can write a keep rule like the following which captures the prefix using a wildcard to keep the original class but not the _Adapter class:

-if class **_Adapter
-keep class <1>

See this example on the ProGuard Playground: https://playground.proguard.com/p/YLS4pH

-if class * on it's own seems like a mistake.

@Marcono1234
Copy link
Author

Thanks for the answer! Is there a reason then why the documentation has "present" formatted as "present"? I assumed this meant something special.

-if class * on it's own seems like a mistake.

Maybe that is some (undocumented) special behavior for R8 then, see also google/gson#2397 (comment).

@EricLafortune
Copy link
Contributor

It's a good question. To be precise, -if refers to classes before each shrinking/optimization/obfuscation step. Initially, this is your original code, but with -optimizationpasses 2 (or more), this can also be the code after a prior shrinking/optimization step. Technically, -if could be applied during the shrinking step, but it would then have to be applied recursively. Right now, it's more conservatively iterative for the subsequent passes.

-if class * could be useful if the corresponding -keep option refers back to the class wildcard *. For some framework that relies on reflection, the following could be necessary:

-if   class *
-keep class <1>_Foo

Such a construct may be suboptimal, if the kept classes aren't really necessary (as always).

@Marcono1234
Copy link
Author

Marcono1234 commented Jun 25, 2023

Thanks for the clarification!

To be precise, -if refers to classes before each shrinking/optimization/obfuscation step.

If I understand it correctly then, for ProGuard an -if class * would always keep the class, since it is also executed before the first shrinking step. I assume for R8 it might be different then because if I recall correctly it did make a difference there whether -if class * was used or not. So maybe they are performing some shrinking or optimization already before the first evaluation of the -if. -if class * has also been recommended a few times by R8 developers, for example in https://issuetracker.google.com/issues/150189783#comment11.

Such a construct may be suboptimal, if the kept classes aren't really necessary (as always).

It appears to me that even though it is suboptimal, for R8 it is at least better than just using -keep which would always keep the class, so I assume that is why the R8 developers recommended it.

Would it be possible to adjust the ProGuard documentation to replace or adjust the confusingly formatted "present" (as mentioned above)? Maybe it would also be useful to mention in the documentation what you said about -if being evaluated after every shrinking / optimization step, in case that has any potentially relevant effects for ProGuard.

@EricLafortune
Copy link
Contributor

My musings about the technical details may have added to the confusion -- the bottom line is that ProGuard may still remove both the -if class and the subsequent -keep class if they are not explicitly kept in your further configuration, and not used in your app (the former class in a first pass, the latter class in a second pass because the former class is gone). Only if the former class is kept or used, you can be sure the latter class remains too.

The automatically converted highlight present should be a more apt present or just present.

The initial rule for GSON in the R8 tracker seems correct to me. The correction suggested later probably works, but the -if class * makes no sense there -- the rule should work without it (with <1> just specified as *).

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

No branches or pull requests

3 participants