Bug 1119520 - Add opt-in Gradle build mode for mobile/android. r=gps
authorNick Alexander <nalexander@mozilla.com>
Fri, 12 Feb 2016 10:06:40 -0800
changeset 284117 ff393d231e94e95c0a9e03496e94aade94b067f2
parent 284116 864a07b26d9365d8556872bb48605b9abf5c3c39
child 284118 123c802d928a9a02040cc3316988d9b59db0ea45
push id17586
push usernalexander@mozilla.com
push dateFri, 12 Feb 2016 22:50:45 +0000
treeherderfx-team@1b59dd35c8f6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgps
bugs1119520
milestone47.0a1
Bug 1119520 - Add opt-in Gradle build mode for mobile/android. r=gps Opt-in by adding --enable-gradle-mobile-android-builds. Gradle dependencies (including the Android-Gradle plugin) are assumed to be present. Local developers will fetch them from the jcentral repository. Android-specific Maven dependencies are shipped as "extras" with the Android SDK, and should be found automatically by the Android-Gradle plugin. MozReview-Commit-ID: 966XgddWgEu
configure.in
mobile/android/base/Makefile.in
mobile/android/mach_commands.py
mobile/android/moz.build
python/mozbuild/mozbuild/mozconfig.py
testing/instrumentation/Makefile.in
testing/mochitest/Makefile.in
toolkit/mozapps/installer/upload-files.mk
--- a/configure.in
+++ b/configure.in
@@ -3753,16 +3753,17 @@ MOZ_PEERCONNECTION=
 MOZ_SRTP=
 MOZ_WEBRTC_SIGNALING=
 MOZ_WEBRTC_ASSERT_ALWAYS=1
 MOZ_WEBRTC_HARDWARE_AEC_NS=
 MOZ_SCTP=
 MOZ_ANDROID_OMX=
 MOZ_MEDIA_NAVIGATOR=
 MOZ_OMX_PLUGIN=
+MOZ_BUILD_MOBILE_ANDROID_WITH_GRADLE=
 MOZ_VPX_ERROR_CONCEALMENT=
 MOZ_WEBSPEECH=1
 MOZ_WEBSPEECH_MODELS=
 MOZ_WEBSPEECH_POCKETSPHINX=
 MOZ_WEBSPEECH_TEST_BACKEND=1
 VPX_AS=
 VPX_ASFLAGS=
 VPX_AS_CONVERSION=
@@ -5361,18 +5362,36 @@ MOZ_ARG_ENABLE_BOOL(omx-plugin,
     MOZ_OMX_PLUGIN=1,
     MOZ_OMX_PLUGIN=)
 
 if test -n "$MOZ_OMX_PLUGIN"; then
     if test "$OS_TARGET" = "Android"; then
         dnl Only allow building OMX plugin on Gonk (B2G) or Android
         AC_DEFINE(MOZ_OMX_PLUGIN)
     else
-       dnl fail if we're not building on Gonk or Android
-       AC_MSG_ERROR([OMX media plugin can only be built on B2G or Android])
+        dnl fail if we're not building on Gonk or Android
+        AC_MSG_ERROR([OMX media plugin can only be built on B2G or Android])
+    fi
+fi
+
+dnl ========================================================
+dnl = Enable building mobile/android with Gradle
+dnl ========================================================
+MOZ_ARG_ENABLE_BOOL(gradle-mobile-android-builds,
+[  --enable-gradle-mobile-android-builds      Enable building mobile/android with Gradle],
+    MOZ_BUILD_MOBILE_ANDROID_WITH_GRADLE=1,
+    MOZ_BUILD_MOBILE_ANDROID_WITH_GRADLE=)
+
+if test -n "$MOZ_BUILD_MOBILE_ANDROID_WITH_GRADLE"; then
+    if test "$OS_TARGET" = "Android" -a x"$MOZ_WIDGET_TOOLKIT" != x"gonk"; then
+        dnl Only allow building mobile/android with Gradle.
+        AC_DEFINE(MOZ_BUILD_MOBILE_ANDROID_WITH_GRADLE)
+    else
+        dnl fail if we're not building mobile/android.
+        AC_MSG_ERROR([Can only build mobile/android with Gradle])
     fi
 fi
 
 dnl system libvpx Support
 dnl ========================================================
 MOZ_ARG_WITH_BOOL(system-libvpx,
 [  --with-system-libvpx    Use system libvpx (located with pkgconfig)],
     MOZ_NATIVE_LIBVPX=1)
@@ -8895,16 +8914,17 @@ AC_SUBST(MOZ_FFVPX)
 AC_SUBST(FFVPX_AS)
 AC_SUBST_LIST(FFVPX_ASFLAGS)
 AC_SUBST(MOZ_FMP4)
 AC_SUBST(MOZ_EME)
 AC_SUBST(MOZ_DIRECTSHOW)
 AC_SUBST(MOZ_ANDROID_OMX)
 AC_SUBST(MOZ_APPLEMEDIA)
 AC_SUBST(MOZ_OMX_PLUGIN)
+AC_SUBST(MOZ_BUILD_MOBILE_ANDROID_WITH_GRADLE)
 AC_SUBST(MOZ_VPX_ERROR_CONCEALMENT)
 AC_SUBST(VPX_AS)
 AC_SUBST_LIST(VPX_ASFLAGS)
 AC_SUBST(VPX_AS_CONVERSION)
 AC_SUBST(VPX_ASM_SUFFIX)
 AC_SUBST(VPX_X86_ASM)
 AC_SUBST(VPX_ARM_ASM)
 AC_SUBST(VPX_NEED_OBJ_INT_EXTRACT)
--- a/mobile/android/base/Makefile.in
+++ b/mobile/android/base/Makefile.in
@@ -1,12 +1,18 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
+# We call mach -> Make -> gradle -> mach, which races to find and
+# create .mozconfig files and to generate targets.
+ifdef MOZ_BUILD_MOBILE_ANDROID_WITH_GRADLE
+.NOTPARALLEL:
+endif
+
 MOZ_BUILDID := $(shell awk '{print $$3}' $(DEPTH)/buildid.h)
 
 # Set the appropriate version code, based on the existance of the
 # MOZ_APP_ANDROID_VERSION_CODE variable.
 ifdef MOZ_APP_ANDROID_VERSION_CODE
     ANDROID_VERSION_CODE:=$(MOZ_APP_ANDROID_VERSION_CODE)
 else
     ANDROID_VERSION_CODE:=$(shell $(PYTHON) \
@@ -196,19 +202,33 @@ library_jars := \
 # See https://bugzilla.mozilla.org/show_bug.cgi?id=1233238#c19 for symptoms and
 # more discussion.
 ifdef MOZ_INSTALL_TRACKING
 library_jars += $(ANDROID_SDK)/optional/org.apache.http.legacy.jar
 endif # MOZ_INSTALL_TRACKING
 
 library_jars := $(subst $(NULL) ,:,$(strip $(library_jars)))
 
+gradle_dir := $(topobjdir)/gradle/build/mobile/android
+
+ifdef MOZ_BUILD_MOBILE_ANDROID_WITH_GRADLE
+.gradle.deps: .aapt.deps FORCE
+	@$(TOUCH) $@
+	$(topsrcdir)/mach gradle \
+		$(if $(MOZILLA_OFFICIAL),--no-daemon --offline --info) \
+		app:assembleAutomationDebug app:assembleAutomationDebugAndroidTest -x lint
+
+classes.dex: .gradle.deps
+	$(REPORT_BUILD)
+	cp $(gradle_dir)/app/intermediates/transforms/dex/automation/debug/folders/1000/1f/main/classes.dex $@
+else
 classes.dex: .proguard.deps
 	$(REPORT_BUILD)
 	$(DX) --dex --output=classes.dex jars-proguarded
+endif
 
 ifdef MOZ_DISABLE_PROGUARD
   PROGUARD_PASSES=0
 else
   ifdef MOZ_DEBUG
     PROGUARD_PASSES=1
   else
     ifndef MOZILLA_OFFICIAL
@@ -496,18 +516,23 @@ endef
 # packaging.  It doesn't write the normal ap_, or R.java, since we
 # don't want the packaging step to write anything that would make a
 # further no-op build do work.  See also
 # toolkit/mozapps/installer/packager.mk.
 
 # .aapt.deps: $(all_resources)
 $(eval $(call aapt_command,.aapt.deps,$(all_resources),gecko.ap_,generated/,./))
 
-# .aapt.nodeps: $(abspath $(CURDIR)/AndroidManifest.xml) FORCE
-$(eval $(call aapt_command,.aapt.nodeps,$(abspath $(CURDIR)/AndroidManifest.xml) FORCE,gecko-nodeps.ap_,gecko-nodeps/,gecko-nodeps/))
+ifdef MOZ_BUILD_MOBILE_ANDROID_WITH_GRADLE
+.aapt.nodeps: FORCE
+	cp $(gradle_dir)/app/intermediates/res/resources-automation-debug.ap_ gecko-nodeps.ap_
+else
+# .aapt.nodeps: $(CURDIR)/AndroidManifest.xml FORCE
+$(eval $(call aapt_command,.aapt.nodeps,$(CURDIR)/AndroidManifest.xml FORCE,gecko-nodeps.ap_,gecko-nodeps/,gecko-nodeps/))
+endif
 
 # Override the Java settings with some specific android settings
 include $(topsrcdir)/config/android-common.mk
 
 update-generated-wrappers:
 	@cp $(CURDIR)/jni-stubs.inc $(topsrcdir)/mozglue/android
 	@cp $(CURDIR)/GeneratedJNIWrappers.cpp $(CURDIR)/GeneratedJNIWrappers.h $(CURDIR)/GeneratedJNINatives.h $(topsrcdir)/widget/android
 	@echo Updated generated JNI code
@@ -527,34 +552,47 @@ update-generated-wrappers:
 	rsync --update $(DIST)/fennec/$(notdir $(OMNIJAR_NAME)) $@
 	$(RM) $(DIST)/fennec/$(notdir $(OMNIJAR_NAME))
 
 # Targets built very early during a Gradle build.
 gradle-targets: $(foreach f,$(constants_PP_JAVAFILES),$(f))
 gradle-targets: $(abspath AndroidManifest.xml)
 gradle-targets: $(ANDROID_GENERATED_RESFILES)
 
-gradle-omnijar: $(ABS_DIST)/fennec/$(OMNIJAR_NAME)
+ifndef MOZILLA_OFFICIAL
+# Local developers update omni.ja during their builds.  There's a
+# chicken-and-egg problem here.
+gradle-omnijar: $(abspath $(DIST)/fennec/$(OMNIJAR_NAME))
+else
+# In automation, omni.ja is built only during packaging.
+gradle-omnijar:
+endif
 
 .PHONY: gradle-targets gradle-omnijar
 
 ifndef MOZ_DISABLE_GECKOVIEW
 libs:: geckoview_resources.zip
 	$(INSTALL) geckoview_resources.zip $(FINAL_TARGET)
 endif
 
 # GeneratedJNIWrappers.cpp target also generates
 # GeneratedJNIWrappers.h and GeneratedJNINatives.h
-libs:: classes.dex jni-stubs.inc GeneratedJNIWrappers.cpp $(CURDIR)/fennec_ids.txt
-	$(INSTALL) classes.dex $(FINAL_TARGET)
+ifndef MOZ_BUILD_MOBILE_ANDROID_WITH_GRADLE
+libs:: jni-stubs.inc GeneratedJNIWrappers.cpp
 	@(diff jni-stubs.inc $(topsrcdir)/mozglue/android/jni-stubs.inc >/dev/null && \
 	  diff GeneratedJNIWrappers.cpp $(topsrcdir)/widget/android/GeneratedJNIWrappers.cpp >/dev/null && \
 	  diff GeneratedJNIWrappers.h $(topsrcdir)/widget/android/GeneratedJNIWrappers.h >/dev/null && \
 	  diff GeneratedJNINatives.h $(topsrcdir)/widget/android/GeneratedJNINatives.h >/dev/null) || \
 	 (echo '*****************************************************' && \
 	  echo '***   Error: The generated JNI code has changed   ***' && \
 	  echo '* To update generated code in the tree, please run  *' && \
 	  echo && \
 	  echo '  make -C $(CURDIR) update-generated-wrappers' && \
 	  echo && \
 	  echo '* Repeat the build, and check in any changes.       *' && \
 	  echo '*****************************************************' && \
 	  exit 1)
+endif
+
+libs:: $(CURDIR)/fennec_ids.txt
+
+libs:: classes.dex
+	$(INSTALL) classes.dex $(FINAL_TARGET)
--- a/mobile/android/mach_commands.py
+++ b/mobile/android/mach_commands.py
@@ -16,26 +16,16 @@ from mozbuild.base import (
 )
 
 from mach.decorators import (
     CommandArgument,
     CommandProvider,
     Command,
 )
 
-SUCCESS = '''
-You should be ready to build with Gradle and import into IntelliJ!  Test with
-
-    ./mach gradle build
-
-and in IntelliJ select File > Import project... and choose
-
-    {topobjdir}/mobile/android/gradle
-'''
-
 
 # NOTE python/mach/mach/commands/commandinfo.py references this function
 #      by name. If this function is renamed or removed, that file should
 #      be updated accordingly as well.
 def REMOVED(cls):
     """Command no longer exists! Use the Gradle configuration rooted in the top source directory instead.
 
     See https://developer.mozilla.org/en-US/docs/Simple_Firefox_for_Android_build#Developing_Firefox_for_Android_in_Android_Studio_or_IDEA_IntelliJ.
--- a/mobile/android/moz.build
+++ b/mobile/android/moz.build
@@ -24,13 +24,14 @@ DIRS += [
     'app',
     'fonts',
     'geckoview_library',
 ]
 
 if CONFIG['MOZ_ANDROID_PACKAGE_INSTALL_BOUNCER']:
     DIRS += ['bouncer'] # No ordering implied with respect to base.
 
-TEST_DIRS += [
-    'tests',
-]
+if not CONFIG['MOZ_BUILD_MOBILE_ANDROID_WITH_GRADLE']:
+    TEST_DIRS += [
+        'tests',
+    ]
 
 SPHINX_TREES['fennec'] = 'docs'
--- a/python/mozbuild/mozbuild/mozconfig.py
+++ b/python/mozbuild/mozbuild/mozconfig.py
@@ -102,17 +102,17 @@ class MozconfigLoader(ProcessExecutionMi
         MozconfigFindException will be raised if there is a bad state,
         including conditions from #3 above.
         """
         # Check for legacy methods first.
 
         if 'MOZ_MYCONFIG' in env:
             raise MozconfigFindException(MOZ_MYCONFIG_ERROR)
 
-        env_path = env.get('MOZCONFIG', None)
+        env_path = env.get('MOZCONFIG', None) or None
         if env_path is not None:
             if not os.path.isabs(env_path):
                 potential_roots = [self.topsrcdir, os.getcwd()]
                 # Attempt to eliminate duplicates for e.g.
                 # self.topsrcdir == os.curdir.
                 potential_roots = set(os.path.abspath(p) for p in potential_roots)
                 existing = [root for root in potential_roots
                             if os.path.exists(os.path.join(root, env_path))]
--- a/testing/instrumentation/Makefile.in
+++ b/testing/instrumentation/Makefile.in
@@ -9,15 +9,17 @@ include $(topsrcdir)/config/rules.mk
 
 # Fennec and all instrumentation tests need to be signed with the same
 # key, which means release signing them all.
 
 include $(topsrcdir)/config/android-common.mk
 
 stage-package:
 	$(NSINSTALL) -D $(_DEST_DIR)
+ifndef MOZ_BUILD_MOBILE_ANDROID_WITH_GRADLE
 	$(call RELEASE_SIGN_ANDROID_APK,\
 		$(DEPTH)/mobile/android/tests/background/junit3/background-junit3-debug-unsigned-unaligned.apk,\
 		$(_DEST_DIR)/background-junit3.apk)
 	$(call RELEASE_SIGN_ANDROID_APK,\
 		$(DEPTH)/mobile/android/tests/browser/junit3/browser-junit3-debug-unsigned-unaligned.apk,\
 		$(_DEST_DIR)/browser-junit3.apk)
+endif
 	@(cd $(DEPTH)/_tests/ && tar $(TAR_CREATE_FLAGS) - instrumentation) | (cd $(PKG_STAGE) && tar -xf -)
--- a/testing/mochitest/Makefile.in
+++ b/testing/mochitest/Makefile.in
@@ -102,21 +102,25 @@ GMP_TEST_PLUGIN_DIRS := \
 
 $(_DEST_DIR):
 	$(NSINSTALL) -D $@
 
 # On Android only, include a release signed Robocop APK in the test package.
 ifeq ($(MOZ_BUILD_APP),mobile/android)
 include $(topsrcdir)/config/android-common.mk
 
+ifndef MOZ_BUILD_MOBILE_ANDROID_WITH_GRADLE
+robocop_apk := $(topobjdir)/mobile/android/tests/browser/robocop/robocop-debug-unsigned-unaligned.apk
+else
+robocop_apk := $(topobjdir)/gradle/build/mobile/android/app/outputs/apk/app-automation-debug-androidTest-unaligned.apk
+endif
+
 stage-package-android:
 	$(NSINSTALL) -D $(_DEST_DIR)
-	$(call RELEASE_SIGN_ANDROID_APK,\
-		$(DEPTH)/mobile/android/tests/browser/robocop/robocop-debug-unsigned-unaligned.apk,\
-		$(_DEST_DIR)/robocop.apk)
+	$(call RELEASE_SIGN_ANDROID_APK,$(robocop_apk),$(_DEST_DIR)/robocop.apk)
 
 stage-package: stage-package-android
 endif
 
 stage-package:
 	$(NSINSTALL) -D $(PKG_STAGE)/mochitest && $(NSINSTALL) -D $(PKG_STAGE)/bin/plugins && $(NSINSTALL) -D $(DIST)/plugins
 	cp $(DEPTH)/mozinfo.json $(PKG_STAGE)/mochitest
 	@cp $(DEPTH)/mozinfo.json $(PKG_STAGE)/mochitest
--- a/toolkit/mozapps/installer/upload-files.mk
+++ b/toolkit/mozapps/installer/upload-files.mk
@@ -320,23 +320,28 @@ ifeq ($(MOZ_BUILD_APP),mobile/android)
 UPLOAD_EXTRA_FILES += robocop.apk
 UPLOAD_EXTRA_FILES += fennec_ids.txt
 UPLOAD_EXTRA_FILES += geckoview_library/geckoview_library.zip
 UPLOAD_EXTRA_FILES += geckoview_library/geckoview_assets.zip
 
 # Robocop/Robotium tests, Android Background tests, and Fennec need to
 # be signed with the same key, which means release signing them all.
 
-ROBOCOP_PATH = $(topobjdir)/mobile/android/tests/browser/robocop
+ifndef MOZ_BUILD_MOBILE_ANDROID_WITH_GRADLE
+robocop_apk := $(topobjdir)/mobile/android/tests/browser/robocop/robocop-debug-unsigned-unaligned.apk
+else
+robocop_apk := $(topobjdir)/gradle/build/mobile/android/app/outputs/apk/app-automation-debug-androidTest-unaligned.apk
+endif
+
 # Normally, $(NSINSTALL) would be used instead of cp, but INNER_ROBOCOP_PACKAGE
 # is used in a series of commands that run under a "cd something", while
 # $(NSINSTALL) is relative.
 INNER_ROBOCOP_PACKAGE= \
   cp $(GECKO_APP_AP_PATH)/fennec_ids.txt $(ABS_DIST) && \
-  $(call RELEASE_SIGN_ANDROID_APK,$(ROBOCOP_PATH)/robocop-debug-unsigned-unaligned.apk,$(ABS_DIST)/robocop.apk)
+  $(call RELEASE_SIGN_ANDROID_APK,$(robocop_apk),$(ABS_DIST)/robocop.apk)
 endif
 else
 INNER_ROBOCOP_PACKAGE=echo 'Testing is disabled - No Android Robocop for you'
 endif
 
 ifdef MOZ_ANDROID_PACKAGE_INSTALL_BOUNCER
 UPLOAD_EXTRA_FILES += bouncer.apk
 
@@ -465,16 +470,25 @@ OMNIJAR_NAME := $(notdir $(OMNIJAR_NAME)
 # and the res/ directory is taken from the ap_ as part of the regular
 # packaging.
 
 PKG_SUFFIX = .apk
 
 INNER_SZIP_LIBRARIES = \
   $(if $(ALREADY_SZIPPED),,$(foreach lib,$(SZIP_LIBRARIES),host/bin/szip $(MOZ_SZIP_FLAGS) $(STAGEPATH)$(MOZ_PKG_DIR)$(_BINPATH)/$(lib) && )) true
 
+ifdef MOZ_BUILD_MOBILE_ANDROID_WITH_GRADLE
+INNER_CHECK_R_TXT=echo 'No R.txt checking for you!'
+else
+INNER_CHECK_R_TXT=\
+  ((test ! -f $(GECKO_APP_AP_PATH)/R.txt && echo "*** Warning: The R.txt that is being packaged might not agree with the R.txt that was built. This is normal during l10n repacks.") || \
+    diff $(GECKO_APP_AP_PATH)/R.txt $(GECKO_APP_AP_PATH)/gecko-nodeps/R.txt >/dev/null || \
+    (echo "*** Error: The R.txt that was built and the R.txt that is being packaged are not the same. Rebuild mobile/android/base and re-package." && exit 1))
+endif
+
 # Insert $(STAGEPATH)$(MOZ_PKG_DIR)$(_BINPATH)/classes.dex into
 # $(ABS_DIST)/gecko.ap_, producing $(ABS_DIST)/gecko.apk.
 INNER_MAKE_APK = \
   ( cd $(STAGEPATH)$(MOZ_PKG_DIR)$(_BINPATH) && \
     unzip -o $(ABS_DIST)/gecko.ap_ && \
     rm $(ABS_DIST)/gecko.ap_ && \
     $(ZIP) -r9D $(ABS_DIST)/gecko.ap_ assets && \
     $(ZIP) $(if $(ALREADY_SZIPPED),-0 ,$(if $(MOZ_ENABLE_SZIP),-0 ))$(ABS_DIST)/gecko.ap_ $(ASSET_SO_LIBRARIES) && \
@@ -485,32 +499,30 @@ INNER_MAKE_APK = \
   rm -f $(ABS_DIST)/gecko.apk && \
   cp $(ABS_DIST)/gecko.ap_ $(ABS_DIST)/gecko.apk && \
   $(ZIP) -j0 $(ABS_DIST)/gecko.apk $(STAGEPATH)$(MOZ_PKG_DIR)$(_BINPATH)/classes.dex && \
   cp $(ABS_DIST)/gecko.apk $(ABS_DIST)/gecko-unsigned-unaligned.apk && \
   $(RELEASE_JARSIGNER) $(ABS_DIST)/gecko.apk && \
   $(ZIPALIGN) -f -v 4 $(ABS_DIST)/gecko.apk $(PACKAGE)
 
 ifeq ($(MOZ_BUILD_APP),mobile/android)
-INNER_MAKE_PACKAGE	= \
+INNER_MAKE_PACKAGE = \
   $(INNER_SZIP_LIBRARIES) && \
   make -C $(GECKO_APP_AP_PATH) gecko-nodeps.ap_ && \
   cp $(GECKO_APP_AP_PATH)/gecko-nodeps.ap_ $(ABS_DIST)/gecko.ap_ && \
-  ( (test ! -f $(GECKO_APP_AP_PATH)/R.txt && echo "*** Warning: The R.txt that is being packaged might not agree with the R.txt that was built. This is normal during l10n repacks.") || \
-    diff $(GECKO_APP_AP_PATH)/R.txt $(GECKO_APP_AP_PATH)/gecko-nodeps/R.txt >/dev/null || \
-    (echo "*** Error: The R.txt that was built and the R.txt that is being packaged are not the same. Rebuild mobile/android/base and re-package." && exit 1)) && \
+  $(INNER_CHECK_R_TXT) && \
   $(INNER_MAKE_APK) && \
   $(INNER_ROBOCOP_PACKAGE) && \
   $(INNER_INSTALL_BOUNCER_PACKAGE) && \
   $(INNER_MAKE_GECKOLIBS_AAR) && \
   $(INNER_MAKE_GECKOVIEW_LIBRARY)
 endif
 
 ifeq ($(MOZ_BUILD_APP),mobile/android/b2gdroid)
-INNER_MAKE_PACKAGE	= \
+INNER_MAKE_PACKAGE = \
   $(INNER_SZIP_LIBRARIES) && \
   cp $(topobjdir)/mobile/android/b2gdroid/app/classes.dex $(ABS_DIST)/classes.dex && \
   cp $(topobjdir)/mobile/android/b2gdroid/app/b2gdroid-unsigned-unaligned.apk $(ABS_DIST)/gecko.ap_ && \
   $(INNER_MAKE_APK)
 endif
 
 # Language repacks root the resources contained in assets/omni.ja
 # under assets/, but the repacks expect them to be rooted at /.