java 1.8 and retrolambda support

928 views
Skip to first unread message

Giorgio Zamparelli

unread,
Apr 11, 2015, 5:26:05 AM4/11/15
to buck-...@googlegroups.com
I've been using rxjava on Android project built with Buck.
I would like to simplify the callback syntax with functional programming goodies available on java 1.8.
I managed to build my Android project using retrolambda and the retrolambda Gradle plugin.

I did not have success so far into building the Android project with Buck + retrolambda + java 1.8

retrolambda does support command line applications.
So in theory it would be possible to add a step to the buck build where the code compiled in java 1.8 is adapted to java 1.7 code using retrolambda.

The retrolambda documentation says:

Run Retrolambda, using Java 8, on the class files produced by JDK 8. Run java -jar retrolambda.jar without any additional options to see the instructions (for your convenience they are also shown below).

so far what I tried was: 

1) add the following lines to the .buckconfig

[java]
  source_level = 8
  target_level = 8

and got error:

An exception has occurred in the compiler (1.8.0_25). Please file a bug at the Java Developer Connection (http://java.sun.com/webapps/bugreport)  after checking the Bug Parade for duplicates. Include your program and the following diagnostic in your report.  Thank you.
com.sun.tools.javac.code.Symbol$CompletionFailure: class file for java.lang.invoke.MethodType not found


2) add retrolambda-2.0.1.jar to the buck-libs folder and got error:

UNEXPECTED TOP-LEVEL EXCEPTION:
com.android.dx.cf.iface.ParseException: bad class file magic (cafebabe) or version (0034.0000)
at com.android.dx.cf.direct.DirectClassFile.parse0(DirectClassFile.java:476)
at com.android.dx.cf.direct.DirectClassFile.parse(DirectClassFile.java:406)
at com.android.dx.cf.direct.DirectClassFile.parseToInterfacesIfNecessary(DirectClassFile.java:388)
at com.android.dx.cf.direct.DirectClassFile.getMagic(DirectClassFile.java:251)
at com.android.dx.command.dexer.Main.processClass(Main.java:691)
at com.android.dx.command.dexer.Main.processFileBytes(Main.java:660)
at com.android.dx.command.dexer.Main.access$600(Main.java:81)
at com.android.dx.command.dexer.Main$1.processFileBytes(Main.java:598)
at com.android.dx.cf.direct.ClassPathOpener.processArchive(ClassPathOpener.java:284)
at com.android.dx.cf.direct.ClassPathOpener.processOne(ClassPathOpener.java:166)
at com.android.dx.cf.direct.ClassPathOpener.process(ClassPathOpener.java:144)
at com.android.dx.command.dexer.Main.processOne(Main.java:622)
at com.android.dx.command.dexer.Main.processAllFiles(Main.java:517)
at com.android.dx.command.dexer.Main.runMonoDex(Main.java:284)
at com.android.dx.command.dexer.Main.run(Main.java:243)
at com.android.dx.command.dexer.Main.run(Main.java:213)
at com.facebook.buck.android.DxStep.executeInProcess(DxStep.java:181)
at com.facebook.buck.android.DxStep.execute(DxStep.java:165)
at com.facebook.buck.step.DefaultStepRunner.runStepInternal(DefaultStepRunner.java:74)
at com.facebook.buck.step.DefaultStepRunner.runStepForBuildTarget(DefaultStepRunner.java:60)
at com.facebook.buck.rules.CachingBuildEngine.executeCommandsNowThatDepsAreBuilt(CachingBuildEngine.java:550)
at com.facebook.buck.rules.CachingBuildEngine.buildOnceDepsAreBuilt(CachingBuildEngine.java:394)
at com.facebook.buck.rules.CachingBuildEngine.access$3(CachingBuildEngine.java:318)
at com.facebook.buck.rules.CachingBuildEngine$1.onSuccess(CachingBuildEngine.java:192)
at com.facebook.buck.rules.CachingBuildEngine$1.onSuccess(CachingBuildEngine.java:1)
at com.google.common.util.concurrent.Futures$6.run(Futures.java:1319)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
...while parsing net/orfjackal/retrolambda/files/BytecodeFileVisitor.class

Giorgio Zamparelli

unread,
Apr 14, 2015, 3:28:45 AM4/14/15
to buck-...@googlegroups.com
so I've spend the last three days trying to make this work. 
I got pretty close and discovered there is only one approach to solve this.

I used genrule() and a shell script that did the following steps.
1) unzip the content .jar file that was the output of the previous android_library() build step
2) run retrolambda on the .class files that were inside the .jar to convert their bytecode from java 1.8 to java 1.7
3) zip back the .class files inside the original .jar

This worked fine for the .java source files.
The problem is the R.java file.
The R.java file is not generated by Buck during the android_library build step.
The R.java file is generated during the android_binary build step.

The android_binary build step is one massive step and as far as I know there is no way to hook in some genrule build step after the generation of R.java and the Dex build step.

So the only possible way to use retrolambda with buck would be to modify the Buck (open) source code and add a new class RetrolambdaStep which should execute after the AaptStep (which generates R.java) and before the DxStep.

Right now I don't have enough time to compile and modify Buck to add such step.

Piasy Xu

unread,
May 2, 2016, 12:11:52 PM5/2/16
to Buck
Hi I have create a demo project that could let BUCK and RetroLambda work together, check it out! https://github.com/Piasy/BuckJava8RetroLambdaDemo

在 2015年4月11日星期六 UTC+8下午5:26:05,Giorgio Zamparelli写道:
Reply all
Reply to author
Forward
0 new messages