Bazel configuration files are much more structured than Gradle's, letting Bazel understand exactly what each action does. This allows for more parallelism and better reproducibility.
Could you please elaborate on that (i.e. with regards to both parallelism and reproducibility)?
I'm not a Gradle expert, so take this with a grain of salt.
Gradle a single-threaded execution in some parts (I believe it may be configuration?), because the build-rules are written in a full blown language with access to the filesystem, and internal parts of Gradle.
In Bazel, rules have to declare inputs and outputs, and this can be enforced with sandboxing. This allows to predict that two rules do not interfere with each other, so we know we can run them in parallel. Our extension language disallows direct access to the file system, and also forbids access to other sources of non-determinism, such as hash tables and the clock.
Ah, OK. BTW, while Gradle doesn't enforce it, even tasks that directly touch the filesystem may (and should) declare their inputs (that can be files or other tasks) and outputs[1] so that their freshness can be evaluated. All default tasks (like compilation), do that out of the box.
Bazel configuration files are much more structured than Gradle's, letting Bazel understand exactly what each action does. This allows for more parallelism and better reproducibility.
Could you please elaborate on that (i.e. with regards to both parallelism and reproducibility)?