michael@0: # This Source Code Form is subject to the terms of the Mozilla Public michael@0: # License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: # file, You can obtain one at http://mozilla.org/MPL/2.0/. michael@0: michael@0: DIST_FILES := \ michael@0: package-name.txt.in \ michael@0: $(NULL) michael@0: michael@0: ifneq (,$(findstring -march=armv7,$(OS_CFLAGS))) michael@0: MIN_CPU_VERSION=7 michael@0: else michael@0: MIN_CPU_VERSION=5 michael@0: endif michael@0: michael@0: MOZ_APP_BUILDID=$(shell cat $(DEPTH)/config/buildid) michael@0: michael@0: ifeq (,$(ANDROID_VERSION_CODE)) michael@0: ifeq ($(CPU_ARCH),arm) michael@0: ifeq ($(MIN_CPU_VERSION),7) michael@0: ANDROID_VERSION_CODE=$(shell cat $(DEPTH)/config/buildid | cut -c1-10) michael@0: else michael@0: # See https://bugzilla.mozilla.org/show_bug.cgi?id=1042128#c11 for an explanation of this: michael@0: ANDROID_VERSION_CODE=$(shell cat $(topsrcdir)/mobile/android/config/armv6_play_store_version_code.txt) michael@0: endif michael@0: else #not arm, so x86 michael@0: # increment the version code by 1 for x86 builds so they are offered to x86 phones that have arm emulators michael@0: ANDROID_VERSION_CODE=$(shell echo $$((`cat $(DEPTH)/config/buildid | cut -c1-10` + 1))) michael@0: endif michael@0: endif michael@0: michael@0: UA_BUILDID=$(shell echo $(ANDROID_VERSION_CODE) | cut -c1-8) michael@0: michael@0: MOZ_BUILD_TIMESTAMP=$(shell echo `$(PYTHON) $(topsrcdir)/toolkit/xre/make-platformini.py --print-timestamp`) michael@0: michael@0: DEFINES += \ michael@0: -DANDROID_VERSION_CODE=$(ANDROID_VERSION_CODE) \ michael@0: -DMOZ_ANDROID_SHARED_ID="$(MOZ_ANDROID_SHARED_ID)" \ michael@0: -DMOZ_ANDROID_SHARED_ACCOUNT_TYPE="$(MOZ_ANDROID_SHARED_ACCOUNT_TYPE)" \ michael@0: -DMOZ_ANDROID_SHARED_FXACCOUNT_TYPE="$(MOZ_ANDROID_SHARED_FXACCOUNT_TYPE)" \ michael@0: -DMOZ_APP_BUILDID=$(MOZ_APP_BUILDID) \ michael@0: -DMOZ_BUILD_TIMESTAMP=$(MOZ_BUILD_TIMESTAMP) \ michael@0: -DUA_BUILDID=$(UA_BUILDID) \ michael@0: -DMOZ_DEBUG=$(MOZ_DEBUG) \ michael@0: $(NULL) michael@0: michael@0: GARBAGE += \ michael@0: AndroidManifest.xml \ michael@0: WebappManifestFragment.xml.frag \ michael@0: classes.dex \ michael@0: gecko.ap_ \ michael@0: res/values/strings.xml \ michael@0: .aapt.deps \ michael@0: fennec_ids.txt \ michael@0: javah.out \ michael@0: jni-stubs.inc \ michael@0: GeneratedJNIWrappers.cpp \ michael@0: GeneratedJNIWrappers.h \ michael@0: $(NULL) michael@0: michael@0: GARBAGE_DIRS += classes db jars res sync services generated michael@0: michael@0: JAVA_CLASSPATH = $(ANDROID_SDK)/android.jar michael@0: michael@0: ALL_JARS = \ michael@0: gecko-R.jar \ michael@0: gecko-browser.jar \ michael@0: gecko-mozglue.jar \ michael@0: gecko-util.jar \ michael@0: squareup-picasso.jar \ michael@0: sync-thirdparty.jar \ michael@0: websockets.jar \ michael@0: $(NULL) michael@0: michael@0: ifdef MOZ_WEBRTC michael@0: ALL_JARS += webrtc.jar michael@0: endif michael@0: michael@0: include $(topsrcdir)/config/config.mk michael@0: michael@0: # Note that we're going to set up a dependency directly between embed_android.dex and the java files michael@0: # Instead of on the .class files, since more than one .class file might be produced per .java file michael@0: # Sync dependencies are provided in a single jar. Sync classes themselves are delivered as source, michael@0: # because Android resource classes must be compiled together in order to avoid overlapping resource michael@0: # indices. michael@0: michael@0: classes.dex: .proguard.deps michael@0: $(REPORT_BUILD) michael@0: $(DX) --dex --output=classes.dex jars-proguarded $(ANDROID_COMPAT_LIB) michael@0: michael@0: ifdef MOZ_DISABLE_PROGUARD michael@0: PROGUARD_PASSES=0 michael@0: else michael@0: ifdef MOZ_DEBUG michael@0: PROGUARD_PASSES=1 michael@0: else michael@0: PROGUARD_PASSES=6 michael@0: endif michael@0: endif michael@0: michael@0: # We touch the target file before invoking Proguard so that Proguard's michael@0: # outputs are fresher than the target, preventing a subsequent michael@0: # invocation from thinking Proguard's outputs are stale. This is safe michael@0: # because Make removes the target file if any recipe command fails. michael@0: .proguard.deps: $(ALL_JARS) michael@0: $(REPORT_BUILD) michael@0: @$(TOUCH) $@ michael@0: java -jar $(ANDROID_SDK_ROOT)/tools/proguard/lib/proguard.jar \ michael@0: @$(topsrcdir)/mobile/android/config/proguard.cfg \ michael@0: -optimizationpasses $(PROGUARD_PASSES) \ michael@0: -injars $(subst ::,:,$(subst $(NULL) ,:,$(strip $(ALL_JARS)))) \ michael@0: -outjars jars-proguarded \ michael@0: -libraryjars $(ANDROID_SDK)/android.jar:$(ANDROID_COMPAT_LIB) michael@0: michael@0: CLASSES_WITH_JNI= \ michael@0: org.mozilla.gecko.ANRReporter \ michael@0: org.mozilla.gecko.GeckoAppShell \ michael@0: org.mozilla.gecko.GeckoJavaSampler \ michael@0: org.mozilla.gecko.gfx.NativePanZoomController \ michael@0: org.mozilla.gecko.util.NativeJSContainer \ michael@0: org.mozilla.gecko.util.NativeJSObject \ michael@0: $(NULL) michael@0: michael@0: ifdef MOZ_WEBSMS_BACKEND michael@0: # Note: if you are building with MOZ_WEBSMS_BACKEND turned on, then michael@0: # you will get a build error because the generated jni-stubs.inc will michael@0: # be different than the one checked in (i.e. it will have the sms-related michael@0: # JNI stubs as well). Just copy the generated file to mozglue/android/ michael@0: # like the error message says and rebuild. All should be well after that. michael@0: CLASSES_WITH_JNI += org.mozilla.gecko.GeckoSmsManager michael@0: endif michael@0: michael@0: jni-stubs.inc: gecko-browser.jar gecko-mozglue.jar gecko-util.jar sync-thirdparty.jar michael@0: $(JAVAH) -o javah.out -bootclasspath $(JAVA_BOOTCLASSPATH) -classpath $(subst $(NULL) $(NULL),:,$^) $(CLASSES_WITH_JNI) michael@0: $(PYTHON) $(topsrcdir)/mobile/android/base/jni-generator.py javah.out $@ michael@0: michael@0: ANNOTATION_PROCESSOR_JAR_FILES := $(DEPTH)/build/annotationProcessors/annotationProcessors.jar michael@0: michael@0: GeneratedJNIWrappers.cpp: $(ANNOTATION_PROCESSOR_JAR_FILES) michael@0: GeneratedJNIWrappers.cpp: $(ALL_JARS) michael@0: $(JAVA) -classpath gecko-mozglue.jar:$(JAVA_BOOTCLASSPATH):$(ANNOTATION_PROCESSOR_JAR_FILES) org.mozilla.gecko.annotationProcessors.AnnotationProcessor $(ALL_JARS) michael@0: michael@0: gecko_package_dir = generated/org/mozilla/gecko michael@0: # Like generated/org/mozilla/fennec_$USERID. michael@0: android_package_dir = $(addprefix generated/,$(subst .,/,$(ANDROID_PACKAGE_NAME))) michael@0: michael@0: # These _PP_JAVAFILES are specified in moz.build and defined in michael@0: # backend.mk, which is included by config.mk. Therefore this needs to michael@0: # be defined after config.mk is included. michael@0: PP_JAVAFILES := $(filter-out $(gecko_package_dir)/R.java,$(gecko-mozglue_PP_JAVAFILES) $(gecko-browser_PP_JAVAFILES)) michael@0: michael@0: manifest := \ michael@0: AndroidManifest.xml.in \ michael@0: WebappManifestFragment.xml.frag.in \ michael@0: $(NULL) michael@0: michael@0: PP_TARGETS += manifest michael@0: michael@0: # Certain source files need to be preprocessed. This special rule michael@0: # generates these files into generated/org/mozilla/gecko for michael@0: # consumption by the build system and IDEs. michael@0: michael@0: preprocessed := $(addsuffix .in,$(subst $(gecko_package_dir)/,,$(filter $(gecko_package_dir)/%,$(PP_JAVAFILES)))) michael@0: michael@0: preprocessed_PATH := $(gecko_package_dir) michael@0: preprocessed_KEEP_PATH := 1 michael@0: michael@0: PP_TARGETS += preprocessed michael@0: michael@0: # Certain source files have Java package name @ANDROID_PACKAGE_NAME@. michael@0: # We hate these files but they are necessary for backwards michael@0: # compatibility. These special rules generate these files into michael@0: # generated/org/mozilla/{firefox,firefox_beta,fennec,fennec_$USER} for michael@0: # consumption by the build system and IDEs. michael@0: michael@0: preprocessed_package := $(addsuffix .in,$(subst $(android_package_dir)/,,$(filter $(android_package_dir)/%,$(PP_JAVAFILES)))) michael@0: michael@0: preprocessed_package_PATH := $(android_package_dir) michael@0: preprocessed_package_KEEP_PATH := 1 michael@0: michael@0: PP_TARGETS += preprocessed_package michael@0: michael@0: include $(topsrcdir)/config/rules.mk michael@0: michael@0: not_android_res_files := \ michael@0: *.mkdir.done* \ michael@0: *.DS_Store* \ michael@0: *\#* \ michael@0: *.rej \ michael@0: *.orig \ michael@0: $(NULL) michael@0: michael@0: # This uses the fact that Android resource directories list all michael@0: # resource files one subdirectory below the parent resource directory. michael@0: android_res_files := $(filter-out $(not_android_res_files),$(wildcard $(addsuffix /*,$(wildcard $(addsuffix /*,$(ANDROID_RES_DIRS)))))) michael@0: michael@0: $(ANDROID_GENERATED_RESFILES): $(call mkdir_deps,$(sort $(dir $(ANDROID_GENERATED_RESFILES)))) michael@0: michael@0: # [Comment 1/3] We don't have correct dependencies for strings.xml at michael@0: # this point, so we always recursively invoke the submake to check the michael@0: # dependencies. Sigh. And, with multilocale builds, there will be michael@0: # multiple strings.xml files, and we need to rebuild gecko.ap_ if any michael@0: # of them change. But! mobile/android/base/locales does not have michael@0: # enough information to actually build res/values/strings.xml during a michael@0: # language repack. So rather than adding rules into the main michael@0: # makefile, and trying to work around the lack of information, we michael@0: # force a rebuild of gecko.ap_ during packaging. See below. michael@0: michael@0: res/values/strings.xml: FORCE michael@0: $(MAKE) -C locales michael@0: michael@0: all_resources = \ michael@0: $(CURDIR)/AndroidManifest.xml \ michael@0: $(CURDIR)/WebappManifestFragment.xml.frag \ michael@0: $(android_res_files) \ michael@0: $(ANDROID_GENERATED_RESFILES) \ michael@0: $(NULL) michael@0: michael@0: # For GeckoView, we want a zip of an Android res/ directory that michael@0: # merges the contents of all the ANDROID_RES_DIRS. The inner res/ michael@0: # directory must have the Android resource two-layer hierarchy. michael@0: michael@0: # The following helper zips files in a directory into a zip file while michael@0: # maintaining the directory structure rooted below the directory. michael@0: # (adding or creating said file as appropriate). For example, if the michael@0: # dir contains dir/subdir/file, calling with directory dir would michael@0: # create a zip containing subdir/file. Note: the trailing newline is michael@0: # necessary. michael@0: michael@0: # $(1): zip file to add to (or create). michael@0: # $(2): directory to zip contents of. michael@0: define zip_directory_with_relative_paths michael@0: cd $(2) && zip -q $(1) -r * -x $(not_android_res_files) michael@0: michael@0: endef michael@0: michael@0: geckoview_resources.zip: $(all_resources) $(GLOBAL_DEPS) michael@0: $(foreach dir,$(ANDROID_RES_DIRS),$(call zip_directory_with_relative_paths,$(CURDIR)/$@,$(dir))) michael@0: michael@0: # All of generated/org/mozilla/gecko/R.java, gecko.ap_, and R.txt are michael@0: # produced by aapt; this saves aapt invocations. The trailing michael@0: # semi-colon defines an empty recipe; defining no recipe at all causes michael@0: # Make to treat the target differently, in a way that defeats our michael@0: # dependencies. michael@0: michael@0: $(gecko_package_dir)/R.java: .aapt.deps ; michael@0: gecko.ap_: .aapt.deps ; michael@0: R.txt: .aapt.deps ; michael@0: michael@0: # [Comment 2/3] This tom-foolery provides a target that forces a michael@0: # rebuild of gecko.ap_. This is used during packaging to ensure that michael@0: # resources are fresh. The alternative would be complicated; see michael@0: # [Comment 1/3]. michael@0: michael@0: gecko-nodeps/R.java: .aapt.nodeps ; michael@0: gecko-nodeps.ap_: .aapt.nodeps ; michael@0: gecko-nodeps/R.txt: .aapt.nodeps ; michael@0: michael@0: # This ignores the default set of resources ignored by aapt, plus michael@0: # files starting with '#'. (Emacs produces temp files named #temp#.) michael@0: # This doesn't actually set the environment variable; it's used as a michael@0: # parameter in the aapt invocation below. Consider updating michael@0: # not_android_res_files as well. michael@0: michael@0: ANDROID_AAPT_IGNORE := !.svn:!.git:.*:_*:!CVS:!thumbs.db:!picasa.ini:!*.scc:*~:\#*:*.rej:*.orig michael@0: michael@0: # 1: target file. michael@0: # 2: dependencies. michael@0: # 3: name of ap_ file to write. michael@0: # 4: directory to write R.java into. michael@0: # 5: directory to write R.txt into. michael@0: # We touch the target file before invoking aapt so that aapt's outputs michael@0: # are fresher than the target, preventing a subsequent invocation from michael@0: # thinking aapt's outputs are stale. This is safe because Make michael@0: # removes the target file if any recipe command fails. michael@0: define aapt_command michael@0: $(1): $$(call mkdir_deps,$(filter-out ./,$(dir $(3) $(4) $(5)))) $(2) michael@0: @$$(TOUCH) $$@ michael@0: $$(AAPT) package -f -M AndroidManifest.xml -I $$(ANDROID_SDK)/android.jar \ michael@0: --auto-add-overlay \ michael@0: $$(addprefix -S ,$$(ANDROID_RES_DIRS)) \ michael@0: --custom-package org.mozilla.gecko --non-constant-id \ michael@0: -F $(3) \ michael@0: -J $(4) \ michael@0: --output-text-symbols $(5) \ michael@0: --ignore-assets "$$(ANDROID_AAPT_IGNORE)" michael@0: endef michael@0: michael@0: # [Comment 3/3] The first of these rules is used during regular michael@0: # builds. The second writes an ap_ file that is only used during michael@0: # packaging. It doesn't write the normal ap_, or R.java, since we michael@0: # don't want the packaging step to write anything that would make a michael@0: # further no-op build do work. See also michael@0: # toolkit/mozapps/installer/packager.mk. michael@0: michael@0: # .aapt.deps: $(all_resources) michael@0: $(eval $(call aapt_command,.aapt.deps,$(all_resources),gecko.ap_,$(gecko_package_dir)/,./)) michael@0: michael@0: # .aapt.nodeps: $(CURDIR)/AndroidManifest.xml FORCE michael@0: $(eval $(call aapt_command,.aapt.nodeps,$(CURDIR)/AndroidManifest.xml FORCE,gecko-nodeps.ap_,gecko-nodeps/,gecko-nodeps/)) michael@0: michael@0: fennec_ids.txt: $(gecko_package_dir)/R.java fennec-ids-generator.py michael@0: $(PYTHON) $(topsrcdir)/mobile/android/base/fennec-ids-generator.py -i $< -o $@ michael@0: michael@0: # Override the Java settings with some specific android settings michael@0: include $(topsrcdir)/config/android-common.mk michael@0: michael@0: libs:: geckoview_resources.zip classes.dex jni-stubs.inc GeneratedJNIWrappers.cpp fennec_ids.txt michael@0: $(INSTALL) geckoview_resources.zip $(FINAL_TARGET) michael@0: $(INSTALL) classes.dex $(FINAL_TARGET) michael@0: @(diff jni-stubs.inc $(topsrcdir)/mozglue/android/jni-stubs.inc >/dev/null && diff GeneratedJNIWrappers.cpp $(topsrcdir)/widget/android/GeneratedJNIWrappers.cpp >/dev/null) || \ michael@0: (echo '*****************************************************' && \ michael@0: echo '*** Error: The generated JNI code has changed ***' && \ michael@0: echo '* To update generated code in the tree, please run *' && \ michael@0: echo && \ michael@0: echo ' cp $(CURDIR)/jni-stubs.inc $(topsrcdir)/mozglue/android && cp $(CURDIR)/GeneratedJNIWrappers.* $(topsrcdir)/widget/android' && \ michael@0: echo && \ michael@0: echo '* Repeat the build, and check in any changes. *' && \ michael@0: echo '*****************************************************' && \ michael@0: exit 1)