Open advayDev1 opened 9 years ago
Doesn't the Java compile remove unused code on its own?
Can you cite that claim? I don't know of anything like that.
I am not sure about that but I thought that Java compiles only the code you are using and removes unused code. Isn't that the case?
i don't see how that is possible. javac doesn't automatically know what endpoints your code has - that is why you have to configure ProGuard with endpoints. then you can figure out what code is statically reachable from those endpoints.
i'd really like to see a reference about what you're talking about.
Or was it GWT which removes unused codes. Not sure.
Please do find a reference, then we won't be guessing...
@confile - javac eliminates only if (true) { x } else { y }
style constructs, and that only optionally, per http://stackoverflow.com/questions/17965562/javac-code-elimination-capabilities/17966917#17966917
@advayDev1 may be you are right. I am not an expert on that. You had a good idea.
impl note:
Depend on app:proguardRelease
Add translate arg --dead-code-report APP_PROJECT_DIR/build/outputs/mapping/release/usage.txt
@advayDev1 Are you working on a proguard task? If so there is a proguard.gradle file in the proguard sample folder.
There's no need for a task. This is just about hooking up the right argument to our existing tasks.
The reason this didn't go anywhere for me is that I could not get j2objcc to succeed with my proguard files. It seemed like too many methods were always removed, so compilation would not succeed. I assume it has something to do with build-closure. If you would like to try this out, please feel free - I don't have time atm.
So you say. ProGuard does not work for you?
no, proguard for my app on Android works perfectly. Taking that proguard dead-code file from the Android build, and piping it into j2objc eliminates too many methods (it seems), and the compile fails with missing methods.
Do you see any solution for that?
haven't had time to investigate yet. if you do, please update the thread.
@advayDev1 Could you please post your ProGuard config file is it is open. Then I can try to start with.
i'm not sure what you mean. i use the default proguard rules that come with android sdk. nothing special.
I am just interested which libs you configure in the proguard config file. I have no clue how ProGuard works yet.
@advayDev1 what I meant was that I need a little help with how and which libs I have to specify. One of your examples would be very helpful.
I have no idea how proguard works but from the example here
-injars app-bin.jar
-libraryjars <java.home>/lib/rt.jar
-dontoptimize
-dontobfuscate
-dontpreverify
-printusage
-dontnote
-keep public class com.foo.app.Main {
public static void main(java.lang.String[]);
}
-keepclassmembers class * {
static final % *;
static final java.lang.String *;
}
it looks like we have to specify all the endpoints to Objecive-c in order to get them not being removed. It is similar to the main function I guess.
@advayDev1 @brunobowden The simples way to do this automatically might be with an annotation. Something like
@ObjectiveCEndpoint
This can be used to annotate classes and functions in Java. Next, an annotation processor could collect all the functions and print then in a proguard config file.
What do you think?
@advayDev1 @brunobowden I would like to here your thoughts on my idea?
sorry forgot to update; my internal implementation has proguard + j2objc working for the most part. however, we should definitely not make annotation processors a part of this plugin - they are unnecessary complexity. you can add an annotation like ObjectiveCEndpoint (I use a more general DontShrink(value=reason) named after proguard's dead code removal option), but then add the following to your proguard (replace VisibleForTesting with the FQN of your annotation class)
-keep @com.google.common.annotations.VisibleForTesting class *
-keepclasseswithmembers class * {
@com.google.common.annotations.VisibleForTesting *;
}
also, i have not PR-ed my proguard code because to do it right requires first splitting the main and test source sets and having them built and translated separately. why? because the proguard report you get by default does not consider code you use defined in main used only in test. so your j2objc translate step with such a proguard usage report fails.
splitting our sourcesets is a substantial refactor #112 which i do not have time for right now. if @confile or @brunobowden do have time, by all means please do
@advayDev1 I would like to help but I am totally blocked unless I get the plugin to run. Otherwise my code would be alway untested.
@Confile - please reduce your code down to a failure case that you can share with us. It's very difficult to assist you without something like this.
On Thu, Jul 23, 2015 at 3:49 PM Michael Gorski notifications@github.com wrote:
@advayDev1 https://github.com/advayDev1 I would like to help but I am totally blocked unless I get the plugin to run. Otherwise my code would be alway untested.
— Reply to this email directly or view it on GitHub https://github.com/j2objc-contrib/j2objc-gradle/issues/247#issuecomment-124259747 .
@advayDev1 I know :-) I will do my best.
@advayDev1 What do you think about proguard-annotations? https://github.com/yongjhih/proguard-annotations
I don't see why we should bind ourselves to a particular Proguard annotations library. That library is not a community standard (looking at the number of forks/etc.) and I don't see it recommended by Google/Android/Proguard etc.
Proguard already has a way of denoting what to keep: the rules file.
@advayDev1 How did you proceed in making your j2objc translated which was reduced with proguard work?
I guess you compile in xcode, see what was missing and add keep rules. Is this the way to do it?
No. Assume my application is one android Java app project, one iOS Xcode project, one iOS Java j2objc project, and many shared Java j2objc support projects. All of the API used by my iOS Xcode project is exposed solely via the public API of the iOS Java j2objc project. I keep all of that project's public endpoints. Then by running Proguard against the iOS Java j2objc project, I'm guaranteed to keep all the correct transitively used code in all shared j2objc projects as well.
So this means when you have an interface:
public interface MyInterface {}
which you implement in objective-c, than you add a keep rule for the whole interface?
No, I keep the whole public API of any class that I use in objective-c.
@advayDev1 I try to build a proguard task for the plugin. Hope to make a first push later
Which task should the proguard task depends on?
What do you mean you built a proguard task? Proguard already has a Gradle tasks. We don't need a new task. What you need to do is just pass the proguard output dead code report to j2objc TranslateTask.
Don't we need a task which runs the following?
java -jar $PRO_GUARD_HOME/proguard.jar @proguard-rules.pro > usage.log
A ProGuardTask should also auto include the dependencies.
We should use the standard Proguard task: http://proguard.sourceforge.net/manual/gradle.html It is also what Android uses.
Ok great. Could you please post your pro guard task you are using for j2obc?
What "depends on" should this task have or finalized by? I mean where do I have to put this task into?
@confile - I think you are misunderstanding something. There is no task for us to write - it has already been implemented, see the link above. While I did have a version of hooking up this task to j2objc internally a while back, I do not have time to clean it up to open-source it right now.
You are welcome to submit a PR yourself, but you will have to do the research yourself - unfortunately I just don't have time. If you would like to do the investigation and implementation, let me know and I'll assign the bug to you.
Could you at least tell me on what task the proguard task should depend on?
@confile - maybe the 'jar' task or the 'classes' task? please do the research, it is part of solving the issue...
Voting to punt post 1.0 unless someone has cycles to implement this. I do not.
j2objc allows you to pass in a proguard report to remove dead code. Android Gradle projects will create such reports within their 'proguardRelease' task.
We should add a j2objcConfig DSL method that allow you to set this up. This method configures the right j2objc argument, and also causes j2objcPreBuild to depend on the android project's proguardRelease task.
Note when this functionality is used, the build will proceed as follows: