The scenario here is an AAR file that has no resources in its res/ directory, and has no R.txt file. The AAR has a classes.jar that includes an R.class that was created as a result of what appears to be an obfuscation pass (proguard or otherwise) -- that assumption is made based on the fact that there are several other adjacent classes with single-character names: Q.class, R.class, S.class, etc. Ordinarily, if there is no R.txt, then no resources-related R.class should be generated for it (and this works correctly in a Gradle build, for example: there is no build/generated/source/r/debug/com/crashlytics/android/R.java file, because the AAR contains no R.txt).
Buck appears to be assuming that all AAR files require an R.class, even if it has an empty res/ and missing R.txt, so it ends up generating an empty R.class for that package. However, in this case, that class ends up overwriting the R class that already exists in classes.jar. That causes an error with the caching system, reporting an error due to "Multiple entries with the same key":
Multiple entries with same key: com/crashlytics/android/R=3040495ca6cb51bd19a9878a5a73ae8093cdb0fd and com/crashlytics/android/R=2dd42ddb490ce969a59fcfd0e692f3ee1accafad
Checking the buck-out/ directory shows that the entries come from two different places:
buck-out//gen/aars__crashlytics-2.0.3#aar_prebuilt_jar.classes.txt:com/crashlytics/android/R 2dd42ddb490ce969a59fcfd0e692f3ee1accafad
buck-out//bin/__app#aapt_package_rdotjava_classes__/classes.txt:com/crashlytics/android/R 3040495ca6cb51bd19a9878a5a73ae8093cdb0fd
Presumably, the one in #aar_prebuilt_jar.classes.txt is the true R.class that exists in the classes.jar of the AAR. The one in #aapt_package_rdotjava_classes__/classes.txt appears to be the automatically generated R.class as a result of the aapt resources processing.
In an effort to get past this error just to get the project to compile, I deleted the entry from the #aapt_package_ version, and that allowed it to continue to the smart_dex step. At this point I hit a GC overhead limit exceeded error (this is caused by dx not having a large enough heap size: my project requires a 3GB heap for dex to succeed). But that's a separate issue.
After adjusting the heap size in the dx shell script, the dex tool itself then hit an error with:
java.lang.IllegalArgumentException: already added: Lcom/crashlytics/android/R;
It's already added because it is still trying to add both the real (obfuscated) R.class and the generated (R.txt) R.class.
I'm not sure if this should be reported as an issue to the Crashlytics team (since having an R.class in the library's own package scope can be seen as risky and should probably be avoided). However, since all other build tools seem to work perfectly fine with this scenario, I'm going to assume that it's a bug in buck in that it generates the resources R.class for an AAR that does not want one.
An AAR that exhibits this behavior is the Crashlytics SDK (both versions 1.2.0 and 2.0.3). The URL to download the AAR from their Maven repository: crashlytics-2.0.3.aar.
The scenario here is an AAR file that has no resources in its
res/directory, and has noR.txtfile. The AAR has a classes.jar that includes anR.classthat was created as a result of what appears to be an obfuscation pass (proguard or otherwise) -- that assumption is made based on the fact that there are several other adjacent classes with single-character names:Q.class,R.class,S.class, etc. Ordinarily, if there is no R.txt, then no resources-related R.class should be generated for it (and this works correctly in a Gradle build, for example: there is nobuild/generated/source/r/debug/com/crashlytics/android/R.javafile, because the AAR contains noR.txt).Buck appears to be assuming that all AAR files require an
R.class, even if it has an emptyres/and missingR.txt, so it ends up generating an emptyR.classfor that package. However, in this case, that class ends up overwriting theRclass that already exists in classes.jar. That causes an error with the caching system, reporting an error due to "Multiple entries with the same key":Checking the
buck-out/directory shows that the entries come from two different places:Presumably, the one in
#aar_prebuilt_jar.classes.txtis the true R.class that exists in theclasses.jarof the AAR. The one in#aapt_package_rdotjava_classes__/classes.txtappears to be the automatically generated R.class as a result of the aapt resources processing.In an effort to get past this error just to get the project to compile, I deleted the entry from the
#aapt_package_version, and that allowed it to continue to thesmart_dexstep. At this point I hit aGC overhead limit exceedederror (this is caused bydxnot having a large enough heap size: my project requires a 3GB heap for dex to succeed). But that's a separate issue.After adjusting the heap size in the
dxshell script, the dex tool itself then hit an error with:It's already added because it is still trying to add both the real (obfuscated) R.class and the generated (R.txt) R.class.
I'm not sure if this should be reported as an issue to the Crashlytics team (since having an R.class in the library's own package scope can be seen as risky and should probably be avoided). However, since all other build tools seem to work perfectly fine with this scenario, I'm going to assume that it's a bug in buck in that it generates the resources R.class for an AAR that does not want one.
An AAR that exhibits this behavior is the Crashlytics SDK (both versions 1.2.0 and 2.0.3). The URL to download the AAR from their Maven repository: crashlytics-2.0.3.aar.