greenrobot/EventBus

Generated EventBusIndex.class order should not change on every build

GrazianoCapelli opened this issue · 6 comments

Hi,
First of all thanks for making and publishing your great EventBus library.
Very simple to use and stable, I love it.

I opened this issue because I'm trying to compile our free and open source app BasicAirData GPS Logger in a deterministic way in order to have a reproducible build of the APK.
One of the first tests I made is to build the app 2 times and verify if the 2 builds are identical, and I found that they differ on the EventBusIndex.class, that have the rows in a different order.

Here below you can view an extract of the output of my diffoscope:

Schermata del 2023-05-10 23-20-54

I made the test using your latest EventBus v3.3.1 and the v3.2.0, and both have this issue.

I'm using the following Java version on Android Studio Electric Eel | 2022.1.1 for Linux:

openjdk version "11.0.15" 2022-04-19
OpenJDK Runtime Environment (build 11.0.15+0-b2043.56-8887301)
OpenJDK 64-Bit Server VM (build 11.0.15+0-b2043.56-8887301, mixed mode)
Gradle 7.1.2

I have two questions:

  1. Is the file EventBusIndex.class the Subscriber Index? If so: I generated the Subscriber Index once (like suggested on your web page) and then I commented that line (https://github.com/BasicAirData/GPSLogger/blob/966a9a8841cd7df4bb515a722eee54c94a7b48ae/app/src/main/java/eu/basicairdata/graziano/gpslogger/GPSApplication.java#LL1033C20-L1033C20). Why the build process creates a new Subscriber Index every time I compile the app?
  2. Is it possible to generate the EventBusIndex.class file in a deterministic way?

Thanks and regards.

Yes, you configured it to be that.

The index is re-created each time the annotation processor runs. So IIRC if Gradle detects any changes it will re-run.

As for determinism, one would have to check the annotation processor source code in this repo if it e.g. sorts things in a stable way. I don't have time right now, but maybe at some point.

Ok, thanks for the answer.
As information: I made a second test using only 1 processor (as suggested here: https://f-droid.org/docs/Reproducible_Builds/#potential-sources-of-unreproducible-builds) by disabling in my system all my processors except 1, and I still have differences in Indexes.

I hope in the future someone of your team will have the time to deepen this topic.
Thanks and bye!

obfusk commented

I'm guessing the issue is that writeIndexLines() should not iterate over a HashMap in undefined order like now

for (TypeElement subscriberTypeElement : methodsByClass.keySet()) {
    ...
}

but should probably use something like

List<TypeElement> keys = new ArrayList<>(methodsByClass.keySet());
keys.sort((o1, o2) -> o1.getQualifiedName().compareTo(o2.getQualifiedName()));
for (TypeElement subscriberTypeElement : keys) {
    ...
}

For your information:
Basing on a suggestion of the F-Droid team (https://gitlab.com/fdroid/fdroiddata/-/merge_requests/12975) I tried to apply an ugly python patch that orders the items in EventBusIndex.java, and the patch fixed the reproducibility issue. Thus @obfusk is right: it is only a sorting problem.

Here you can find the commit: BasicAirData/GPSLogger@3bfee78

@greenrobot-team do you have in plan to check the annotation processor source code and to fix soon the sorting problem?

I kindly ask it because I can use the sorting python patch mentioned above to test the reproducibility with method sorting, but I cannot use it to make the signed APK, due to the new lint checks on Gradle 8.
Depending on your plan I should decide to work on or to postpone the publication of the app on the F-Droid store.

Thanks in advance.

@GrazianoCapelli There likely won't be a release anytime soon as I'm busy with other stuff.