### @configure_input@ # Copyright (C) 2023-2024 Free Software Foundation, Inc. # This file is part of GNU Emacs. # GNU Emacs is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # GNU Emacs is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with GNU Emacs. If not, see . top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ srcdir = @srcdir@ builddir = @builddir@ version = @version@ # Don't install movemail if mailutils are to be used. emacs_use_mailutils = @emacs_use_mailutils@ # This is the host lib-src and lib, not the cross compiler's lib-src. libsrc = ../lib-src EXEEXT = @EXEEXT@ -include ${top_builddir}/src/verbose.mk SHELL = @SHELL@ JAVAC = @JAVAC@ AAPT = @AAPT@ D8 = @D8@ ZIPALIGN = @ZIPALIGN@ JARSIGNER = @JARSIGNER@ APKSIGNER = @APKSIGNER@ JARSIGNER_FLAGS = ANDROID_JAR = @ANDROID_JAR@ ANDROID_ABI = @ANDROID_ABI@ ANDROID_SDK_18_OR_EARLIER = @ANDROID_SDK_18_OR_EARLIER@ ANDROID_SDK_8_OR_EARLIER = @ANDROID_SDK_8_OR_EARLIER@ WARN_JAVAFLAGS = @WARN_JAVAFLAGS@ JAVAFLAGS = $(WARN_JAVAFLAGS) -classpath "$(ANDROID_JAR):$(srcdir)" FIND_DELETE = @FIND_DELETE@ # Android 4.3 and earlier require Emacs to be signed with a different # digital signature algorithm. ifneq (,$(ANDROID_SDK_18_OR_EARLIER)) JARSIGNER_FLAGS = -sigalg MD5withRSA -digestalg SHA1 else JARSIGNER_FLAGS = endif # When building Emacs for Android 2.2, assets must not be compressed. # Otherwise, the asset manager fails to extract files larger than 1 # MB. ifneq (,$(ANDROID_SDK_8_OR_EARLIER)) AAPT_ASSET_ARGS = -0 "" else AAPT_ASSET_ARGS = endif SIGN_EMACS = -keystore $(srcdir)/emacs.keystore -storepass \ emacs1 $(JARSIGNER_FLAGS) SIGN_EMACS_V2 = sign --v2-signing-enabled --ks \ $(srcdir)/emacs.keystore -debuggable-apk-permitted \ --ks-pass pass:emacs1 JAVA_FILES := $(wildcard $(srcdir)/org/gnu/emacs/*.java) RESOURCE_FILES := $(foreach file,$(wildcard $(srcdir)/res/*), \ $(wildcard $(file)/*)) # R.java is a file generated by the `aapt' utility containing # constants that can then be used to locate ``resource identifiers''. # It is not a regular file and should not be compiled as Java source # code. Instead, it is automatically included by the Java compiler. RESOURCE_FILE := $(srcdir)/org/gnu/emacs/R.java # EmacsConfig.java is a file that holds information regarding the set of # shared libraries this binary links to, and similar build variables. CONFIG_FILE := $(builddir)/org/gnu/emacs/EmacsConfig.java # CLASS_FILES is what should actually be built and included in the # resulting Emacs executable. The Java compiler might generate more # than one class file for each source file, so this only serves as a # list of dependencies for Make. CLASS_FILES := $(foreach file,$(JAVA_FILES),$(basename $(file)).class) # Remove RESOURCE_FILE from JAVA_FILES, if it is already present. JAVA_FILES := $(filter-out $(RESOURCE_FILE),$(JAVA_FILES)) # Compute the name for the Emacs application package. This should be: # emacs---.apk ANDROID_MIN_SDK := @ANDROID_MIN_SDK@ APK_NAME := emacs-$(version)-$(ANDROID_MIN_SDK)-$(ANDROID_ABI).apk # Whether or not the bundle is to be debuggable. ANDROID_DEBUGGABLE := @ANDROID_DEBUGGABLE@ # Whether or not $(D8) is in fact the name of the `r8' optimizer binary. IS_D8_R8 := @IS_D8_R8@ # How this stuff works. # emacs.apk depends on emacs.apk-in, which is simply a ZIP archive # containing the following files: # lib/$(ANDROID_ABI)/libemacs.so # lib/$(ANDROID_ABI)/libandroid-emacs.so # lib/$(ANDROID_ABI)/libctags.so # lib/$(ANDROID_ABI)/libetags.so # lib/$(ANDROID_ABI)/libhexl.so # lib/$(ANDROID_ABI)/libmovemail.so # lib/$(ANDROID_ABI)/librcs2log.so # lib/$(ANDROID_ABI)/libebrowse.so # assets/info/ # assets/etc/ # assets/lisp/ .PHONY: emacs.apk-in all all: $(APK_NAME) # Binaries to cross-compile. CROSS_SRC_BINS := $(top_builddir)/cross/src/android-emacs CROSS_LIBSRC_BINS := $(top_builddir)/cross/lib-src/ctags \ $(top_builddir)/cross/lib-src/hexl \ $(top_builddir)/cross/lib-src/ebrowse \ $(top_builddir)/cross/lib-src/emacsclient \ $(top_builddir)/cross/lib-src/etags CROSS_LIBSRC_BINS_MOVEMAIL := $(top_builddir)/cross/lib-src/movemail CROSS_EXEC_BINS := $(top_builddir)/exec/exec1 $(top_builddir)/exec/loader CROSS_BINS = $(CROSS_SRC_BINS) $(CROSS_LIBSRC_BINS) $(CROSS_EXEC_BINS) ifneq ($(emacs_use_mailutils),yes) CROSS_LIBSRC_BINS := $(CROSS_LIBSRC_BINS) $(CROSS_LIBSRC_BINS_MOVEMAIL) endif # Libraries to cross-compile. CROSS_LIBS = $(top_builddir)/cross/src/libemacs.so # Make sure gnulib is built first! # If not, then the recursive invocations of make below will try to # build gnulib at the same time. CROSS_ARCHIVES = $(top_builddir)/cross/lib/libgnu.a # Third party libraries to compile. -include $(top_builddir)/cross/ndk-build/ndk-build.mk .PHONY: $(CROSS_BINS) $(CROSS_LIBS) $(CROSS_ARCHIVES) # There should only be a single invocation of $(MAKE) -C # $(top_srcdir)/cross for each directory under $(top_srcdir)/cross. $(CROSS_SRC_BINS) $(CROSS_LIBS) &: $(CROSS_ARCHIVES) $(MAKE) -C $(top_builddir)/cross $(foreach file, \ $(CROSS_SRC_BINS) \ $(CROSS_LIBS), \ src/$(notdir $(file))) $(CROSS_LIBSRC_BINS) &: $(CROSS_ARCHIVES) $(MAKE) -C $(top_builddir)/cross $(foreach file, \ $(CROSS_LIBSRC_BINS), \ lib-src/$(notdir $(file))) $(CROSS_ARCHIVES): $(MAKE) -C $(top_builddir)/cross lib/libgnu.a # These two binaries are helpers used to execute binaries on Android # 10 and later. $(CROSS_EXEC_BINS) &: $(MAKE) -C $(top_builddir)/exec $(notdir $(CROSS_EXEC_BINS)) # This is needed to generate the ``.directory-tree'' file used by the # Android emulations of readdir and faccessat. $(libsrc)/asset-directory-tool: $(MAKE) -C $(libsrc) $(notdir $@) # install_tmp is a directory used to generate emacs.apk-in. # That is then packaged into $(APK_NAME). # There is no need to depend on NDK_BUILD_SHARED as libemacs.so # does already. .PHONY: install_temp install_temp/assets/directory-tree install_temp: $(CROSS_BINS) $(CROSS_LIBS) $(RESOURCE_FILES) $(AM_V_GEN) # Make the working directory for this stuff $(AM_V_SILENT) rm -rf install_temp $(AM_V_SILENT) mkdir -p install_temp/lib/$(ANDROID_ABI) $(AM_V_SILENT) mkdir -p install_temp/assets/etc $(AM_V_SILENT) mkdir -p install_temp/assets/lisp $(AM_V_SILENT) mkdir -p install_temp/assets/info # Install architecture independents to assets/etc and assets/lisp $(AM_V_SILENT) cp -r $(top_srcdir)/lisp install_temp/assets $(AM_V_SILENT) cp -r $(top_srcdir)/etc install_temp/assets $(AM_V_SILENT) cp -r $(top_srcdir)/info install_temp/assets # Replace etc/DOC generated by compiling Emacs for the build machine # with etc/DOC from the cross-compiled Emacs. $(AM_V_SILENT) test -f $(top_builddir)/cross/etc/DOC \ && cp -r $(top_builddir)/cross/etc/DOC \ install_temp/assets/etc # Remove undesirable files from those directories. $(AM_V_SILENT) \ for subdir in `find install_temp -type d -print`; do \ chmod a+rx $${subdir} ; \ rm -rf $${subdir}/.gitignore ; \ rm -rf $${subdir}/.DS_Store ; \ rm -rf $${subdir}/#* ; \ rm -rf $${subdir}/.#* ; \ rm -rf $${subdir}/*~ ; \ rm -rf $${subdir}/*.orig ; \ rm -rf $${subdir}/ChangeLog* ; \ rm -rf $${subdir}/[mM]akefile*[.-]in ; \ rm -rf $${subdir}/Makefile; \ done # Generate the directory tree for those directories. # Install architecture dependents to lib/$(ANDROID_ABI). This # perculiar naming scheme is required to make Android preserve these # binaries upon installation. $(AM_V_SILENT) \ for file in $(CROSS_BINS); do \ if [ -x $$file ]; then \ filename=`basename $$file`; \ cp -f $$file install_temp/lib/$(ANDROID_ABI)/lib$${filename}.so; \ fi \ done $(AM_V_SILENT) \ for file in $(CROSS_LIBS); do \ if [ -x $$file ]; then \ cp -f $$file install_temp/lib/$(ANDROID_ABI); \ fi \ done # Next, produce a version of rcs2log befitting Android's naming # conventions and shell interpreter location. $(AM_V_at) \ sed 's|/bin/sh|/system/bin/sh|' \ $(top_srcdir)/lib-src/rcs2log > \ install_temp/lib/$(ANDROID_ABI)/librcs2log.so $(AM_V_at) chmod +x install_temp/lib/$(ANDROID_ABI)/librcs2log.so ifneq ($(NDK_BUILD_SHARED),) $(AM_V_SILENT) cp -f $(NDK_BUILD_SHARED) \ install_temp/lib/$(ANDROID_ABI) endif install_temp/assets/directory-tree: $(libsrc)/asset-directory-tool \ install_temp install_temp/assets/version \ install_temp/assets/build_info $(AM_V_GEN) $(libsrc)/asset-directory-tool install_temp/assets \ install_temp/assets/directory-tree install_temp/assets/version: install_temp $(AM_V_GEN) { (cd $(top_srcdir) \ && git rev-parse HEAD || echo "Unknown") \ && (git rev-parse --abbrev-ref HEAD \ || echo "Unknown") } 2> /dev/null > $@ install_temp/assets/build_info: install_temp $(AM_V_GEN) { hostname; date +%s; } > $@ emacs.apk-in: install_temp install_temp/assets/directory-tree \ AndroidManifest.xml install_temp/assets/version \ install_temp/assets/build_info classes.dex # Package everything. Redirect the generated R.java to install_temp, as # it must already have been generated as a prerequisite of # classes.dex's. $(AM_V_AAPT) $(AAPT) p -I "$(ANDROID_JAR)" -F $@ \ -f -M AndroidManifest.xml $(AAPT_ASSET_ARGS) \ -A install_temp/assets \ -S $(top_srcdir)/java/res -J install_temp $(AM_V_SILENT) $(AAPT) a $@ classes.dex $(AM_V_SILENT) pushd install_temp &> /dev/null; \ $(AAPT) add ../$@ `find lib -type f`; \ popd &> /dev/null $(AM_V_SILENT) rm -rf install_temp # Makefile itself. .PRECIOUS: $(top_builddir)/config.status Makefile $(top_builddir)/config.status: $(top_srcdir)/configure.ac $(top_srcdir)/m4/*.m4 $(MAKE) -C $(dir $@) $(notdir $@) Makefile: $(top_builddir)/config.status $(top_srcdir)/java/Makefile.in $(MAKE) -C .. java/$@ # AndroidManifest.xml: AndroidManifest.xml: $(top_srcdir)/configure.ac $(top_srcdir)/m4/*.m4 \ $(srcdir)/AndroidManifest.xml.in pushd ..; ./config.status java/AndroidManifest.xml; popd # R.java: $(RESOURCE_FILE): $(RESOURCE_FILES) $(AM_V_GEN) $(AAPT) p -I "$(ANDROID_JAR)" -f \ -J $(dir $@) -M AndroidManifest.xml \ -S $(top_srcdir)/java/res # Generate a list of libemacs's dependencies with each item ordered # before its dependents for the startup process to load in advance, as # older versions of the dynamic linker do not consider these libraries # when resolving its imports. The several following statements are # executed from a recursive `make' run after shared libraries are # generated. ALL_DEPENDENCIES := ifneq (,$(filter cf-stamp-1,$(MAKECMDGOALS))) # Don't be sidetracked by dependencies of shared libraries outside the # ndk-build directory. define get-dependencies $(foreach x, \ $(and $(wildcard $(top_builddir)/cross/ndk-build/$1.so), \ $(shell $(NDK_BUILD_READELF) -d \ $(wildcard $(top_builddir)/cross/ndk-build/$1.so) \ | sed -n 's/.*(NEEDED).*\[\(.*\.so\)\].*/\1/p')), \ $(basename $(notdir $(x)))) endef #get-dependencies define resolve-one-dependency $(foreach dependency,$(call get-dependencies,$1),\ $(if $(findstring "$(dependency)",$(ALL_DEPENDENCIES)),,\ $(call resolve-one-dependency,$(basename $(notdir $(dependency)))) \ $(eval ALL_DEPENDENCIES := $(ALL_DEPENDENCIES) "$(dependency)",))) endef #resolve-one-dependency DEPENDENCIES := $(foreach file,$(NDK_BUILD_SHARED),\ $(basename $(notdir $(file)))) $(foreach file,$(DEPENDENCIES),\ $(if $(findstring "$(file)",$(ALL_DEPENDENCIES)),,\ $(call resolve-one-dependency,$(file)) \ $(eval ALL_DEPENDENCIES := $(ALL_DEPENDENCIES) "$(file)",))) endif # EmacsConfig.java: ifeq (${V},1) AM_V_EMACSCONFIG = else AM_V_EMACSCONFIG = @$(info $. GEN org/gnu/emacs/EmacsConfig.java) endif .PHONY: cf-stamp-1 cf-stamp-1: $(AM_V_at) echo 'package org.gnu.emacs;\ public class EmacsConfig\ {\ /* This is a generated file. Do not edit! */\ public static final String[] EMACS_SHARED_LIBRARIES\ = {$(ALL_DEPENDENCIES)};\ }' | sed 's/\\//g' > globals.tmp $(AM_V_at) mkdir -p org/gnu/emacs $(AM_V_at) $(top_srcdir)/build-aux/move-if-change \ globals.tmp org/gnu/emacs/EmacsConfig.java # cf-stamp-1 is a phony target invoked in a second `make' instance after # all shared libraries are compiled, because the computation of # ALL_DEPENDENCIES cannot be postponed until that stage in this instance # of Make. cf-stamp: $(NDK_BUILD_SHARED) $(CROSS_LIBS) $(AM_V_EMACSCONFIG) $(MAKE) cf-stamp-1 $(AM_V_at) touch $@ $(CONFIG_FILE): cf-stamp; @true # Make all class files depend on R.java and EmacsConfig.java being # built. $(CLASS_FILES): $(RESOURCE_FILE) $(CONFIG_FILE) .SUFFIXES: .java .class $(CLASS_FILES) &: $(JAVA_FILES) $(AM_V_JAVAC) $(JAVAC) $(JAVAFLAGS) $(JAVA_FILES) $(AM_V_SILENT) touch $(CLASS_FILES) # N.B. that find must be called all over again in case javac generated # nested classes. ALL_CLASS_FILES = \ $(subst $$,\$$,$(shell find $(srcdir) -type f -name *.class)) ifneq ($(builddir),$(srcdir)) # If the build directory is distinct from the source directory, also # include generated class files located there. ALL_CLASS_FILES = $(ALL_CLASS_FILES) \ $(subst $$,\$$,$(shell find $(builddir) -type f -name *.class)) endif classes.dex: $(CLASS_FILES) $(if $(IS_D8_R8), $(srcdir)/proguard.conf) $(AM_V_D8) $(D8) --classpath $(ANDROID_JAR) \ $(ALL_CLASS_FILES) \ --output $(builddir) \ --min-api $(ANDROID_MIN_SDK) \ $(if $(filter false,$(ANDROID_DEBUGGABLE)),--release, \ --debug) \ $(if $(IS_D8_R8),--pg-conf $(srcdir)/proguard.conf) # When emacs.keystore expires, regenerate it with: # # keytool -genkey -v -keystore emacs.keystore -alias "Emacs keystore" \ # -keyalg RSA -sigalg SHA1withRSA -keysize 2048 -validity 100000 .PHONY: clean maintainer-clean $(APK_NAME): emacs.apk-in $(srcdir)/emacs.keystore $(AM_V_GEN) $(AM_V_SILENT) cp -f emacs.apk-in $@.unaligned $(AM_V_SILENT) $(JARSIGNER) $(SIGN_EMACS) $@.unaligned "Emacs keystore" $(AM_V_SILENT) $(ZIPALIGN) -f 4 $@.unaligned $@ # Signing must happen after alignment! $(AM_V_SILENT) $(APKSIGNER) $(SIGN_EMACS_V2) $@ $(AM_V_SILENT) rm -f $@.unaligned *.idsig # TAGS generation. ETAGS = $(top_builddir)/lib-src/etags $(ETAGS): FORCE $(MAKE) -C ../lib-src $(notdir $@) tagsfiles = $(JAVA_FILES) $(RESOURCE_FILE) .PHONY: tags FORCE tags: TAGS TAGS: $(ETAGS) $(tagsfiles) $(AM_V_GEN) $(ETAGS) $(tagsfiles) clean: rm -f *.apk emacs.apk-in *.dex *.unaligned *.class *.idsig \ cf-stamp $(CONFIG_FILE) rm -rf install-temp $(RESOURCE_FILE) TAGS find . -name '*.class' $(FIND_DELETE) maintainer-clean distclean bootstrap-clean: clean rm -f Makefile ndk-build.mk