Convert DexProducedFromJavaLibraryThatContainsClassFiles into an AbstractCachingBuildRule that is an AbiRule.

There are three possible scenarios when building `DexProducedFromJavaLibraryThatContainsClassFiles`:

(1) The are are no `.class` files to dex.
(2) There are `.class` files that need to be dexed to update/create the `.dex.jar` file in `buck-out`.
(3) The existing `.dex.jar` file in `buck-out` already represents the `.class` files to dex.

In order to be able to look at what is in `buck-out` before building (case 3), we either
need to get a rule key match (which works by default in Buck), or leverage the `AbiRule`
logic we already have in place for Java rules. (If we wait until we start building
`DexProducedFromJavaLibraryThatContainsClassFiles`, the `buck-out` directory containing
the old `.dex.jar` may already be deleted.)

Recall that an `AbiRule` can avoid rebuilding if the following conditions hold:
(1) The hash of the current rule definition and its input files matches the
hash on disk (written in `.metadata/METADATA_KEY_FOR_RULE_KEY_WITHOUT_DEPS`).
(2) All relevant deps that have an ABI have the same ABI as the last time the
rule was built (written in `.metadata/ABI_KEY_FOR_DEPS_ON_DISK_METADATA`).

Therefore, for an `AccumulateClassNames`, we assign it an ABI based on the
contents of the `classes.txt` file that it writes.
Because a `DexProducedFromJavaLibraryThatContainsClassFiles` has a
`AccumulateClassNames` as its only dependency, the ABI of `AccumulateClassNames`
is the ABI-key-for-deps of the `DexProducedFromJavaLibraryThatContainsClassFiles`.

Ultimately, this ensures that if a `java_library` rule is recompiled such that its
generated `.class` files are the same (this happens when a `java_library` rule is
recompiled in response to one of its deps changing in a way that does not affect
that `java_library` that depends on it, such as adding a new public method),
then the output of the `classes.txt` file for the `java_library` should be the same.
In turn, because the ABI of the `AccumulateClassNames` that generated the
`classes.txt` is unchanged, the `DexProducedFromJavaLibraryThatContainsClassFiles`
should rightfully avoid a rebuild. This optimization can have a significant impact on
incremental build times.

Test Plan: Sandcastle builds.
9 files changed
tree: 236789700199aa1712a79e5e2c13f6fbc5314668
  1. .buckconfig
  2. .classpath
  3. .gitignore
  4. .idea/
  5. .project
  6. .travis.yml
  7. DEFS
  10. bin/
  11. buck.iml
  12. build.xml
  13. config/
  14. docs/
  15. lib/
  16. plugin/
  17. pmd/
  18. scripts/
  19. src/
  20. test/
  21. testdata/
  22. third-party/


Buck is an Android build tool. To see what Buck can do for you, check out the documentation at

Build Status


To build Buck, run the following:

git clone
cd buck
./bin/buck --help


Apache License 2.0