In the typical android build in Gradle, every module generates and compiles
- A merged R.java file which contains the resource identifiers of all resources from the module and every other module/aar it depends on.
- A copy of all the individual merged R.java of every module/aar it depends on. This is useful as a convenience when referring to resources in code. But this also comes with a significant cost as detailed below.
In buck, the same mechanism of resource merging is supported. Goal is to eliminate the expensive computation (copying, compilation) of all the individual merged R.java of every module/aar it depends on. Here’s why Consider below dependency tree for Android Libraries L1 - L7:
L4
\
L3
/ \
L5 \
L1
L6 /
\ /
L2
/
L7
Without Union Package | With union package |
---|---|
L1 will have one R.java which will contain entries from L1 - L7 along with six other R.java for each dependents i.e L2 - L7. | L1 will have only one R.java which will contain entries from L1 - L7. |
For n libraries total number of final + intermediate R.java files would be n * log(n) | Total number of final + intermediate R.java files would be n |
For n libraries with x entries in each, total combined entries for all of R.java files would be x * n^3 | Total combined entries for all R.java is x * n * log(n) |
For example, let us assume each library in the above example had 20 resources (layouts, images etc) and they all depended on the support appcompat library which is a very common aar dependency that’s pulled in transitively. The appcompat library (v26.1.0) has 1506 resource entries. We have to compile a total of 33752 entries without Union Package and 12388 entries with union package