author Nick Alexander <>
Mon, 22 Dec 2014 19:49:04 -0800
changeset 220976 6d4ab59f9764de7a00e9a22074d909994d3cd34a
parent 217333 197ddcc3d0bccd8ae6650b9dc9c0462e746a2840
child 223518 b92fe2cbbbcd73c77ee831b80d345a66b8bb98c6
permissions -rw-r--r--
Bug 1098239 - Rewrite mobile/android Gradle integration. r=me This is a big patch, but it's essentially NPOTB. The part that is POTB is ... removing Gradle integration from the build. I've implemented |mach gradle-install| as a substitute for the build system stuff; it's just so much easier to iterate on a mach command than a and I'm landing this with self-review because this lessens the impact of the Gradle integration on the build system and because I am the only person who understands either the old or the new system. You'll need to run |mach gradle-install| at top level to configure the new Gradle integration. But |mach gradle ...| does the right thing configuration steps too. This patch rewrites most of the Gradle integration. The major changes are: * all .gradle files move into mobile/android/gradle; * all the Gradle projects live in the object directory; * mozconfig exposed to all build.gradle files; * simplification of Android configuration between build.gradle files; * support for user-specified version of build tools; * first steps towards supporting builds from the source directory; * bumps Gradle to 2.2.1; * bumps the Android-Gradle plugin to 0.14.4. This is seemingly a step backwards given that we'd prefer to ship the .idea directory in the source directory. But in fact we get closer to that; it's possible to run ./gradlew in the source directory and get a reasonable build. We'll progress with this in time. The win right now is that the projects are nested, which makes importing work better on Linux machines. Unfortunately IntelliJ 13 and 14 now have conflicting Android-Gradle plugin version requirements, so we now only support IntelliJ 14.0.2 and above.

.. -*- Mode: rst; fill-column: 80; -*-

 Building with Gradle


.. code-block:: shell

  ./mach build && ./mach package
  ./mach gradle build

The debug APK will be at

The ``$OBJDIR/mobile/android/gradle`` directory can be imported into IntelliJ as

- File > Import Project...
- [select ``$OBJDIR/mobile/android/gradle``]
- Import project from external model > Gradle
- [select Use customizable Gradle wrapper]

When prompted, do not add any files to git.  You may need to re-open the
project, or restart IntelliJ, to pick up a compiler language-level change.

Technical overview


* The Gradle build will "succeed" but crash on start up if the object directory
  has not been properly packaged.
* Changes to preprocessed source code and resources (namely, ````
  and the accompanying DTD files) may not be recognized.
* There's minimal support for editing JavaScript.
* There's no support for editing C/C++.

How the Gradle project is laid out

To the greatest extent possible, the Gradle configuration lives in the object

At the time of writing, their are three main sub-modules: *app*, *base*, and
*thirdparty*, and several smaller sub-modules.

*app* is the Fennec wrapper; it generates the **org.mozilla.fennec.R** resource
package.  *base* is the Gecko code; it generates the **org.mozilla.gecko.R**
resource package.  Together, *app* and *base* address the "two package
namespaces" that has plagued Fennec from day one.

Due to limitations in the Android Gradle plugin, all test code is shoved into
the *app* module.  (The issue is that, at the time of writing, there is no
support for test-only APKs.)  For no particular reason, the compiled C/C++
libraries are included in the *app* module; they could be included in the *base*
module.  I expect *base* to rebuilt slightly more frequently than *app*, so I'm
hoping this choice will allow for faster incremental builds.

*thirdparty* is the external code we use in Fennec; it's built as an Android
library but uses no resources.  It's separate simply to allow the build system
to cache the compiled and pre-dexed artifacts, hopefully allowing for faster
incremental builds.

Recursive make backend details

The ``mobile/android/gradle`` directory writes the following into

1) the Gradle wrapper;
2) ````;
3) symlinks to certain source and resource directories.

The Gradle wrapper is written to make it easy to build with Gradle from the
object directory.  The wrapper is `intended to be checked into version

```` is the single source of per-object directory Gradle
configuration, and provides the Gradle configuration access to
configure/ variables.

The symlinks are not necessary for the Gradle build itself, but they prevent
nested directory errors and incorrect Java package scoping when the Gradle
project is imported into IntelliJ.  Because IntelliJ treats the Gradle project
as authoritative, it's not sufficient to fix these manually in IntelliJ after
the initial import -- IntelliJ reverts to the Gradle configuration after every
build.  Since there aren't many symlinks, I've done them in the Makefile rather
than at a higher level of abstraction (like a definition, or a custom
build backend).  In future, I expect to be able to remove all such symlinks by
making our in-tree directory structures agree with what Gradle and IntelliJ

.. _intended to be checked into version control: