Bug 1169873 - Part 1: WIP on using Path instances in Java JAR declarations. draft
authorNick Alexander <nalexander@mozilla.com>
Sun, 24 Jan 2016 22:00:30 -0800
changeset 325490 5474efb046e1fc2a02693becf7c839a89693c82a
parent 324976 b4600877d959435ef43ce362b04b9546639f0be4
child 513449 e1cea4daefd6bcf105c2ef30fbaad0b4a83aa2c0
push id9980
push usernalexander@mozilla.com
push dateMon, 25 Jan 2016 17:34:30 +0000
bugs1169873
milestone46.0a1
Bug 1169873 - Part 1: WIP on using Path instances in Java JAR declarations. I'm just pushing this out to capture my thoughts. There are lots of path incompatibilities running java and javac on Windows. I think the best approach is to use @argument files with javac; that decouples the paths produced for javac from the paths that Make uses. In turn, that's much easier to achieve if we use Path instances in the recursive make backend. This patch does this for Java JAR files. To complete this approach, we need to lift some Makefile.in variables (JAVAFILES, ANDROID_EXTRA_JARS) into moz.build, so that we can modify the @argument files for classes.dex easily. That's getting into a decent amount of work, and I think it's better to put that energy into just building with Gradle.
config/makefiles/java-build.mk
mobile/android/base/Makefile.in
mobile/android/base/android-services.mozbuild
mobile/android/base/moz.build
python/mozbuild/mozbuild/backend/recursivemake.py
--- a/config/makefiles/java-build.mk
+++ b/config/makefiles/java-build.mk
@@ -108,52 +108,52 @@ GARBAGE += \
   $(NULL)
 
 # Include Android specific java flags, instead of what's in rules.mk.
 include $(topsrcdir)/config/android-common.mk
 endif #} ANDROID_APK_NAME
 
 
 ifdef JAVA_JAR_TARGETS #{
-# Arg 1: Output target name with .jar suffix, like jars/jarfile.jar.
-#        Intermediate class files are generated in jars/jarfile-classes.
+# Arg 1: Output target name without .jar suffix, like 'jarfile'.
+#        Intermediate class files are generated in jarfile-classes.
 # Arg 2: Java sources list.  We use VPATH and $^ so sources can be
 #        relative to $(srcdir) or $(CURDIR).
 # Arg 3: List of extra jars to link against.  We do not use VPATH so
 #        jars must be relative to $(CURDIR).
 # Arg 4: Additional JAVAC_FLAGS.
+# Arg 5: Full path to output target file, like '/abspath/to/jarfile.jar'.
 
 # Note: Proguard fails when stale .class files corresponding to
 # removed inner classes are present in the object directory.  These
 # stale class files get packaged into the .jar file, which then gets
 # processed by Proguard.  To work around this, we always delete any
 # existing jarfile-classes directory and start fresh.
 
 define java_jar_template
-$(1): $(2) $(3) $(default_bootclasspath_jars) $(default_classpath_jars)
+$(5): $(2) $(3) $(default_bootclasspath_jars) $(default_classpath_jars)
 	$$(REPORT_BUILD)
-	@$$(RM) -rf $(1:.jar=)-classes
-	@$$(NSINSTALL) -D $(1:.jar=)-classes
+	@$$(RM) -rf $(1)-classes
+	@$$(NSINSTALL) -D $(1)-classes
 	@$$(if $$(filter-out .,$$(@D)),$$(NSINSTALL) -D $$(@D))
 	$$(JAVAC) $$(JAVAC_FLAGS)\
 		$(4)\
-		-d $(1:.jar=)-classes\
-		$(addprefix -bootclasspath ,$(call classpath_template,$(default_bootclasspath_jars)))\
-		$(addprefix -classpath ,$(call classpath_template,$(default_classpath_jars) $(3)))\
-		$$(filter %.java,$$^)
-	$$(JAR) cMf $$@ -C $(1:.jar=)-classes .
+		-d $(1)-classes\
+		@$(1)-java-arguments
+	$$(JAR) cMf $$@ -C $(1)-classes .
 
-GARBAGE += $(1)
+GARBAGE += $(5)
 
-GARBAGE_DIRS += $(1:.jar=)-classes
+GARBAGE_DIRS += $(1)-classes
 endef
 
 $(foreach jar,$(JAVA_JAR_TARGETS),\
+  $(if $($(jar)_NAME),,$(error Missing $(jar)_NAME))\
   $(if $($(jar)_DEST),,$(error Missing $(jar)_DEST))\
   $(if $($(jar)_JAVAFILES) $($(jar)_PP_JAVAFILES),,$(error Must provide at least one of $(jar)_JAVAFILES and $(jar)_PP_JAVAFILES))\
-  $(eval $(call java_jar_template,$($(jar)_DEST),$($(jar)_JAVAFILES) $($(jar)_PP_JAVAFILES),$($(jar)_EXTRA_JARS),$($(jar)_JAVAC_FLAGS)))\
+  $(eval $(call java_jar_template,$($(jar)_NAME),$($(jar)_JAVAFILES) $($(jar)_PP_JAVAFILES),$($(jar)_EXTRA_JARS),$($(jar)_JAVAC_FLAGS),$($(jar)_DEST)))\
 )
 endif #} JAVA_JAR_TARGETS
 
 
 INCLUDED_JAVA_BUILD_MK := 1
 
 endif #} INCLUDED_JAVA_BUILD_MK
--- a/mobile/android/base/Makefile.in
+++ b/mobile/android/base/Makefile.in
@@ -143,16 +143,18 @@ endif
 ifdef MOZ_ANDROID_MLS_STUMBLER
 ALL_JARS += ../stumbler/stumbler.jar
 endif
 
 ifdef MOZ_INSTALL_TRACKING
 ALL_JARS += gecko-thirdparty-adjust_sdk.jar
 endif
 
+ALL_JARS := $(foreach jar,$(ALL_JARS),$(abspath $(CURDIR)/$(jar)))
+
 # The list of jars in Java classpath notation (colon-separated).
 all_jars_classpath := $(subst $(NULL) ,:,$(strip $(ALL_JARS)))
 
 include $(topsrcdir)/config/config.mk
 
 library_jars := \
     $(ANDROID_SDK)/android.jar \
     $(NULL)
@@ -260,17 +262,20 @@ PP_TARGETS += manifest
 # consumption by the build system and IDEs.
 
 # The list in moz.build looks like
 # 'preprocessed/org/mozilla/gecko/AppConstants.java'.  The list in
 # constants_PP_JAVAFILES looks like
 # 'generated/preprocessed/org/mozilla/gecko/AppConstants.java'.  We
 # need to write AppConstants.java.in to
 # generated/preprocessed/org/mozilla/gecko.
-preprocessed := $(addsuffix .in,$(subst generated/preprocessed/org/mozilla/gecko/,,$(filter generated/preprocessed/org/mozilla/gecko/%,$(constants_PP_JAVAFILES))))
+preprocessed := \
+  AdjustConstants.java.in \
+  AppConstants.java.in \
+  $(NULL)
 
 preprocessed_PATH := generated/preprocessed/org/mozilla/gecko
 preprocessed_KEEP_PATH := 1
 preprocessed_FLAGS := --marker='//\\\#'
 
 ifdef MOZ_INSTALL_TRACKING
 ifdef MOZ_INSTALL_TRACKING_ADJUST_SDK_APP_TOKEN
 # The value of MOZ_INSTALL_TRACKING_ADJUST_SDK_APP_TOKEN is sensitive: we don't
@@ -375,28 +380,28 @@ geckoview_resources.zip: $(all_resources
 endif
 
 # All of generated/org/mozilla/gecko/R.java, gecko.ap_, and R.txt are
 # produced by aapt; this saves aapt invocations.  The trailing
 # semi-colon defines an empty recipe; defining no recipe at all causes
 # Make to treat the target differently, in a way that defeats our
 # dependencies.
 
-generated/org/mozilla/gecko/R.java: .aapt.deps ;
+$(abspath $(CURDIR)/generated/org/mozilla/gecko/R.java): .aapt.deps ;
 
 # If native devices are enabled, add Google Play Services, build their resources
-generated/android/support/v4/R.java: .aapt.deps ;
-generated/android/support/v7/appcompat/R.java: .aapt.deps ;
-generated/android/support/design/R.java: .aapt.deps ;
-generated/android/support/v7/mediarouter/R.java: .aapt.deps ;
-generated/android/support/v7/recyclerview/R.java: .aapt.deps ;
-generated/com/google/android/gms/R.java: .aapt.deps ;
-generated/com/google/android/gms/base/R.java: .aapt.deps ;
-generated/com/google/android/gms/cast/R.java: .aapt.deps ;
-generated/com/google/android/gms/gcm/R.java: .aapt.deps ;
+$(abspath $(CURDIR)/generated/android/support/v4/R.java): .aapt.deps ;
+$(abspath $(CURDIR)/generated/android/support/v7/appcompat/R.java): .aapt.deps ;
+$(abspath $(CURDIR)/generated/android/support/design/R.java): .aapt.deps ;
+$(abspath $(CURDIR)/generated/android/support/v7/mediarouter/R.java): .aapt.deps ;
+$(abspath $(CURDIR)/generated/android/support/v7/recyclerview/R.java): .aapt.deps ;
+$(abspath $(CURDIR)/generated/com/google/android/gms/R.java): .aapt.deps ;
+$(abspath $(CURDIR)/generated/com/google/android/gms/base/R.java): .aapt.deps ;
+$(abspath $(CURDIR)/generated/com/google/android/gms/cast/R.java): .aapt.deps ;
+$(abspath $(CURDIR)/generated/com/google/android/gms/gcm/R.java): .aapt.deps ;
 
 gecko.ap_: .aapt.deps ;
 R.txt: .aapt.deps ;
 
 # [Comment 2/3] This tom-foolery provides a target that forces a
 # rebuild of gecko.ap_.  This is used during packaging to ensure that
 # resources are fresh.  The alternative would be complicated; see
 # [Comment 1/3].
--- a/mobile/android/base/android-services.mozbuild
+++ b/mobile/android/base/android-services.mozbuild
@@ -758,17 +758,17 @@ sync_thirdparty_java_files = [
     'org/mozilla/apache/commons/codec/net/RFC1522Codec.java',
     'org/mozilla/apache/commons/codec/net/URLCodec.java',
     'org/mozilla/apache/commons/codec/net/Utils.java',
     'org/mozilla/apache/commons/codec/StringDecoder.java',
     'org/mozilla/apache/commons/codec/StringEncoder.java',
     'org/mozilla/apache/commons/codec/StringEncoderComparator.java',
 ]
 
-sync_java_files = [TOPSRCDIR + '/mobile/android/services/src/main/java/org/mozilla/gecko/' + x for x in [
+sync_java_files = ['/mobile/android/services/src/main/java/org/mozilla/gecko/' + x for x in [
     'background/BackgroundService.java',
     'background/common/EditorBranch.java',
     'background/common/GlobalConstants.java',
     'background/common/log/Logger.java',
     'background/common/log/writers/AndroidLevelCachingLogWriter.java',
     'background/common/log/writers/AndroidLogWriter.java',
     'background/common/log/writers/LevelFilteringLogWriter.java',
     'background/common/log/writers/LogWriter.java',
--- a/mobile/android/base/moz.build
+++ b/mobile/android/base/moz.build
@@ -3,17 +3,17 @@
 # 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/.
 
 DIRS += ['locales']
 
 include('android-services.mozbuild')
 
-thirdparty_source_dir = TOPSRCDIR + '/mobile/android/thirdparty/'
+thirdparty_source_dir = '/mobile/android/thirdparty/'
 
 constants_jar = add_java_jar('constants')
 constants_jar.sources = ['java/org/mozilla/gecko/' + x for x in [
     'adjust/AdjustHelperInterface.java',
     'annotation/JNITarget.java',
     'annotation/ReflectionTarget.java',
     'annotation/RobocopTarget.java',
     'annotation/WebRTCJNITarget.java',
@@ -23,28 +23,28 @@ constants_jar.sources = ['java/org/mozil
     'Locales.java',
     'SysInfo.java',
 ]]
 constants_jar.generated_sources = [
     'preprocessed/org/mozilla/gecko/AdjustConstants.java',
     'preprocessed/org/mozilla/gecko/AppConstants.java',
 ]
 constants_jar.extra_jars = [
-    CONFIG['ANDROID_SUPPORT_ANNOTATIONS_JAR_LIB'],
-    CONFIG['ANDROID_SUPPORT_V4_AAR_LIB'],
-    CONFIG['ANDROID_SUPPORT_V4_AAR_INTERNAL_LIB'],
-    CONFIG['ANDROID_APPCOMPAT_V7_AAR_LIB'],
+    '%' + CONFIG['ANDROID_SUPPORT_ANNOTATIONS_JAR_LIB'],
+    '%' + CONFIG['ANDROID_SUPPORT_V4_AAR_LIB'],
+    '%' + CONFIG['ANDROID_SUPPORT_V4_AAR_INTERNAL_LIB'],
+    '%' + CONFIG['ANDROID_APPCOMPAT_V7_AAR_LIB'],
 ]
 
 if CONFIG['MOZ_INSTALL_TRACKING']:
     constants_jar.sources += ['java/org/mozilla/gecko/' + x for x in [
         'adjust/AdjustHelper.java',
     ]]
     constants_jar.extra_jars += [
-        'gecko-thirdparty-adjust_sdk.jar',
+        '!gecko-thirdparty-adjust_sdk.jar',
     ]
 else:
     constants_jar.sources += ['java/org/mozilla/gecko/' + x for x in [
         'adjust/StubAdjustHelper.java',
     ]]
 
 resjar = add_java_jar('gecko-R')
 resjar.sources = []
@@ -78,17 +78,17 @@ mgjar.sources += ['java/org/mozilla/geck
     'mozglue/DirectBufferAllocator.java',
     'mozglue/GeckoLoader.java',
     'mozglue/JNIObject.java',
     'mozglue/NativeReference.java',
     'mozglue/NativeZip.java',
 ]]
 mgjar.generated_sources = [] # Keep it this way.
 mgjar.extra_jars += [
-    'constants.jar',
+    '!constants.jar',
 ]
 mgjar.javac_flags += ['-Xlint:all']
 
 gujar = add_java_jar('gecko-util')
 gujar.sources += ['java/org/mozilla/gecko/' + x for x in [
     'util/ActivityResultHandler.java',
     'util/ActivityResultHandlerMap.java',
     'util/ActivityUtils.java',
@@ -123,68 +123,68 @@ gujar.sources += ['java/org/mozilla/geck
     'util/StringUtils.java',
     'util/ThreadUtils.java',
     'util/UIAsyncTask.java',
     'util/WeakReferenceHandler.java',
     'util/WebActivityMapper.java',
     'util/WindowUtils.java',
 ]]
 gujar.extra_jars = [
-    CONFIG['ANDROID_SUPPORT_ANNOTATIONS_JAR_LIB'],
-    CONFIG['ANDROID_SUPPORT_V4_AAR_LIB'],
-    CONFIG['ANDROID_SUPPORT_V4_AAR_INTERNAL_LIB'],
-    'constants.jar',
-    'gecko-mozglue.jar',
+    '%' + CONFIG['ANDROID_SUPPORT_ANNOTATIONS_JAR_LIB'],
+    '%' + CONFIG['ANDROID_SUPPORT_V4_AAR_LIB'],
+    '%' + CONFIG['ANDROID_SUPPORT_V4_AAR_INTERNAL_LIB'],
+    '!constants.jar',
+    '!gecko-mozglue.jar',
 ]
 gujar.javac_flags += ['-Xlint:all,-deprecation']
 
 stjar = add_java_jar('sync-thirdparty')
 stjar.sources += [ thirdparty_source_dir + f for f in sync_thirdparty_java_files ]
 stjar.javac_flags = ['-Xlint:none']
 
 services_jar = add_java_jar('services')
 services_jar.sources += sync_java_files
 services_jar.extra_jars = [
-    CONFIG['ANDROID_SUPPORT_ANNOTATIONS_JAR_LIB'],
-    CONFIG['ANDROID_SUPPORT_V4_AAR_LIB'],
-    CONFIG['ANDROID_SUPPORT_V4_AAR_INTERNAL_LIB'],
-    'constants.jar',
-    'gecko-R.jar',
-    'gecko-mozglue.jar',
-    'gecko-thirdparty.jar',
-    'gecko-util.jar',
-    'sync-thirdparty.jar',
+    '%' + CONFIG['ANDROID_SUPPORT_ANNOTATIONS_JAR_LIB'],
+    '%' + CONFIG['ANDROID_SUPPORT_V4_AAR_LIB'],
+    '%' + CONFIG['ANDROID_SUPPORT_V4_AAR_INTERNAL_LIB'],
+    '!constants.jar',
+    '!gecko-R.jar',
+    '!gecko-mozglue.jar',
+    '!gecko-thirdparty.jar',
+    '!gecko-util.jar',
+    '!sync-thirdparty.jar',
 ]
 services_jar.javac_flags += ['-Xlint:all,-deprecation']
 
 if CONFIG['MOZ_WEBRTC']:
-    video_root = TOPSRCDIR + '/media/webrtc/trunk/webrtc/modules/video_capture/android/java/src/org/webrtc/videoengine/'
-    video_render_root = TOPSRCDIR + '/media/webrtc/trunk/webrtc/modules/video_render/android/java/src/org/webrtc/videoengine/'
-    audio_root = TOPSRCDIR + '/media/webrtc/trunk/webrtc/modules/audio_device/android/java/src/org/webrtc/voiceengine/'
+    video_root = '/media/webrtc/trunk/webrtc/modules/video_capture/android/java/src/org/webrtc/videoengine/'
+    video_render_root = '/media/webrtc/trunk/webrtc/modules/video_render/android/java/src/org/webrtc/videoengine/'
+    audio_root = '/media/webrtc/trunk/webrtc/modules/audio_device/android/java/src/org/webrtc/voiceengine/'
     wrjar = add_java_jar('webrtc')
     wrjar.sources += [
         video_root + 'CaptureCapabilityAndroid.java',
         video_root + 'VideoCaptureAndroid.java',
         video_root + 'VideoCaptureDeviceInfoAndroid.java',
         video_render_root + 'ViEAndroidGLES20.java',
         video_render_root + 'ViERenderer.java',
     ]
     wrjar.sources += [
         audio_root + 'AudioManagerAndroid.java',
         audio_root + 'WebRtcAudioManager.java',
         audio_root + 'WebRtcAudioRecord.java',
         audio_root + 'WebRtcAudioTrack.java',
         audio_root + 'WebRtcAudioUtils.java',
     ]
     wrjar.extra_jars = [
-        'constants.jar',
-        'gecko-R.jar',
-        'gecko-browser.jar',
-        'gecko-util.jar',
-        'gecko-mozglue.jar',
+        '!constants.jar',
+        '!gecko-R.jar',
+        '!gecko-browser.jar',
+        '!gecko-util.jar',
+        '!gecko-mozglue.jar',
     ]
     wrjar.javac_flags += ['-Xlint:all,-deprecation,-cast']
 
 gbjar = add_java_jar('gecko-browser')
 gbjar.sources += ['java/org/mozilla/gecko/' + x for x in [
     'AboutPages.java',
     'AccountsHelper.java',
     'ActionModeCompat.java',
@@ -638,20 +638,20 @@ gbjar.sources += ['java/org/mozilla/geck
 gbjar.sources += [ thirdparty_source_dir + f for f in [
     'com/googlecode/eyesfree/braille/selfbraille/ISelfBrailleService.java',
     'com/googlecode/eyesfree/braille/selfbraille/SelfBrailleClient.java',
     'com/googlecode/eyesfree/braille/selfbraille/WriteData.java',
 ] ]
 android_package_dir = CONFIG['ANDROID_PACKAGE_NAME'].replace('.', '/')
 gbjar.generated_sources = [] # Keep it this way.
 gbjar.extra_jars += [
-    CONFIG['ANDROID_SUPPORT_ANNOTATIONS_JAR_LIB'],
-    CONFIG['ANDROID_SUPPORT_V4_AAR_LIB'],
-    CONFIG['ANDROID_SUPPORT_V4_AAR_INTERNAL_LIB'],
-    'constants.jar'
+    '%' + CONFIG['ANDROID_SUPPORT_ANNOTATIONS_JAR_LIB'],
+    '%' + CONFIG['ANDROID_SUPPORT_V4_AAR_LIB'],
+    '%' + CONFIG['ANDROID_SUPPORT_V4_AAR_INTERNAL_LIB'],
+    '!constants.jar'
 ]
 if CONFIG['MOZ_CRASHREPORTER']:
     gbjar.sources += [ 'java/org/mozilla/gecko/CrashReporter.java' ]
     ANDROID_RES_DIRS += [ 'crashreporter/res' ]
 
 if (CONFIG['MOZ_ANDROID_MAX_SDK_VERSION']):
     max_sdk_version = int(CONFIG['MOZ_ANDROID_MAX_SDK_VERSION'])
 else:
@@ -663,31 +663,31 @@ if max_sdk_version >= 11:
     gbjar.sources += ['java/org/mozilla/gecko/' + x for x in [
         'tabs/TabStrip.java',
         'tabs/TabStripAdapter.java',
         'tabs/TabStripItemView.java',
         'tabs/TabStripView.java'
     ]]
 
 gbjar.extra_jars += [
-    OBJDIR + '/../javaaddons/javaaddons-1.0.jar',
-    'gecko-R.jar',
-    'gecko-mozglue.jar',
-    'gecko-thirdparty.jar',
-    'gecko-util.jar',
-    'sync-thirdparty.jar',
-    'services.jar',
+    '!/mobile/android/javaaddons/javaaddons-1.0.jar',
+    '!gecko-R.jar',
+    '!gecko-mozglue.jar',
+    '!gecko-thirdparty.jar',
+    '!gecko-util.jar',
+    '!sync-thirdparty.jar',
+    '!services.jar',
 ]
 
 moz_native_devices_jars = [
-    CONFIG['ANDROID_MEDIAROUTER_V7_AAR_LIB'],
-    CONFIG['ANDROID_MEDIAROUTER_V7_AAR_INTERNAL_LIB'],
-    CONFIG['ANDROID_PLAY_SERVICES_BASE_AAR_LIB'],
-    CONFIG['ANDROID_PLAY_SERVICES_BASEMENT_AAR_LIB'],
-    CONFIG['ANDROID_PLAY_SERVICES_CAST_AAR_LIB'],
+    '%' + CONFIG['ANDROID_MEDIAROUTER_V7_AAR_LIB'],
+    '%' + CONFIG['ANDROID_MEDIAROUTER_V7_AAR_INTERNAL_LIB'],
+    '%' + CONFIG['ANDROID_PLAY_SERVICES_BASE_AAR_LIB'],
+    '%' + CONFIG['ANDROID_PLAY_SERVICES_BASEMENT_AAR_LIB'],
+    '%' + CONFIG['ANDROID_PLAY_SERVICES_CAST_AAR_LIB'],
 ]
 moz_native_devices_sources = ['java/org/mozilla/gecko/' + x for x in [
     'ChromeCast.java',
     'GeckoMediaPlayer.java',
     'MediaPlayerManager.java',
     'PresentationMediaPlayerManager.java',
 ]]
 if CONFIG['MOZ_NATIVE_DEVICES']:
@@ -711,19 +711,19 @@ if CONFIG['MOZ_NATIVE_DEVICES']:
 
     if CONFIG['ANDROID_PLAY_SERVICES_CAST_AAR']:
         ANDROID_EXTRA_PACKAGES += ['com.google.android.gms.cast']
         ANDROID_EXTRA_RES_DIRS += ['%' + CONFIG['ANDROID_PLAY_SERVICES_CAST_AAR_RES']]
         resjar.generated_sources += ['com/google/android/gms/cast/R.java']
 
 if CONFIG['MOZ_ANDROID_GCM']:
     gbjar.extra_jars += [
-        CONFIG['ANDROID_PLAY_SERVICES_BASE_AAR_LIB'],
-        CONFIG['ANDROID_PLAY_SERVICES_BASEMENT_AAR_LIB'],
-        CONFIG['ANDROID_PLAY_SERVICES_GCM_AAR_LIB'],
+        '%' + CONFIG['ANDROID_PLAY_SERVICES_BASE_AAR_LIB'],
+        '%' + CONFIG['ANDROID_PLAY_SERVICES_BASEMENT_AAR_LIB'],
+        '%' + CONFIG['ANDROID_PLAY_SERVICES_GCM_AAR_LIB'],
     ]
 
     if CONFIG['ANDROID_PLAY_SERVICES_BASE_AAR']:
         ANDROID_EXTRA_PACKAGES += ['com.google.android.gms']
         ANDROID_EXTRA_RES_DIRS += ['%' + CONFIG['ANDROID_PLAY_SERVICES_BASE_AAR_RES']]
         resjar.generated_sources += ['com/google/android/gms/R.java']
 
     if CONFIG['ANDROID_PLAY_SERVICES_BASEMENT_AAR']:
@@ -731,19 +731,19 @@ if CONFIG['MOZ_ANDROID_GCM']:
         ANDROID_EXTRA_RES_DIRS += ['%' + CONFIG['ANDROID_PLAY_SERVICES_BASEMENT_AAR_RES']]
         resjar.generated_sources += ['com/google/android/gms/R.java']
 
     if CONFIG['ANDROID_PLAY_SERVICES_GCM_AAR']:
         ANDROID_EXTRA_PACKAGES += ['com.google.android.gms.gcm']
         ANDROID_EXTRA_RES_DIRS += ['%' + CONFIG['ANDROID_PLAY_SERVICES_GCM_AAR_RES']]
         resjar.generated_sources += ['com/google/android/gms/gcm/R.java']
 
-gbjar.extra_jars += [CONFIG['ANDROID_APPCOMPAT_V7_AAR_LIB']]
-gbjar.extra_jars += [CONFIG['ANDROID_DESIGN_AAR_LIB']]
-gbjar.extra_jars += [CONFIG['ANDROID_RECYCLERVIEW_V7_AAR_LIB']]
+gbjar.extra_jars += ['%' + CONFIG['ANDROID_APPCOMPAT_V7_AAR_LIB']]
+gbjar.extra_jars += ['%' + CONFIG['ANDROID_DESIGN_AAR_LIB']]
+gbjar.extra_jars += ['%' + CONFIG['ANDROID_RECYCLERVIEW_V7_AAR_LIB']]
 
 gbjar.javac_flags += ['-Xlint:all,-deprecation,-fallthrough', '-J-Xmx512m', '-J-Xms128m']
 
 # gecko-thirdparty is a good place to put small independent libraries
 gtjar = add_java_jar('gecko-thirdparty')
 gtjar.sources += [ thirdparty_source_dir + f for f in [
     'com/keepsafe/switchboard/AsyncConfigLoader.java',
     'com/keepsafe/switchboard/DeviceUuidFactory.java',
@@ -806,19 +806,19 @@ gtjar.sources += [ thirdparty_source_dir
     'com/squareup/picasso/StatsSnapshot.java',
     'com/squareup/picasso/Target.java',
     'com/squareup/picasso/TargetAction.java',
     'com/squareup/picasso/Transformation.java',
     'com/squareup/picasso/UrlConnectionDownloader.java',
     'com/squareup/picasso/Utils.java'
 ] ]
 gtjar.extra_jars = [
-    CONFIG['ANDROID_SUPPORT_ANNOTATIONS_JAR_LIB'],
-    CONFIG['ANDROID_SUPPORT_V4_AAR_LIB'],
-    CONFIG['ANDROID_SUPPORT_V4_AAR_INTERNAL_LIB'],
+    '%' + CONFIG['ANDROID_SUPPORT_ANNOTATIONS_JAR_LIB'],
+    '%' + CONFIG['ANDROID_SUPPORT_V4_AAR_LIB'],
+    '%' + CONFIG['ANDROID_SUPPORT_V4_AAR_INTERNAL_LIB'],
 ]
 
 if not CONFIG['MOZILLA_OFFICIAL']:
     gtjar.sources += [ thirdparty_source_dir + f for f in [
         'org/lucasr/dspec/DesignSpec.java',
         'org/lucasr/dspec/RawResource.java'
     ] ]
 
@@ -853,17 +853,17 @@ if CONFIG['MOZ_INSTALL_TRACKING']:
         'com/adjust/sdk/plugin/MacAddressUtil.java',
         'com/adjust/sdk/plugin/Plugin.java',
         'com/adjust/sdk/Reflection.java',
         'com/adjust/sdk/RequestHandler.java',
         'com/adjust/sdk/UnitTestActivity.java',
         'com/adjust/sdk/Util.java'
     ] ]
     adjustjar.extra_jars += [
-        'sync-thirdparty.jar',
+        '!sync-thirdparty.jar',
     ]
 
 # Putting branding earlier allows branders to override default resources.
 ANDROID_RES_DIRS += [
     '/' + CONFIG['MOZ_BRANDING_DIRECTORY'] + '/res',
     'resources',
     '/mobile/android/services/src/main/res',
     '!res',
@@ -914,27 +914,27 @@ if '-march=armv7' in CONFIG['OS_CFLAGS']
     DEFINES['MOZ_MIN_CPU_VERSION'] = 7
 else:
     DEFINES['MOZ_MIN_CPU_VERSION'] = 5
 
 if CONFIG['MOZ_ANDROID_SEARCH_ACTIVITY']:
     # The Search Activity is mostly independent of Fennec proper, but
     # it does depend on Geckoview.  Therefore, we build it as a jar
     # that depends on the Geckoview jars.
-    search_source_dir = SRCDIR + '/../search'
+    search_source_dir = '/mobile/android/search'
     include('../search/search_activity_sources.mozbuild')
 
     search_activity = add_java_jar('search-activity')
     search_activity.sources += [search_source_dir + '/' + f for f in search_activity_sources]
     search_activity.javac_flags += ['-Xlint:all']
     search_activity.extra_jars = [
-        CONFIG['ANDROID_SUPPORT_ANNOTATIONS_JAR_LIB'],
-        CONFIG['ANDROID_SUPPORT_V4_AAR_LIB'],
-        CONFIG['ANDROID_SUPPORT_V4_AAR_INTERNAL_LIB'],
-        'constants.jar',
-        'gecko-R.jar',
-        'gecko-browser.jar',
-        'gecko-mozglue.jar',
-        'gecko-thirdparty.jar',
-        'gecko-util.jar'
+        '%' + CONFIG['ANDROID_SUPPORT_ANNOTATIONS_JAR_LIB'],
+        '%' + CONFIG['ANDROID_SUPPORT_V4_AAR_LIB'],
+        '%' + CONFIG['ANDROID_SUPPORT_V4_AAR_INTERNAL_LIB'],
+        '!constants.jar',
+        '!gecko-R.jar',
+        '!gecko-browser.jar',
+        '!gecko-mozglue.jar',
+        '!gecko-thirdparty.jar',
+        '!gecko-util.jar'
     ]
 
 FINAL_TARGET_PP_FILES += ['package-name.txt.in']
--- a/python/mozbuild/mozbuild/backend/recursivemake.py
+++ b/python/mozbuild/mozbuild/backend/recursivemake.py
@@ -561,17 +561,17 @@ class RecursiveMakeBackend(CommonBackend
 
         elif isinstance(obj, ContextWrapped):
             # Process a rich build system object from the front-end
             # as-is.  Please follow precedent and handle CamelCaseData
             # in a function named _process_camel_case_data.  At some
             # point in the future, this unwrapping process may be
             # automated.
             if isinstance(obj.wrapped, JavaJarData):
-                self._process_java_jar_data(obj.wrapped, backend_file)
+                self._process_java_jar_data(obj.wrapped, backend_file, obj._context)
             elif isinstance(obj.wrapped, AndroidEclipseProjectData):
                 self._process_android_eclipse_project_data(obj.wrapped, backend_file)
             else:
                 return False
 
         elif isinstance(obj, SharedLibrary):
             self._process_shared_library(obj, backend_file)
             self._process_linked_libraries(obj, backend_file)
@@ -1105,33 +1105,43 @@ INSTALL_TARGETS += %(prefix)s
         else:
             path = d + path
         backend_file.write('LOCAL_INCLUDES += -I%s\n' % path)
 
     def _process_per_source_flag(self, per_source_flag, backend_file):
         for flag in per_source_flag.flags:
             backend_file.write('%s_FLAGS += %s\n' % (mozpath.basename(per_source_flag.file_name), flag))
 
-    def _process_java_jar_data(self, jar, backend_file):
+    def _process_java_jar_data(self, jar, backend_file, context):
         target = jar.name
         backend_file.write('JAVA_JAR_TARGETS += %s\n' % target)
-        backend_file.write('%s_DEST := %s.jar\n' % (target, jar.name))
+        backend_file.write('%s_NAME := %s\n' % (target, jar.name))
+        backend_file.write('%s_DEST := %s.jar\n' % (target, mozpath.join(backend_file.objdir, jar.name)))
         if jar.sources:
             backend_file.write('%s_JAVAFILES := %s\n' %
-                (target, ' '.join(jar.sources)))
+                (target, ' '.join(Path(context, s).full_path for s in jar.sources)))
         if jar.generated_sources:
             backend_file.write('%s_PP_JAVAFILES := %s\n' %
-                (target, ' '.join(mozpath.join('generated', f) for f in jar.generated_sources)))
+                (target, ' '.join(Path(context, mozpath.join('!generated', f)).full_path for f in jar.generated_sources)))
         if jar.extra_jars:
             backend_file.write('%s_EXTRA_JARS := %s\n' %
-                (target, ' '.join(sorted(set(jar.extra_jars)))))
+                (target, ' '.join(sorted(set(Path(context, s).full_path for s in jar.extra_jars)))))
         if jar.javac_flags:
             backend_file.write('%s_JAVAC_FLAGS := %s\n' %
                 (target, ' '.join(jar.javac_flags)))
 
+        with self._write_file(mozpath.join(backend_file.objdir, '%s-java-arguments' % target)) as f:
+            cpsep = ';' if os.name in ('nt', 'ce') else ':'
+            f.write('-classpath "' + cpsep.join(sorted(set(Path(context, s).full_path for s in jar.extra_jars))) + '"\n')
+            f.write('-bootclasspath "%s/android.jar"\n' % self.environment.substs['ANDROID_SDK'])
+            for s in jar.sources:
+                f.write('"%s"\n' % Path(context, s).full_path)
+            for s in jar.generated_sources:
+                f.write('"%s"\n' % Path(context, mozpath.join('!generated', s)).full_path)
+
     def _process_android_eclipse_project_data(self, project, backend_file):
         # We add a single target to the backend.mk corresponding to
         # the moz.build defining the Android Eclipse project. This
         # target depends on some targets to be fresh, and installs a
         # manifest generated by the Android Eclipse build backend. The
         # manifests for all projects live in $TOPOBJDIR/android_eclipse
         # and are installed into subdirectories thereof.