* .gitignore: Update with new files. Do not ignore std*.in.h.
* INSTALL.android: Explain how to build Emacs with external
dependencies.
* Makefile.in (xcompile, cross): Rename to `cross'.
(clean_dirs): Clean cross, not xcompile.
* README: Document new directories.
* build-aux/ndk-build-helper-1.mk (build_kind, NDK_SO_NAMES):
* build-aux/ndk-build-helper-2.mk (build_kind, NDK_SO_NAMES):
* build-aux/ndk-build-helper-3.mk (build_kind):
* build-aux/ndk-build-helper-4.mk:
* build-aux/ndk-build-helper.mk (NDK_BUILD_DIR, my-dir):
* build-aux/ndk-module-extract.awk: New files.
* configure.ac: Set up libgif, libwebp, and libpng for
ndk-build.
* cross/ndk-build/Makefile.in (srcdir, NDK_BUILD_ANDROID_MK):
* cross/ndk-build/ndk-build-executable.mk:
* cross/ndk-build/ndk-build-shared-library.mk (eq, objname):
* cross/ndk-build/ndk-build-static-library.mk (eq, objname):
* cross/ndk-build/ndk-build.in (NDK_BUILD_MODULES):
* cross/ndk-build/ndk-build.mk.in (NDK_BUILD_MODULES)
(NDK_BUILD_SHARED):
* cross/ndk-build/ndk-clear-vars.mk:
* cross/ndk-build/ndk-prebuilt-shared-library.mk:
* cross/ndk-build/ndk-prebuilt-static-library.mk: New files.
* doc/emacs/android.texi (Android, Android Environment):
Document clipboard support on Android.
* doc/emacs/emacs.texi (Top): Update menus.
* etc/MACHINES: Document Android.
* java/AndroidManifest.xml.in: Respect new
`--with-android-debug' option.
* java/Makefile.in (CROSS_BINS, CROSS_LIBS): Adjust for rename.
Include ndk-build.mk.:(emacs.apk-in): Depend on shared
libraries. Then, package shared libraries.
* java/org/gnu/emacs/EmacsClipboard.java (EmacsClipboard): New
class.
* java/org/gnu/emacs/EmacsFontDriver.java: Update comment to say
this is unused.
* java/org/gnu/emacs/EmacsNative.java (EmacsNative): New
function `sendExpose'.
* java/org/gnu/emacs/EmacsSdk11Clipboard.java
(EmacsSdk11Clipboard):
* java/org/gnu/emacs/EmacsSdk8Clipboard.java
(EmacsSdk8Clipboard): New classes.
* java/org/gnu/emacs/EmacsView.java (EmacsView, handleDirtyBitmap)
(onDetachedFromWindow): When window is reattached, expose the
frame.
* lib/Makefile.in (VPATH):
(ALL_CFLAGS): Adjust for rename.
* lisp/term/android-win.el (android-clipboard-exists-p)
(android-get-clipboard, android-set-clipboard)
(android-clipboard-owner-p, android-primary-selection)
(android-get-clipboard-1, android-get-primary)
(android-selection-bounds, android-encode-select-string)
(gui-backend-get-selection, gui-backend-selection-exists-p)
(gui-backend-selection-owner-p, gui-backend-set-selection): New
functions.
* m4/ndk-build.m4: New file.
* src/Makefile.in (GIF_CFLAGS, ANDROID_LDFLAGS): New variables.
(EMACS_CFLAGS): Add GIF_CFLAGS. Include
ndk-build.mk.
(libemacs.so): Depend on and link with required
libraries.
* src/android.c (android_check_compressed_file): New function.
(android_open): Work around Android platform bug.
(sendExpose): New function.
(android_readdir): Set d_type if this is a directory.
* src/androidgui.h (enum android_event_type)
(struct android_expose_event, union android_event): Add expose
events.
* src/androidselect.c (struct android_emacs_clipboard)
(android_init_emacs_clipboard, Fandroid_clipboard_owner_p)
(Fandroid_set_clipboard, Fandroid_get_clipboard)
(Fandroid_clipboard_exists_p, init_androidselect)
(syms_of_androidselect): New file.
* src/androidterm.c (handle_one_android_event): Handle
exposures.
* src/androidterm.h: Update prototypes.
* src/emacs.c (android_emacs_init): Initialize androidselect.
src/verbose.mk
# Stuff built during cross compilation
-xcompile/lib/alloca.h
-xcompile/lib/assert.h
-xcompile/lib/byteswap.h
-xcompile/lib/dirent.h
-xcompile/lib/errno.h
-xcompile/lib/execinfo.h
-xcompile/lib/fcntl.h
-xcompile/lib/getopt.h
-xcompile/lib/getopt-cdefs.h
-xcompile/lib/gmp.h
-xcompile/lib/ieee754.h
-xcompile/lib/inttypes.h
-xcompile/lib/libgnu.a
-xcompile/lib/limits.h
-xcompile/lib/malloc/*.gl.h
-xcompile/lib/signal.h
-xcompile/lib/std*.h
-xcompile/!lib/std*.in.h
-xcompile/!lib/stdio-impl.h
-xcompile/lib/string.h
-xcompile/lib/sys/
-xcompile/lib/time.h
-xcompile/lib/unistd.h
-xcompile/lib/config.h
-xcompile/lib/gnulib.mk
-xcompile/src/*
-xcompile/lib-src/*
-xcompile/sys/*
-xcompile/config.status
-xcompile/*.bak
+cross/lib/alloca.h
+cross/lib/assert.h
+cross/lib/byteswap.h
+cross/lib/dirent.h
+cross/lib/errno.h
+cross/lib/execinfo.h
+cross/lib/fcntl.h
+cross/lib/getopt.h
+cross/lib/getopt-cdefs.h
+cross/lib/gmp.h
+cross/lib/ieee754.h
+cross/lib/inttypes.h
+cross/lib/libgnu.a
+cross/lib/limits.h
+cross/lib/malloc/*.gl.h
+cross/lib/signal.h
+cross/lib/std*.h
+!cross/lib/std*.in.h
+!cross/lib/stdio-impl.h
+cross/lib/string.h
+cross/lib/sys/
+cross/lib/time.h
+cross/lib/unistd.h
+cross/lib/config.h
+cross/lib/gnulib.mk
+cross/src/*
+cross/lib-src/*
+cross/sys/*
+cross/config.status
+cross/*.bak
+
+cross/ndk-build/Makefile
+cross/ndk-build/ndk-build.mk
+cross/ndk-build/*.o
# Lisp-level sources built by 'make'.
*cus-load.el
BUILDING WITH OLD NDK VERSIONS
Building Emacs with an old version of the Android NDK requires special
-setup. This is because there is no separate C compiler binary for
+setup. This is because there is no separate C compiler binary for
each version of Android in those versions of the NDK.
Before running `configure', you must identify three variables:
run on Android 2.3 or later. It is supposed to run on Android 2.2 as
well.
+DEBUG AND RELEASE BUILDS
+
+Android makes a distinction between ``debug'' and ``release'' builds
+of applications. With ``release'' builds, the system will apply
+stronger optimizations to the application at the cost of being unable
+to debug them with the steps in etc/DEBUG.
+
+Emacs is built as a debuggable package by default, but:
+
+ ./configure --without-android-debug
+
+will create a release build of Emacs instead. This may be useful when
+running Emacs on resource constrained machines.
+
+If you are building an Emacs package for redistribution, we urge you
+to provide both debug and release versions.
+
+BUILDING WITH THIRD PARTY LIBRARIES
+
+The Android NDK does not support the usual ways of locating third
+party libraries, especially not via `pkg-config'. Instead, it uses
+its own system called `ndk-build'. The one exception to this rule is
+zlib, which is considered a part of the Android OS itself and is
+available on all devices running Android.
+
+Android also requires that each application include its own
+dependencies, as the system makes no guarantee about the existence of
+any particular library.
+
+Emacs is not built with the `ndk-build' system. Instead, it is built
+with Autoconf and Make.
+
+However, it supports building and including dependencies which use the
+similarly Make-based `ndk-build' system.
+
+To use dependencies built through `ndk-build', you must specify a list
+of directories within which Emacs will search for ``Android.mk''
+files, like so:
+
+ ./configure "--with-ndk-path=directory1 directory2"
+
+Emacs will then read the ``Android.mk'' file in each directory, and
+automatically build and use those modules.
+
+Google, Inc. has adapted many common Emacs dependencies to use the
+`ndk-build' system. Here is a non-exhaustive list of what is known to
+work:
+
+ libpng - https://android.googlesource.com/platform/external/libpng
+ libwebp - https://android.googlesource.com/platform/external/webp
+ giflib - https://android.googlesource.com/platform/external/giflib
+ (You must add LOCAL_EXPORT_CFLAGS := -I$(LOCAL_PATH) before
+ its Android.mk includes $(BUILD_STATIC_LIBRARY))
+
+We anticipate that most untested non-trivial ndk-build dependencies
+will need adjustments in Emacs to work, as the Emacs build system
+which emulates ndk-build is in an extremely early state.
+
+NDK BUILD SYSTEM IMPLEMENTATION
+
+Emacs implements ndk-build itself, because the version that comes with
+the Android NDK is not easy to use from another Makefile, and keeps
+accumulating incompatible changes.
+
+The Emacs implementation of ndk-build consists of one m4 file:
+
+ m4/ndk-build.m4
+
+four Makefiles in build-aux, run during configure:
+
+ build-aux/ndk-build-helper-1.mk
+ build-aux/ndk-build-helper-2.mk
+ build-aux/ndk-build-helper-3.mk
+ build-aux/ndk-build-helper.mk
+
+one awk script in build-awx, run during configure:
+
+ build-aux/ndk-module-extract.awk
+
+six Makefiles in cross/ndk-build,
+
+ cross/ndk-build/ndk-build-shared-library.mk
+ cross/ndk-build/ndk-build-static-library.mk
+ cross/ndk-build/ndk-build-executable.mk
+ cross/ndk-build/ndk-clear-vars.mk
+ cross/ndk-build/ndk-prebuilt-shared-library.mk
+ cross/ndk-build/ndk-prebuilt-static-library.mk
+
+and finally, two more Makefiles in cross/ndk-build, generated by
+configure:
+
+ cross/ndk-build/Makefile (generated from cross/ndk-build/Makefile.in)
+ cross/ndk-build/ndk-build.mk (generated from cross/ndk-build/ndk-build.mk.in)
+
+m4/ndk-build.m4 is a collection of macros which are used by the
+configure script to set up the ndk-build system, look for modules, add
+the appropriate options to LIBS and CFLAGS, and generate the Makefiles
+necessary to build the rest of Emacs.
+
+Immediately after determining the list of directories in which to look
+for ``Android.mk'' files, the version and type of Android system being
+built for, configure calls:
+
+ ndk_INIT([$android_abi], [$ANDROID_SDK], [cross/ndk-build])
+
+This expands to a sequence of shell script that enumerates all of the
+Android.mk files specified in "$with_ndk_path", sets up some shell
+functions used by the rest of the ndk-build code run by the configure
+script, and teaches the ndk-build system that the Makefiles to be
+generated are found in the directory "cross/ndk-build/Makefile".
+
+When configure is cross-compiling for Android, the macro
+EMACS_CHECK_MODULES will expand to the macro ndk_CHECK_MODULES,
+instead of pkg-config.m4's PKG_CHECK_MODULES. Thus, the following
+code:
+
+ EMACS_CHECK_MODULES([PNG], [libpng >= 1.0.0])
+
+will actually expand to:
+
+ ndk_CHECK_MODULES([PNG], [libpng >= 1.0.0], [HAVE_PNG=yes],
+ [HAVE_PNG=no])
+
+which in turn expands to a sequence shell script that first invokes:
+
+ make -f build-aux/ndk-build-helper.mk
+
+for each ``Android.mk'' file found by ndk_INIT, with the following
+variables given to Make:
+
+ EMACS_SRCDIR=. # the source directory (in which configure is running)
+ EMACS_ABI=$ndk_ABI # this is the $android_abi given to ndk_INIT
+ ANDROID_MAKEFILE="/opt/android/libpng/Android.mk"
+ ANDROID_MODULE_DIRECTORY="/opt/android/libpng"
+ NDK_BUILD_DIR="$ndk_DIR" # this is the directory given as to ndk_INIT
+
+build-aux/ndk-build-helper.mk will then evaluate the contents
+$(ANDROID_MAKEFILE), the ``Android.mk'' file, for the first time. The
+purpose of this evaluation is to establish a list of packages (or
+modules) provided by the ``Android.mk'' file, and the corresponding
+Makefile targets and compiler and linker flags required to build and
+link to those tagets.
+
+Before doing so, build-aux/ndk-build-helper.mk will define several
+variables and functions required by all ``Android.mk'' files. The
+most important of these are:
+
+ my-dir # the directory containing the Android.mk file.
+ BUILD_SHARED_LIBRARY # build-aux/ndk-build-helper-1.mk
+ BUILD_STATIC_LIBRARY # build-aux/ndk-build-helper-2.mk
+ BUILD_EXECUTABLE # build-aux/ndk-build-helper-3.mk
+ CLEAR_VARS # build-aux/ndk-build-helper-4.mk
+
+Then, ``Android.mk'' will include $(CLEAN_VARS) (to clear variables
+previously set), set several variables describing each module to the
+ndk-build system, and include one of $(BUILD_SHARED_LIBRARY),
+$(BUILD_STATIC_LIBRARY) and $(BUILD_EXECUTABLE).
+
+Each one of those three scripts will then read from the variables set
+by ``Android.mk'', resolve dependencies, and print out some text
+describing the module to Emacs. For example, the shared library
+module "libpng" results in the following text being printed:
+
+Building shared
+libpng
+/opt/android/libpng/png.c /opt/android/libpng/pngerror.c /opt/android/libpng/pngget.c /opt/android/libpng/pngmem.c /opt/android/libpng/pngpread.c /opt/android/libpng/pngread.c /opt/android/libpng/pngrio.c /opt/android/libpng/pngrtran.c /opt/android/libpng/pngrutil.c /opt/android/libpng/pngset.c /opt/android/libpng/pngtrans.c /opt/android/libpng/pngwio.c /opt/android/libpng/pngwrite.c /opt/android/libpng/pngwtran.c /opt/android/libpng/pngwutil.c
+-I/opt/android/libpng
+
+ -L/opt/emacs/cross/ndk-build -l:libpng_emacs.so
+libpng_emacs.so
+End
+
+The output is arranged as follows:
+
+ - The first line consists of the word ``Building'', followed by
+ either ``shared'', ``static'', or ``executable'', depending on
+ what type of module being built.
+
+ - The second line consists of the name of the module currently being
+ built.
+
+ - The third line consists of all of the source code files comprising
+ the module.
+
+ - The fourth line consists of the text that has to be added to
+ CFLAGS in order to find the includes associated with the module.
+
+ - The fifth line consists of the text that has to be added to LIBS
+ in order to link with this module and all of its dependencies.
+
+ - The sixth line consists of the Make targets (more on this later)
+ that will build the final shared object or library archive of this
+ module, along with all of its dependencies.
+
+The output from Make is given to an awk script,
+build-aux/ndk-module-extract.awk. This is responsible for parsing the
+that output and filtering out modules other than what is being built:
+
+ awk -f build-aux/ndk-module-extract.awk MODULE=libpng
+
+eventually generating this section of shell script:
+
+module_name=libpng
+module_kind=shared
+module_src="/opt/android/libpng/png.c /opt/android/libpng/pngerror.c /opt/android/libpng/pngget.c /opt/android/libpng/pngmem.c /opt/android/libpng/pngpread.c /opt/android/libpng/pngread.c /opt/android/libpng/pngrio.c /opt/android/libpng/pngrtran.c /opt/android/libpng/pngrutil.c /opt/android/libpng/pngset.c /opt/android/libpng/pngtrans.c /opt/android/libpng/pngwio.c /opt/android/libpng/pngwrite.c /opt/android/libpng/pngwtran.c /opt/android/libpng/pngwutil.c"
+module_includes="-I/opt/android/libpng"
+module_cflags=""
+module_ldflags=" -L/opt/emacs/cross/ndk-build -l:libpng_emacs.so"
+module_target="libpng_emacs.so"
+
+which is then evaluated by `configure'. Once the variable
+`module_name' is set, configure apends the remaining
+$(module_includes), $(module_cflags) and $(module_ldflags) to the
+module's CFLAGS and LIBS variables, and appends the list of Makefile
+targets specified to the variable NDK_BUILD_MODULES.
+
+Finally, immediately before generating src/Makefile.android, configure
+expands:
+
+ ndk_CONFIG_FILES
+
+to generate $ndk_DIR/Makefile and $ndk_DIR/ndk-build.mk.
+
+Now, the $ndk_DIR directory is set up to build all modules upon which
+depends, and $ndk_DIR/ndk-build.mk includes a list of files required
+to link Emacs, along with the rules to chdir into $ndk_DIR in order to
+build them.
+
+$ndk_DIR/ndk-build.mk is included by cross/src/Makefile
+(Makefile.android) and java/Makefile. It defines three different
+variables:
+
+ NDK_BUILD_MODULES the file names of all modules to be built.
+ NDK_BUILD_STATIC absolute names of all library archives
+ to be built.
+ NDK_BUILD_SHARED absolute names of all shared libraries to
+ be built.
+
+and then proceeds to define rules to build each of the modules in
+$(NDK_BUILD_MODULES).
+
+cross/src/Makefile arranges to have all dependencies of Emacs not
+already built built before linking ``libemacs.so'' with them.
+
+java/Makefile additionally arranges to have all shared object
+dependencies built before the application package is built, which is
+normally redundant because they should have already been built before
+linking ``libemacs.so''.
+
+Building the modules is performed through $ndk_DIR/Makefile, which
+contains the actual implementation of the ``ndk-build'' build system.
+First, it defines certain variables constant within the ``ndk-build''
+build system, such as the files included by ``Android.mk'' to build
+shared or static libraries, and CLEAR_VARS. The most important of
+these are:
+
+ CLEAR_VARS cross/ndk-build/ndk-clear-vars.mk
+ BUILD_EXECUTABLE cross/ndk-build/ndk-build-executable.mk
+ BUILD_SHARED_LIBRARY cross/ndk-build/ndk-build-shared-library.mk
+ BUILD_STATIC_LIBRARY cross/ndk-build/ndk-build-static-library.mk
+ PREBUILT_SHARED_LIBRARY cross/ndk-build/ndk-prebuilt-shared-library.mk
+ PREBUILT_STATIC_LIBRARY cross/ndk-build/ndk-prebuilt-static-library.mk
+
+Then, it loads each Emacs dependency's ``Android.mk'' file. For each
+module defined there, ``Android.mk'' includes $(CLEAR_VARS) to unset
+all variables specific to each module, and then includes
+$(BUILD_SHARED_LIBRARY) or $(BUILD_STATIC_LIBRARY) for each shared or
+static library module.
+
+This results in cross/ndk-build/ndk-build-shared-library.mk or
+cross/ndk-build/ndk-build-static-library being included, just like the
+Makefiles in build-aux were inside the configure script.
+
+Each one of those two scripts then defines rules to build all of the
+object files associated with the module, and then link or archive
+them. The name under which the module is linked is the same as the
+Make target found on the sixth line of output from
+build-aux/ndk-build-helper.mk.
+
+However, none of the Makefiles in
+cross/ndk-build/ndk-build-shared-library.mk perform any kind of
+dependency resolution! Instead, they only define rules to build
+individual modules, leaving dependency resolution up to the Makefiles
+in the `build-aux' directory.
+
+libpng is a very simple module, providing only a single shared object
+module. This module is named libpng_emacs.so and is eventually built
+and packaged into the library directory of the Emacs application
+package. Now, let us look at a more complex module, libwebp:
+
\f
+
+When built with libwebp, Emacs depends on a single library,
+libwebpdemux. This library is named ``libwebpdemux'' on Unix systems,
+and that is the name by which it is found with pkg-config.
+
+However, the library's module is only named ``webpdemux'' on Android.
+When ndk_CHECK_MODULES begins to look for a module, it first tries to
+see if its name is found in the variable `ndk_package_map', which was
+set inside ndk_INIT. In this case, it finds the following word:
+
+ libwebpdemux:webpdemux
+
+and immediately replaces ``libwebpdemux'' with ``webpdemux''.
+
+Then, it locates the ``Android.mk'' file containing a static library
+module named webpdemux and gives the output from
+build-aux/ndk-build-helper.mk to the awk script, resulting in:
+
+module_name=webpdemux
+module_kind=static
+module_src="/opt/android/webp/src/demux/anim_decode.c /opt/android/webp/src/demux/demux.c"
+module_includes="-I/opt/android/webp/src"
+module_cflags=""
+module_ldflags=" cross/ndk-build/libwebpdemux.a cross/ndk-build/libwebp.a cross/ndk-build/libwebpdecoder_static.a "
+module_target="libwebpdemux.a libwebp.a libwebpdecoder_static.a"
+
+The attentive reader will notice that in addition to the
+``libwebpdemux.a'' archive associated with the ``webpdemux'' library,
+Emacs has been made to link with two additional libraries. This is
+because the ``webpdemux'' module specifies a dependency on the
+``webp'' module (defined in the same Android.mk).
+build-aux/ndk-build-helper.mk resolved that dependency, noticing that
+it in turn specified another dependency on ``webpdecoder_static'',
+which in turn was added to the linker command line and list of targets
+to build.
+
+As a result, all three dependencies will be built and linked to Emacs,
+instead of just the single ``webpdemux'' dependency that was
+specified.
+
+\f
+
This file is part of GNU Emacs.
GNU Emacs is free software: you can redistribute it and/or modify
java: lisp info
$(MAKE) -C $@ all
-xcompile: src
+cross: src
$(MAKE) -C $@ all
trampolines: src lisp
### with them.
###
### Delete '.dvi' files here if they are not part of the distribution.
-clean_dirs = $(mostlyclean_dirs) java xcompile nextstep admin/charsets \
+clean_dirs = $(mostlyclean_dirs) java cross nextstep admin/charsets \
admin/unidata
$(foreach dir,$(clean_dirs),$(eval $(call submake_template,$(dir),clean)))
'admin' holds files used by Emacs developers, and Unicode data files.
'build-aux' holds auxiliary files used during the build.
'm4' holds Autoconf macros used for generating the configure script.
+'java' holds the Java code for the Emacs port to Android.
+'cross' holds Makefiles and an additional copy of gnulib used to build
+ Emacs for Android devices.
Building Emacs on non-Posix platforms requires tools that aren't part
of the standard distribution of the OS. The platform-specific README
--- /dev/null
+# ndk-build-helper-1.mk -- Helper for ndk-build.m4.
+# Copyright (C) 2023 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 <https://www.gnu.org/licenses/>.
+
+# Print out information now defined. Important details include:
+# - list of source files to compile.
+# - module export include directories.
+# - module export CFLAGS.
+# - module export LDFLAGS.
+# - module name.
+
+build_kind = shared
+NDK_SO_NAMES =
+NDK_A_NAMES =
+
+# Record this module's dependencies. This information is used later
+# on to recurse over libraries.
+NDK_$(LOCAL_MODULE)_STATIC_LIBRARIES := $(LOCAL_STATIC_LIBRARIES) $(LOCAL_WHOLE_STATIC_LIBRARIES)
+NDK_$(LOCAL_MODULE)_SHARED_LIBRARIES := $(LOCAL_SHARED_LIBRARIES)
+
+$(info Building $(build_kind))
+$(info $(LOCAL_MODULE))
+$(info $(addprefix $(ANDROID_MODULE_DIRECTORY)?,$(LOCAL_SRC_FILES) $(LOCAL_SRC_FILES$(EMACS_ABI))))
+
+$(info $(foreach dir,$(LOCAL_EXPORT_C_INCLUDE_DIRS) $(LOCAL_EXPORT_C_INCLUDES),-I$(dir)))
+$(info $(LOCAL_EXPORT_CFLAGS))
+ifeq ($(LOCAL_MODULE_FILENAME),)
+ifeq ($(findstring lib,$(LOCAL_MODULE)),lib)
+NDK_SO_NAMES = $(LOCAL_MODULE)_emacs.so
+else
+NDK_SO_NAMES = lib$(LOCAL_MODULE)_emacs.so
+endif
+else
+NDK_SO_NAMES = $(LOCAL_MODULE_FILENAME).so
+endif
+
+define add-a-name
+ifeq ($(findstring lib,$(1)),lib)
+NDK_A_NAME = $(1).a
+else
+NDK_A_NAME = lib$(1).a
+endif
+
+ifeq ($$(NDK_A_NAMES:$$(NDK_A_NAME)=),$$(NDK_A_NAMES))
+NDK_A_NAMES := $$(NDK_A_NAMES) $$(NDK_A_NAME)
+
+# Now recurse over this module's dependencies.
+$$(foreach module,$$(filter-out $$(SYSTEM_LIBRARIES), $$(NDK_$(1)_STATIC_LIBRARIES)),$$(eval $$(call add-a-name,$$(module))))
+$$(foreach module,$$(filter-out $$(SYSTEM_LIBRARIES), $$(NDK_$(1)_SHARED_LIBRARIES)),$$(eval $$(call add-so-name,$$(module))))
+endif
+endef
+
+define add-so-name
+ifeq ($(findstring lib,$(1)),lib)
+NDK_SO_NAME = $(1)_emacs.so
+else
+NDK_SO_NAME = lib$(1)_emacs.so
+endif
+
+ifeq ($$(NDK_SO_NAMES:$$(NDK_SO_NAME)=),$$(NDK_SO_NAMES))
+NDK_SO_NAMES := $$(NDK_SO_NAMES) $$(NDK_SO_NAME)
+
+# Now recurse over this module's dependencies.
+$$(foreach module,$$(filter-out $$(SYSTEM_LIBRARIES), $$(NDK_$(1)_STATIC_LIBRARIES)),$$(eval $$(call add-a-name,$$(module))))
+$$(foreach module,$$(filter-out $$(SYSTEM_LIBRARIES), $$(NDK_$(1)_SHARED_LIBRARIES)),$$(eval $$(call add-so-name,$$(module))))
+endif
+endef
+
+# Resolve additional dependencies based on LOCAL_STATIC_LIBRARIES and
+# LOCAL_SHARED_LIBRARIES.
+
+SYSTEM_LIBRARIES = z libz libc c
+
+$(foreach module,$(filter-out $(SYSTEM_LIBRARIES), $(LOCAL_STATIC_LIBRARIES)),$(eval $(call add-a-name,$(module))))
+$(foreach module,$(filter-out $(SYSTEM_LIBRARIES), $(LOCAL_SHARED_LIBRARIES)),$(eval $(call add-so-name,$(module))))
+
+$(info $(LOCAL_EXPORT_LDFLAGS) $(abspath $(addprefix $(NDK_BUILD_DIR)/,$(NDK_A_NAMES))) -L$(abspath $(NDK_BUILD_DIR)) $(foreach soname,$(NDK_SO_NAMES),-l:$(soname)))
+$(info $(NDK_SO_NAMES))
+$(info End)
--- /dev/null
+# ndk-build-helper-2.mk -- Helper for ndk-build.m4.
+# Copyright (C) 2023 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 <https://www.gnu.org/licenses/>.
+
+# Say a static library is being built
+build_kind = static
+NDK_SO_NAMES =
+NDK_A_NAMES =
+
+# Record this module's dependencies. This information is used later
+# on to recurse over libraries.
+NDK_$(LOCAL_MODULE)_STATIC_LIBRARIES := $(LOCAL_STATIC_LIBRARIES) $(LOCAL_WHOLE_STATIC_LIBRARIES)
+NDK_$(LOCAL_MODULE)_SHARED_LIBRARIES := $(LOCAL_SHARED_LIBRARIES)
+
+$(info Building $(build_kind))
+$(info $(LOCAL_MODULE))
+$(info $(addprefix $(ANDROID_MODULE_DIRECTORY)/,$(LOCAL_SRC_FILES) $(LOCAL_SRC_FILES$(EMACS_ABI))))
+
+$(info $(foreach dir,$(LOCAL_EXPORT_C_INCLUDE_DIRS) $(LOCAL_EXPORT_C_INCLUDES),-I$(dir)))
+$(info $(LOCAL_EXPORT_CFLAGS))
+ifeq ($(LOCAL_MODULE_FILENAME),)
+
+ifeq ($(findstring lib,$(LOCAL_MODULE)),lib)
+NDK_A_NAMES = $(LOCAL_MODULE).a
+else
+NDK_A_NAMES = lib$(LOCAL_MODULE).a
+endif
+else
+NDK_A_NAMES = $(LOCAL_MODULE_FILENAME).a
+endif
+
+define add-a-name
+ifeq ($(findstring lib,$(1)),lib)
+NDK_A_NAME = $(1).a
+else
+NDK_A_NAME = lib$(1).a
+endif
+
+ifeq ($$(NDK_A_NAMES:$$(NDK_A_NAME)=),$$(NDK_A_NAMES))
+NDK_A_NAMES := $$(NDK_A_NAMES) $$(NDK_A_NAME)
+
+# Now recurse over this module's dependencies.
+$$(foreach module,$$(filter-out $$(SYSTEM_LIBRARIES), $$(NDK_$(1)_STATIC_LIBRARIES)),$$(eval $$(call add-a-name,$$(module))))
+$$(foreach module,$$(filter-out $$(SYSTEM_LIBRARIES), $$(NDK_$(1)_SHARED_LIBRARIES)),$$(eval $$(call add-so-name,$$(module))))
+endif
+endef
+
+define add-so-name
+ifeq ($(findstring lib,$(1)),lib)
+NDK_SO_NAME = $(1)_emacs.so
+else
+NDK_SO_NAME = lib$(1)_emacs.so
+endif
+
+ifeq ($$(NDK_SO_NAMES:$$(NDK_SO_NAME)=),$$(NDK_SO_NAMES))
+NDK_SO_NAMES := $$(NDK_SO_NAMES) $$(NDK_SO_NAME)
+
+# Now recurse over this module's dependencies.
+$$(foreach module,$$(filter-out $$(SYSTEM_LIBRARIES), $$(NDK_$(1)_STATIC_LIBRARIES)),$$(eval $$(call add-a-name,$$(module))))
+$$(foreach module,$$(filter-out $$(SYSTEM_LIBRARIES), $$(NDK_$(1)_SHARED_LIBRARIES)),$$(eval $$(call add-so-name,$$(module))))
+endif
+endef
+
+# Resolve additional dependencies based on LOCAL_STATIC_LIBRARIES and
+# LOCAL_SHARED_LIBRARIES.
+
+SYSTEM_LIBRARIES = z libz
+
+$(foreach module,$(filter-out $(SYSTEM_LIBRARIES), $(LOCAL_STATIC_LIBRARIES)),$(eval $(call add-a-name,$(module))))
+$(foreach module,$(filter-out $(SYSTEM_LIBRARIES), $(LOCAL_SHARED_LIBRARIES)),$(eval $(call add-so-name,$(module))))
+
+$(info $(LOCAL_EXPORT_LDFLAGS) $(abspath $(addprefix $(NDK_BUILD_DIR)/,$(NDK_A_NAMES))) $(and $(NDK_SO_NAMES), -L$(abspath $(NDK_BUILD_DIR)) $(foreach soname,$(NDK_SO_NAMES),-l:$(soname))))
+$(info $(NDK_A_NAMES))
+$(info End)
--- /dev/null
+# ndk-build-helper-3.mk -- Helper for ndk-build.m4.
+# Copyright (C) 2023 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 <https://www.gnu.org/licenses/>.
+
+# Say a static library is being built
+build_kind = executable
+
+$(info Building $(build_kind))
+$(info $(LOCAL_MODULE))
+$(info $(addprefix $(ANDROID_MODULE_DIRECTORY),$(LOCAL_SRC_FILES) $(LOCAL_SRC_FILES$(EMACS_ABI))))
+
+$(info $(foreach dir,$(LOCAL_EXPORT_C_INCLUDE_DIRS) $(LOCAL_EXPORT_C_INCLUDES),-I$(dir)))
+$(info $(LOCAL_EXPORT_CFLAGS))
+$(info $(LOCAL_EXPORT_LDFLAGS))
+$(info End)
--- /dev/null
+# Copyright (C) 2023 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 <https://www.gnu.org/licenses/>.
+
+undefine LOCAL_MODULE
+undefine LOCAL_MODULE_FILENAME
+undefine LOCAL_SRC_FILES
+undefine LOCAL_CPP_EXTENSION
+undefine LOCAL_CPP_FEATURES
+undefine LOCAL_C_INCLUDES
+undefine LOCAL_CFLAGS
+undefine LOCAL_CPPFLAGS
+undefine LOCAL_STATIC_LIBRARIES
+undefine LOCAL_SHARED_LIBRARIES
+undefine LOCAL_WHOLE_STATIC_LIBRARIES
+undefine LOCAL_LDLIBS
+undefine LOCAL_LDFLAGS
+undefine LOCAL_ALLOW_UNDEFINED_SYMBOLS
+undefine LOCAL_ARM_MODE
+undefine LOCAL_ARM_NEON
+undefine LOCAL_DISABLE_FORMAT_STRING_CHECKS
+undefine LOCAL_EXPORT_CFLAGS
+undefine LOCAL_EXPORT_CPPFLAGS
+undefine LOCAL_EXPORT_C_INCLUDES
+undefine LOCAL_EXPORT_LDFLAGS
+undefine LOCAL_EXPORT_LDLIBS
--- /dev/null
+# ndk-build-helper.mk -- Helper for ndk-build.m4.
+# Copyright (C) 2023 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 <https://www.gnu.org/licenses/>.
+
+# This Makefile sets up enough to parse an Android-style Android.mk
+# file and return useful information about its contents.
+
+# See the text under ``NDK BUILD SYSTEM IMPLEMENTATION'' in
+# INSTALL.android for more details.
+
+# Make NDK_BUILD_DIR absolute.
+NDK_BUILD_DIR := $(absname $(NDK_BUILD_DIR))
+
+# my-dir is a function that returns the Android module directory.
+my-dir = $(ANDROID_MODULE_DIRECTORY)
+
+# all-subdir-makefiles is a function which returns all Android.mk
+# files within this directory.
+all-subdir-makefiles = $(shell find . -name "Android.mk")
+
+# These functions are not implemented.
+parent-makefile =
+grand-parent-makefile =
+import-module =
+
+# Print out module information every time BUILD_SHARED_LIBRARY is
+# called.
+
+BUILD_SHARED_LIBRARY=$(EMACS_SRCDIR)/build-aux/ndk-build-helper-1.mk
+BUILD_STATIC_LIBRARY=$(EMACS_SRCDIR)/build-aux/ndk-build-helper-2.mk
+BUILD_EXECUTABLE=$(EMACS_SRCDIR)/build-aux/ndk-build-helper-3.mk
+CLEAR_VARS=$(EMACS_SRCDIR)/build-aux/ndk-build-helper-4.mk
+
+# Now include Android.mk.
+
+include $(ANDROID_MAKEFILE)
+
+# Dummy target.
+all:
--- /dev/null
+/^Building.+$/ {
+ kind = $2
+}
+
+// {
+ if (!match ($0, /^End$/) && !match ($0, /^Building.+$/))
+ {
+ if (kind)
+ {
+ if (ldflags_found)
+ target = $0
+ else if (cflags_found)
+ {
+ ldflags = $0
+ ldflags_found = 1
+ }
+ else if (includes_found)
+ {
+ cflags = $0
+ cflags_found = 1
+ }
+ else if (src_found)
+ {
+ includes = $0
+ includes_found = 1
+ }
+ else if (name_found)
+ {
+ src = $0
+ src_found = 1;
+ }
+ else
+ {
+ name = $0
+ name_found = 1
+ }
+ }
+ }
+}
+
+/^End$/ {
+ if (name == MODULE && (kind == "shared" || kind == "static"))
+ {
+ printf "module_name=%s\n", name
+ printf "module_kind=%s\n", kind
+ printf "module_src=\"%s\"\n", src
+ printf "module_includes=\"%s\"\n", includes
+ printf "module_cflags=\"%s\"\n", cflags
+ printf "module_ldflags=\"%s\"\n", ldflags
+ printf "module_target=\"%s\"\n", target
+ }
+
+ src = ""
+ name = ""
+ kind = ""
+ includes = ""
+ cflags = ""
+ ldflags = ""
+ name_found = ""
+ src_found = ""
+ includes_found = ""
+ cflags_found = ""
+ ldflags_found = ""
+}
AC_CANONICAL_HOST
AC_CANONICAL_BUILD
+if test "$XCONFIGURE" = "android"; then
+ # Initialize the Android NDK build system. Make sure to use the
+ # passed through NDK path.
+ with_ndk_path="$android_ndk_path"
+ ndk_INIT([$android_abi], [$ANDROID_SDK], [cross/ndk-build])
+fi
+
case $host in
*-mingw*)
OPTION_DEFAULT_ON([xinput2],[don't use version 2 of the X Input Extension for input])
OPTION_DEFAULT_OFF([small-ja-dic],[generate a smaller-size Japanese dictionary])
OPTION_DEFAULT_OFF([android],[cross-compile Android application package])
+OPTION_DEFAULT_ON([android-debug],[don't build Emacs as a debug package on Android])
AC_ARG_WITH([file-notification],[AS_HELP_STRING([--with-file-notification=LIB],
[use a file notification library (LIB one of: yes, inotify, kqueue, gfile, w32, no)])],
mv -f confdefs.h _confdefs.h
mv -f config.log _config.log
+ # Figure out what --with-FOO options to pass through.
+ passthrough="$passthrough --with-png=$with_png"
+ passthrough="$passthrough --with-webp=$with_webp"
+ passthrough="$passthrough --with-gif=$with_gif"
+
AS_IF([XCONFIGURE=android ANDROID_CC="$ANDROID_CC" \
- ANDROID_SDK="$android_sdk" $0], [],
+ ANDROID_SDK="$android_sdk" android_abi=$android_abi \
+ android_ndk_path="$with_ndk_path" $0 $passthrough], [],
[AC_MSG_ERROR([Failed to cross-configure Emacs for android.])])
# Now set ANDROID to yes.
AC_MSG_NOTICE([Generating src/config.h.android])
mv -f src/config.h src/config.h.android
+ # Tell AndroidManifest.xml whether or not Emacs should be built
+ # debug.
+ ANDROID_DEBUGGABLE=false
+ if test "$with_android_debug" = "yes"; then
+ ANDROID_DEBUGGABLE=true
+ fi
+ AC_SUBST([ANDROID_DEBUGGABLE])
+
# Move confdefs.h back now that the recursive call to configure is
# complete.
mv -f _confdefs.h confdefs.h
with_xpm=no
with_jpeg=no
with_tiff=no
- with_gif=no
- with_png=no
+
+ # Some of these dependencies are now supported within Android, so
+ # they can be enabled.
+ if test "$XCONFIGURE" != "android"; then
+ with_png=no
+ with_webp=no
+ with_gif=no
+ fi
+
+ with_xml2=no
with_rsvg=no
- with_webp=no
with_sqlite3=no
with_lcms2=no
with_libsystemd=no
with_cairo=no
- with_xml2=no
with_imagemagick=no
with_json=no
with_tree_sitter=no
dnl can take the place of the default HAVE_GSTUFF=yes and HAVE_GSTUFF=no
dnl actions.
AC_DEFUN([EMACS_CHECK_MODULES],
- [PKG_CHECK_MODULES([$1], [$2],
- [$1_CFLAGS=`AS_ECHO(["$$1_CFLAGS"]) | sed -e "$edit_cflags"`
- m4_default([$3], [HAVE_$1=yes])],
- [m4_default([$4], [HAVE_$1=no])])])
+ [AS_IF([test -n "$ndk_INITIALIZED"],
+ [ndk_CHECK_MODULES([$1], [$2], m4_default([$3], [HAVE_$1=yes]),
+ m4_default([$4],[HAVE_$1=no]))],
+ [PKG_CHECK_MODULES([$1], [$2],
+ [$1_CFLAGS=`AS_ECHO(["$$1_CFLAGS"]) | sed -e "$edit_cflags"`
+ m4_default([$3], [HAVE_$1=yes])],
+ [m4_default([$4], [HAVE_$1=no])])])])
HAVE_SOUND=no
if test "${with_sound}" != "no"; then
ANDROID_OBJ=
ANDROID_LIBS=
ANDROID_CFLAGS=
+REALLY_ANDROID=
CM_OBJ="cm.o"
if test "${ANDROID}" = "yes"; then
# Link with libraries required for Android support.
ANDROID_LIBS="-landroid -llog -ljnigraphics"
+ # This is required to make the system load emacs.apk's libpng
+ # (among others) instead of the system's own. But it doesn't work
+ # on all Android versions yet, so for now just suffix shared
+ # libraries with _emacs.
+ # ANDROID_LDFLAGS="-Wl,-rpath,'\$\$ORIGIN'"
+
# Link with the sfnt font library and sfntfont.o, along with
# sfntfont-android.o.
ANDROID_OBJ="$ANDROID_OBJ sfnt.o sfntfont.o sfntfont-android.o"
+ # Build androidselect.o.
+ ANDROID_OBJ="$ANDROID_OBJ androidselect.o"
+
# Check for some functions not always present in the NDK.
AC_CHECK_DECLS([android_get_device_api_level])
+
+ # Say this build is really for Android.
+ REALLY_ANDROID=yes
fi
fi
AC_SUBST(ANDROID)
AC_SUBST(ANDROID_OBJ)
AC_SUBST(ANDROID_LIBS)
+AC_SUBST(ANDROID_LDFLAGS)
AC_SUBST(ANDROID_CFLAGS)
if test "${with_pgtk}" = "yes"; then
if test "${with_webp}" != "no"; then
if test "${HAVE_X11}" = "yes" || test "${opsys}" = "mingw32" \
|| test "${HAVE_W32}" = "yes" || test "${HAVE_NS}" = "yes" \
- || test "${HAVE_BE_APP}" = "yes" || test "${HAVE_PGTK}" = "yes"; then
+ || test "${HAVE_BE_APP}" = "yes" || test "${HAVE_PGTK}" = "yes" \
+ || test "${REALLY_ANDROID}" = "yes"; then
WEBP_REQUIRED=0.6.0
WEBP_MODULE="libwebpdemux >= $WEBP_REQUIRED"
LIBJPEG=
if test "${HAVE_X11}" = "yes" || test "${HAVE_W32}" = "yes" \
|| test "${HAVE_NS}" = "yes" || test "${HAVE_BE_APP}" = "yes" \
- || test "$window_system" = "pgtk"; then
+ || test "$window_system" = "pgtk" \
+ || test "${REALLY_ANDROID}" = "yes"; then
if test "${with_jpeg}" != "no"; then
AC_CACHE_CHECK([for jpeglib 6b or later],
[emacs_cv_jpeglib],
AC_CHECK_HEADER([png.h], [HAVE_PNG=yes])
elif test "${HAVE_X11}" = "yes" || test "${HAVE_W32}" = "yes" \
|| test "${HAVE_NS}" = "yes" || test "${HAVE_BE_APP}" = "yes" \
- || test "$window_system" = "pgtk"; then
+ || test "$window_system" = "pgtk" \
+ || test "${REALLY_ANDROID}" = "yes"; then
EMACS_CHECK_MODULES([PNG], [libpng >= 1.0.0])
if test $HAVE_PNG = yes; then
LIBPNG=$PNG_LIBS
### Use -lgif or -lungif if available, unless '--with-gif=no'.
### mingw32 doesn't use -lgif/-lungif, since it loads the library dynamically.
HAVE_GIF=no
+GIF_CFLAGS=
LIBGIF=
if test "${opsys}" = "mingw32"; then
if test "${with_gif}" != "no"; then
elif test "${HAVE_X11}" = "yes" && test "${with_gif}" != "no" \
|| test "${HAVE_W32}" = "yes" || test "${HAVE_NS}" = "yes" \
|| test "${HAVE_BE_APP}" = "yes" || test "$window_system" = "pgtk" \
+ || test "${REALLY_ANDROID}" = "yes" \
&& test "${with_gif}" != "no"; then
AC_CHECK_HEADER([gif_lib.h],
# EGifPutExtensionLast only exists from version libungif-4.1.0b1.
test "$HAVE_GIF" = yes && LIBGIF=-lungif
fi
+# Finally, try ndk-build on Android.
+ if test "$REALLY_ANDROID" = "yes"; then
+ ndk_SEARCH_MODULE([libgif], [GIF], [HAVE_GIF=yes],
+ [HAVE_GIF=no])
+ test "$HAVE_GIF" = yes && LIBGIF="$GIF_LIBS"
+ fi
+
if test "${HAVE_GIF}" = "yes"; then
AC_DEFINE([HAVE_GIF], [1],
[Define to 1 if you have a gif (or ungif) library.])
fi
fi
AC_SUBST([LIBGIF])
+AC_SUBST([GIF_CFLAGS])
dnl Check for required libraries.
MISSING=
fi
if test "$XCOMPILE" = "yes"; then
- SUBDIR_MAKEFILES="$SUBDIR_MAKEFILES xcompile/Makefile"
+ SUBDIR_MAKEFILES="$SUBDIR_MAKEFILES cross/Makefile"
fi
dnl The admin/ directory used to be excluded from tarfiles.
# Make java/Makefile
ARCH_INDEPENDENT_CONFIG_FILES([java/Makefile])
-ARCH_INDEPENDENT_CONFIG_FILES([xcompile/Makefile])
+ARCH_INDEPENDENT_CONFIG_FILES([cross/Makefile])
# Make java/AndroidManifest.xml
ARCH_INDEPENDENT_CONFIG_FILES([java/AndroidManifest.xml])
+# Make ndk-build Makefiles. This is only done inside the recursive
+# configure.
+ndk_CONFIG_FILES
+
AC_OUTPUT
if test ! "$with_mailutils"; then
--- /dev/null
+### @configure_input@
+
+# Copyright 2023 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 <https://www.gnu.org/licenses/>.
+
+# ndk-build works by including a bunch of Makefiles which set
+# variables, and then having those Makefiles include another makefile
+# which actually builds targets.
+
+ srcdir = @srcdir@
+
+# This is a list of Android.mk files which provide targets.
+NDK_BUILD_ANDROID_MK = @NDK_BUILD_ANDROID_MK@
+ NDK_BUILD_ARCH = @NDK_BUILD_ARCH@
+ NDK_BUILD_ABI = @NDK_BUILD_ABI@
+ NDK_BUILD_SDK = @NDK_BUILD_SDK@
+ NDK_BUILD_CC = @NDK_BUILD_CC@
+ NDK_BUILD_AR = @NDK_BUILD_AR@
+
+# This is a list of targets to build.
+ NDK_BUILD_MODULES = @NDK_BUILD_MODULES@
+
+# This is set by the Android in tree build system and is used by some
+# libraries to look for the NDK. Its value is unimportant.
+ NDK_ROOT = /tmp/
+
+# Finally, here are rules common to Emacs.
+.PHONY: all
+all: $(NDK_BUILD_MODULES)
+
+define uniqify
+$(if $1,$(firstword $1) $(call uniqify,$(filter-out $(firstword $1),$1)))
+endef
+
+# Remove duplicate files.
+NDK_BUILD_ANDROID_MK := $(call uniqify,$(NDK_BUILD_ANDROID_MK))
+
+define subr-1
+
+# Define ndk-build functions.
+
+define my-dir
+$(dir $(abspath $(1)))
+endef
+
+# NDK-defined include variables.
+
+CLEAR_VARS = $(srcdir)/ndk-clear-vars.mk
+BUILD_EXECUTABLE = $(srcdir)/ndk-build-executable.mk
+BUILD_SHARED_LIBRARY = $(srcdir)/ndk-build-shared-library.mk
+BUILD_STATIC_LIBRARY = $(srcdir)/ndk-build-static-library.mk
+PREBUILT_SHARED_LIBRARY = $(srcdir)/ndk-prebuilt-shared-library.mk
+PREBUILT_STATIC_LIBRARY = $(srcdir)/ndk-prebuilt-static-library.mk
+
+# Target information variables.
+
+TARGET_ARCH = $(NDK_BUILD_ARCH)
+TARGET_PLATFORM = android-$(NDK_BUILD_SDK)
+TARGET_ARCH_ABI = $(NDK_BUILD_ABI)
+TARGET_ABI = $(TARGET_PLATFORM)-$(TARGET_ABI)
+
+# Module description variables. These are defined by Android.mk.
+LOCAL_PATH :=
+LOCAL_MODULE :=
+LOCAL_MODULE_FILENAME :=
+LOCAL_SRC_FILES :=
+LOCAL_CPP_EXTENSION :=
+LOCAL_CPP_FEATURES :=
+LOCAL_C_INCLUDES :=
+LOCAL_CFLAGS :=
+LOCAL_CPPFLAGS :=
+LOCAL_STATIC_LIBRARIES :=
+LOCAL_SHARED_LIBRARIES :=
+LOCAL_WHOLE_STATIC_LIBRARIES :=
+LOCAL_LDLIBS :=
+LOCAL_LDFLAGS :=
+LOCAL_ALLOW_UNDEFINED_SYMBOLS :=
+LOCAL_ARM_MODE :=
+LOCAL_ARM_NEON :=
+LOCAL_DISABLE_FORMAT_STRING_CHECKS :=
+LOCAL_EXPORT_CFLAGS :=
+LOCAL_EXPORT_CPPFLAGS :=
+LOCAL_EXPORT_C_INCLUDES :=
+LOCAL_EXPORT_LDFLAGS :=
+LOCAL_EXPORT_LDLIBS :=
+
+# Now load Android.mk.
+include $(1)
+
+endef
+
+# Now define rules for each Android.mk file.
+$(foreach android_mk,$(NDK_BUILD_ANDROID_MK),$(eval $(call subr-1,$(android_mk))))
+
+.PHONY: clean mostlyclean
+clean mostlyclean:
+ rm -rf *.o *.so *.a
+
+.PHONY: extraclean dist-clean maintainer-clean
+extraclean dist-clean maintainer-clean:
+ rm -rf Makefile
--- /dev/null
+# Copyright 2023 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 <https://www.gnu.org/licenses/>.
+
+# ndk-build works by including a bunch of Makefiles which set
+# variables, and then having those Makefiles include another makefile
+# which actually builds targets.
+
+# Building executables is not supported
--- /dev/null
+# Copyright 2023 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 <https://www.gnu.org/licenses/>.
+
+# ndk-build works by including a bunch of Makefiles which set
+# variables, and then having those Makefiles include another makefile
+# which actually builds targets.
+
+eq = $(and $(findstring $(1),$(2)),$(findstring $(2),$(1)))
+objname = $(1)-$(subst /,_,$(2).o)
+
+define single-object-target
+
+ifeq (x$(suffix $(1)),x.c)
+
+$(call objname,$(LOCAL_MODULE),$(basename $(1))): $(LOCAL_PATH)/$(1)
+ $(NDK_BUILD_CC) -c $$< -o $$@ $(NDK_CFLAGS_$(LOCAL_MODULE))
+
+else
+ifneq ($(or $(call eq,x$(suffix $(1)),x.s),$(call eq,x$(suffix $(1)),x.S)),)
+
+$(call objname,$(LOCAL_MODULE),$(basename $(1))): $(LOCAL_PATH)/$(1)
+ $(NDK_BUILD_CC) -c $$< -o $$@ $(NDK_ASFLAGS_$(LOCAL_MODULE))
+
+else
+$$(error Unsupported suffix: $(suffix $(1)))
+endif
+endif
+
+ALL_OBJECT_FILES$(LOCAL_MODULE) += $(call objname,$(LOCAL_MODULE),$(basename $(1)))
+
+endef
+
+NDK_CFLAGS_$(LOCAL_MODULE) := $(addprefix -I,$(addprefix $(LOCAL_PATH),$(LOCAL_C_INCLUDES)))
+NDK_CFLAGS_$(LOCAL_MODULE) ::= -fPIC -iquote $(LOCAL_EXPORT_CFLAGS) $(LOCAL_PATH) $(LOCAL_CFLAGS)
+NDK_LDFLAGS_$(LOCAL_MODULE) := $(LOCAL_LDLIBS)
+NDK_LDFLAGS_$(LOCAL_MODULE) := $(LOCAL_LDFLAGS)
+ALL_OBJECT_FILES_$(LOCAL_MODULE) :=
+
+ifeq ($(NDK_BUILD_ARCH)$(NDK_ARM_MODE),armarm)
+NDK_CFLAGS ::= -marm
+else
+ifeq ($(NDK_BUILD_ARCH),arm)
+NDK_CFLAGS ::= -mthumb
+endif
+endif
+
+LOCAL_MODULE_FILENAME := $(strip $(LOCAL_MODULE_FILENAME))
+
+ifndef LOCAL_MODULE_FILENAME
+ifeq ($(findstring lib,$(LOCAL_MODULE)),lib)
+LOCAL_MODULE_FILENAME := $(LOCAL_MODULE)_emacs
+else
+LOCAL_MODULE_FILENAME := lib$(LOCAL_MODULE)_emacs
+endif
+endif
+
+# Since a shared library is being built, suffix the library with
+# _emacs. Otherwise, libraries already on the system will be found
+# first, with potentially nasty consequences.
+
+LOCAL_MODULE_FILENAME := $(LOCAL_MODULE_FILENAME).so
+
+# Then define rules to build all objects.
+ALL_SOURCE_FILES = $(LOCAL_SRC_FILES)
+$(foreach source,$(ALL_SOURCE_FILES),$(eval $(call single-object-target,$(source))))
+
+# Now define the rule to build the shared library.
+$(LOCAL_MODULE_FILENAME): $(ALL_OBJECT_FILES$(LOCAL_MODULE))
+ $(NDK_BUILD_CC) $^ -o $@ -shared $(NDK_LDFLAGS$(LOCAL_MODULE))
--- /dev/null
+# Copyright 2023 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 <https://www.gnu.org/licenses/>.
+
+# ndk-build works by including a bunch of Makefiles which set
+# variables, and then having those Makefiles include another makefile
+# which actually builds targets.
+
+eq = $(and $(findstring $(1),$(2)),$(findstring $(2),$(1)))
+objname = $(1)-$(subst /,_,$(2).o)
+
+define single-object-target
+
+ifeq (x$(suffix $(1)),x.c)
+
+$(call objname,$(LOCAL_MODULE),$(basename $(1))): $(LOCAL_PATH)/$(1)
+ $(NDK_BUILD_CC) -c $$< -o $$@ $(NDK_CFLAGS_$(LOCAL_MODULE))
+
+else
+ifneq ($(or $(call eq,x$(suffix $(1)),x.s),$(call eq,x$(suffix $(1)),x.S)),)
+
+$(call objname,$(LOCAL_MODULE),$(basename $(1))): $(LOCAL_PATH)/$(1)
+ $(NDK_BUILD_CC) -c $$< -o $$@ $(NDK_ASFLAGS_$(LOCAL_MODULE))
+
+else
+$$(error Unsupported suffix: $(suffix $(1)))
+endif
+endif
+
+ALL_OBJECT_FILES$(LOCAL_MODULE) += $(call objname,$(LOCAL_MODULE),$(basename $(1)))
+endef
+
+NDK_CFLAGS_$(LOCAL_MODULE) := $(addprefix -I,$(addprefix $(LOCAL_PATH),$(LOCAL_C_INCLUDES)))
+NDK_CFLAGS_$(LOCAL_MODULE) ::= -iquote $(LOCAL_PATH) $(LOCAL_EXPORT_CFLAGS) $(LOCAL_CFLAGS) $(LOCAL_CFLAGS_$(NDK_BUILD_ARCH))
+NDK_ASFLAGS_$(LOCAL_MODULE) ::= $(LOCAL_ASFLAGS) $(LOCAL_ASFLAGS_$(NDK_BUILD_ARCH))
+NDK_LDFLAGS_$(LOCAL_MODULE) := $(LOCAL_LDLIBS)
+NDK_LDFLAGS_$(LOCAL_MODULE) := $(LOCAL_LDFLAGS)
+ALL_OBJECT_FILES$(LOCAL_MODULE) :=
+
+ifeq ($(NDK_BUILD_ARCH)$(NDK_ARM_MODE),armarm)
+NDK_CFLAGS ::= -marm
+else
+ifeq ($(NDK_BUILD_ARCH),arm)
+NDK_CFLAGS ::= -mthumb
+endif
+endif
+
+LOCAL_MODULE_FILENAME := $(strip $(LOCAL_MODULE_FILENAME))
+
+ifndef LOCAL_MODULE_FILENAME
+ifeq ($(findstring lib,$(LOCAL_MODULE)),lib)
+LOCAL_MODULE_FILENAME := $(LOCAL_MODULE)
+else
+LOCAL_MODULE_FILENAME := lib$(LOCAL_MODULE)
+endif
+endif
+
+LOCAL_MODULE_FILENAME := $(LOCAL_MODULE_FILENAME).a
+
+# Then define rules to build all objects.
+ALL_SOURCE_FILES = $(LOCAL_SRC_FILES) $(LOCAL_SRC_FILES_$(NDK_BUILD_ARCH))
+
+# This defines all dependencies.
+ALL_OBJECT_FILES$(LOCAL_MODULE) =
+
+$(foreach source,$(ALL_SOURCE_FILES),$(eval $(call single-object-target,$(source))))
+
+# Now define the rule to build the library.
+$(LOCAL_MODULE_FILENAME): $(ALL_OBJECT_FILES$(LOCAL_MODULE))
+ $(NDK_BUILD_AR) r $@ $^
--- /dev/null
+### @configure_input@
+
+# Copyright (C) 2023 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 <https://www.gnu.org/licenses/>.
+
+# This file is included all over the place to build prerequisites.
+
+NDK_BUILD_MODULES = @NDK_BUILD_MODULES@
+NDK_BUILD_SHARED =
+NDK_BUILD_STATIC =
+
+define subr-1
+
+.PHONY $(top_builddir)/cross/ndk-build/$(0)
+$(top_builddir)/cross/ndk-build/$(0):
+ $(MAKE) -C $(top_builddir)/cross/ndk-build $(0)
+
+ifeq ($(suffix $(0)),.so)
+NDK_BUILD_SHARED += $(top_builddir)/cross/ndk-build/$(0)
+else
+ifeq ($(suffix $(0)),.a)
+NDK_BUILD_STATIC += $(top_builddir)/cross/ndk-build/$(0)
+endif
+endif
+
+endef
+
+# Generate rules for each module.
+
+$(foreach module,$(NDK_BUILD_MODULES),$(eval $(call subr-1,$(module))))
--- /dev/null
+### @configure_input@
+
+# Copyright (C) 2023 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 <https://www.gnu.org/licenses/>.
+
+# This file is included all over the place to build prerequisites.
+
+NDK_BUILD_MODULES = @NDK_BUILD_MODULES@
+NDK_BUILD_SHARED =
+NDK_BUILD_STATIC =
+
+define subr-1
+
+$(top_builddir)/cross/ndk-build/$(1):
+ $(MAKE) -C $(top_builddir)/cross/ndk-build $(1)
+
+ifeq ($(suffix $(1)),.so)
+NDK_BUILD_SHARED += $(top_builddir)/cross/ndk-build/$(1)
+else
+ifeq ($(suffix $(1)),.a)
+NDK_BUILD_STATIC += $(top_builddir)/cross/ndk-build/$(1)
+endif
+endif
+
+endef
+
+# Generate rules for each module.
+
+$(foreach module,$(NDK_BUILD_MODULES),$(eval $(call subr-1,$(module))))
--- /dev/null
+# Copyright 2023 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 <https://www.gnu.org/licenses/>.
+
+# ndk-build works by including a bunch of Makefiles which set
+# variables, and then having those Makefiles include another makefile
+# which actually builds targets.
+
+undefine LOCAL_MODULE
+undefine LOCAL_MODULE_FILENAME
+undefine LOCAL_SRC_FILES
+undefine LOCAL_CPP_EXTENSION
+undefine LOCAL_CPP_FEATURES
+undefine LOCAL_C_INCLUDES
+undefine LOCAL_CFLAGS
+undefine LOCAL_CPPFLAGS
+undefine LOCAL_STATIC_LIBRARIES
+undefine LOCAL_SHARED_LIBRARIES
+undefine LOCAL_WHOLE_STATIC_LIBRARIES
+undefine LOCAL_LDLIBS
+undefine LOCAL_LDFLAGS
+undefine LOCAL_ALLOW_UNDEFINED_SYMBOLS
+undefine LOCAL_ARM_MODE
+undefine LOCAL_ARM_NEON
+undefine LOCAL_DISABLE_FORMAT_STRING_CHECKS
+undefine LOCAL_EXPORT_CFLAGS
+undefine LOCAL_EXPORT_CPPFLAGS
+undefine LOCAL_EXPORT_C_INCLUDES
+undefine LOCAL_EXPORT_LDFLAGS
+undefine LOCAL_EXPORT_LDLIBS
+
+undefine LOCAL_SRC_FILES_$(NDK_BUILD_ARCH)
+undefine LOCAL_ASFLAGS_$(NDK_BUILD_ARCH)
+undefine LOCAL_CFLAGS_$(NDK_BUILD_ARCH)
--- /dev/null
+### @configure_input@
+
+# Copyright 2023 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 <https://www.gnu.org/licenses/>.
+
+# ndk-build works by including a bunch of Makefiles which set
+# variables, and then having those Makefiles include another makefile
+# which actually builds targets.
+
+$(warn Prebuilt shared libraries are not supported)
--- /dev/null
+### @configure_input@
+
+# Copyright 2023 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 <https://www.gnu.org/licenses/>.
+
+# ndk-build works by including a bunch of Makefiles which set
+# variables, and then having those Makefiles include another makefile
+# which actually builds targets.
+
+$(warn Prebuilt static libraries are not supported)
* Android Startup:: Starting up Emacs on Android.
* Android File System:: The Android file system.
* Android Environment:: Running Emacs under Android.
+* Android Windowing:: The Android window system.
* Android Fonts:: Font selection under Android.
@end menu
more details, as how to do this varies by device.
@end itemize
-@section Android windowing
+@node Android Windowing
+@section The Android window system
Android has an unusual window system; there, all windows are
maximized or full-screen, and only one window can be displayed at a
top-level frames.
@end itemize
+@cindex selections, android
+@cindex android clipboard
+ Emacs does not implement all selection related features supported
+under the X Window System on Android. For example, only the
+@code{CLIPBOARD} and @code{PRIMARY} selections (@pxref{Cut and Paste})
+are supported, and plain text is the only supported data type.
+
+ In addition, the Android system itself places certain restrictions
+on what selection data Emacs can access:
+
+@itemize @bullet
+@item
+On Android 2.3 and earlier, the function @code{gui-selection-owner-p}
+always returns @code{nil} for the clipboard selection.
+
+@item
+On Android 3.0 and later, Emacs can only access clipboard data when
+one of its frames has the input focus.
+@end itemize
+
+ Since the Android system itself has no concept of a primary
+selection, Emacs provides an emulation instead. This means there is
+no way to transfer the contents of the primary selection to another
+application via cut-and-paste.
+
@node Android Fonts
@section Font backends and selection under Android
@cindex fonts, android
* Android Startup:: Starting up Emacs on Android.
* Android File System:: The Android file system.
* Android Environment:: Running Emacs under Android.
+* Android Windowing:: The Android window system.
* Android Fonts:: Font selection under Android.
Emacs and unconventional input devices
The earliest release of Haiku that will successfully compile Emacs
is R1/Beta2. For windowing support, R1/Beta3 or later is required.
+** Android
+
+ Emacs is known to run on all Android versions from 2.3 onwards.
+ It should work with Android 2.2 as well, but only the build
+ has been tested, and actually running the built Emacs has not.
+
+ See the file INSTALL.android for detailed installation instructions.
+
\f
* Obsolete platforms
android:hardwareAccelerated="true"
android:supportsRtl="true"
android:theme="@android:style/Theme"
- android:debuggable="true"
+ android:debuggable="@ANDROID_DEBUGGABLE@"
android:extractNativeLibs="true">
<activity android:name="org.gnu.emacs.EmacsActivity"
android:launchMode="singleTop"
android:windowSoftInputMode="adjustResize"
+ android:exported="true"
android:configChanges="orientation|screenSize|screenLayout|keyboardHidden">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<activity android:name="org.gnu.emacs.EmacsMultitaskActivity"
android:windowSoftInputMode="adjustResize"
+ android:exported="true"
android:configChanges="orientation|screenSize|screenLayout|keyboardHidden"/>
<activity android:autoRemoveFromRecents="true"
android:label="Emacs options"
+ android:exported="true"
android:name=".EmacsPreferencesActivity">
<intent-filter>
<action android:name="android.intent.action.APPLICATION_PREFERENCES" />
all: $(APK_NAME)
# Binaries to cross-compile.
-CROSS_BINS = ../xcompile/src/android-emacs ../xcompile/lib-src/ctags \
- ../xcompile/lib-src/hexl ../xcompile/lib-src/movemail \
- ../xcompile/lib-src/ebrowse ../xcompile/lib-src/emacsclient
+CROSS_BINS = ../cross/src/android-emacs ../cross/lib-src/ctags \
+ ../cross/lib-src/hexl ../cross/lib-src/movemail \
+ ../cross/lib-src/ebrowse ../cross/lib-src/emacsclient
# Libraries to cross-compile.
-CROSS_LIBS = ../xcompile/src/libemacs.so
+CROSS_LIBS = ../cross/src/libemacs.so
+
+# Third party libraries to compile.
+include $(top_builddir)/cross/ndk-build/ndk-build.mk
.PHONY: $(CROSS_BINS) $(CROSS_LIBS)
-../xcompile/src/android-emacs ../xcompile/src/libemacs.so:
- make -C ../xcompile src/$(notdir $@)
+../cross/src/android-emacs ../cross/src/libemacs.so:
+ make -C ../cross src/$(notdir $@)
-../xcompile/lib-src/hexl ../xcompile/lib-src/movemail \
-../xcompile/lib-src/ctags ../xcompile/lib-src/ebrowse &:
- make -C ../xcompile lib-src/$(notdir $@)
+../cross/lib-src/hexl ../cross/lib-src/movemail \
+../cross/lib-src/ctags ../cross/lib-src/ebrowse &:
+ make -C ../cross lib-src/$(notdir $@)
# This is needed to generate the ``.directory-tree'' file used by the
# Android emulations of readdir and faccessat.
$(MAKE) -C $(libsrc) $(notdir $@)
emacs.apk-in: $(CROSS_BINS) $(CROSS_LIBS) $(libsrc)/asset-directory-tool \
- AndroidManifest.xml
+ AndroidManifest.xml $(NDK_BUILD_SHARED)
# Make the working directory for this stuff
rm -rf install_temp
mkdir -p install_temp/lib/$(ANDROID_ABI)
cp -f $$file install_temp/lib/$(ANDROID_ABI); \
fi \
done
+ $(foreach module,$(NDK_BUILD_SHARED), \
+ cp -f $(module) install_temp/lib/$(ANDROID_ABI))
# Package everything. Specifying the assets on this command line is
# necessary for AAssetManager_getNextFileName to work on old versions
# of Android.
- $(AAPT) package -I "$(ANDROID_JAR)" -F $@ -f -M AndroidManifest.xml \
- -A install_temp/assets
+ $(AAPT) package -I "$(ANDROID_JAR)" -F $@ -f \
+ -M AndroidManifest.xml -A install_temp/assets
pushd install_temp; $(AAPT) add ../$@ `find lib -type f`; popd
rm -rf install_temp
find . -name '*.class' -delete
maintainer-clean distclean bootstrap-clean: clean
+ rm -f Makefile ndk-build.mk
--- /dev/null
+/* Communication module for Android terminals. -*- c-file-style: "GNU" -*-
+
+Copyright (C) 2023 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 <https://www.gnu.org/licenses/>. */
+
+package org.gnu.emacs;
+
+import android.os.Build;
+
+/* This class provides helper code for accessing the clipboard,
+ abstracting between the different interfaces on API 8 and 11. */
+
+public abstract class EmacsClipboard
+{
+ public abstract void setClipboard (byte[] bytes);
+ public abstract int ownsClipboard ();
+ public abstract boolean clipboardExists ();
+ public abstract byte[] getClipboard ();
+
+ /* Create the correct kind of clipboard for this system. */
+
+ public static EmacsClipboard
+ makeClipboard ()
+ {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
+ return new EmacsSdk11Clipboard ();
+ else
+ return new EmacsSdk8Clipboard ();
+ }
+};
import android.os.Build;
+/* This code is mostly unused. See sfntfont-android.c for the code
+ that is actually used. */
+
public abstract class EmacsFontDriver
{
/* Font weights. */
/* Send an ANDROID_CONTEXT_MENU event. */
public static native long sendContextMenu (short window, int menuEventID);
+ /* Send an ANDROID_EXPOSE event. */
+ public static native long sendExpose (short window, int x, int y,
+ int width, int height);
+
static
{
System.loadLibrary ("emacs");
--- /dev/null
+/* Communication module for Android terminals. -*- c-file-style: "GNU" -*-
+
+Copyright (C) 2023 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 <https://www.gnu.org/licenses/>. */
+
+package org.gnu.emacs;
+
+import android.content.ClipboardManager;
+import android.content.Context;
+import android.content.ClipData;
+
+import android.util.Log;
+
+import java.io.UnsupportedEncodingException;
+
+/* This class implements EmacsClipboard for Android 3.0 and later
+ systems. */
+
+public class EmacsSdk11Clipboard extends EmacsClipboard
+ implements ClipboardManager.OnPrimaryClipChangedListener
+{
+ private static final String TAG = "EmacsSdk11Clipboard";
+ private ClipboardManager manager;
+ private boolean ownsClipboard;
+ private int clipboardChangedCount;
+ private int monitoredClipboardChangedCount;
+
+ public
+ EmacsSdk11Clipboard ()
+ {
+ String what;
+ Context context;
+
+ what = Context.CLIPBOARD_SERVICE;
+ context = EmacsService.SERVICE;
+ manager
+ = (ClipboardManager) context.getSystemService (what);
+ manager.addPrimaryClipChangedListener (this);
+ }
+
+ @Override
+ public synchronized void
+ onPrimaryClipChanged ()
+ {
+ Log.d (TAG, ("onPrimaryClipChanged: "
+ + monitoredClipboardChangedCount
+ + " " + clipboardChangedCount));
+
+ /* Increment monitoredClipboardChangeCount. If it is now greater
+ than clipboardChangedCount, then Emacs no longer owns the
+ clipboard. */
+ monitoredClipboardChangedCount++;
+
+ if (monitoredClipboardChangedCount > clipboardChangedCount)
+ {
+ ownsClipboard = false;
+
+ /* Reset both values back to 0. */
+ monitoredClipboardChangedCount = 0;
+ clipboardChangedCount = 0;
+ }
+ }
+
+ /* Set the clipboard text to CLIPBOARD, a string in UTF-8
+ encoding. */
+
+ @Override
+ public synchronized void
+ setClipboard (byte[] bytes)
+ {
+ ClipData data;
+ String string;
+
+ try
+ {
+ string = new String (bytes, "UTF-8");
+ data = ClipData.newPlainText ("Emacs", string);
+ manager.setPrimaryClip (data);
+ ownsClipboard = true;
+
+ /* onPrimaryClipChanged will be called again. Use this
+ variable to keep track of how many times the clipboard has
+ been changed. */
+ ++clipboardChangedCount;
+ }
+ catch (UnsupportedEncodingException exception)
+ {
+ Log.w (TAG, "setClipboard: " + exception);
+ }
+ }
+
+ /* Return whether or not Emacs owns the clipboard. Value is 1 if
+ Emacs does, 0 if Emacs does not, and -1 if that information is
+ unavailable. */
+
+ @Override
+ public synchronized int
+ ownsClipboard ()
+ {
+ return ownsClipboard ? 1 : 0;
+ }
+
+ /* Return whether or not clipboard content currently exists. */
+
+ @Override
+ public boolean
+ clipboardExists ()
+ {
+ return manager.hasPrimaryClip ();
+ }
+
+ /* Return the current content of the clipboard, as plain text, or
+ NULL if no content is available. */
+
+ @Override
+ public byte[]
+ getClipboard ()
+ {
+ ClipData clip;
+ CharSequence text;
+ Context context;
+
+ clip = manager.getPrimaryClip ();
+
+ if (clip == null || clip.getItemCount () < 1)
+ return null;
+
+ context = EmacsService.SERVICE;
+
+ try
+ {
+ text = clip.getItemAt (0).coerceToText (context);
+ return text.toString ().getBytes ("UTF-8");
+ }
+ catch (UnsupportedEncodingException exception)
+ {
+ Log.w (TAG, "getClipboard: " + exception);
+ }
+
+ return null;
+ }
+};
--- /dev/null
+/* Communication module for Android terminals. -*- c-file-style: "GNU" -*-
+
+Copyright (C) 2023 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 <https://www.gnu.org/licenses/>. */
+
+package org.gnu.emacs;
+
+/* Importing the entire package avoids the deprecation warning. */
+import android.text.*;
+
+import android.content.Context;
+import android.util.Log;
+
+import java.io.UnsupportedEncodingException;
+
+/* This class implements EmacsClipboard for Android 2.2 and other
+ similarly old systems. */
+
+@SuppressWarnings ("deprecation")
+public class EmacsSdk8Clipboard extends EmacsClipboard
+{
+ private static final String TAG = "EmacsSdk8Clipboard";
+ private ClipboardManager manager;
+
+ public
+ EmacsSdk8Clipboard ()
+ {
+ String what;
+ Context context;
+
+ what = Context.CLIPBOARD_SERVICE;
+ context = EmacsService.SERVICE;
+ manager
+ = (ClipboardManager) context.getSystemService (what);
+ }
+
+ /* Set the clipboard text to CLIPBOARD, a string in UTF-8
+ encoding. */
+
+ @Override
+ public void
+ setClipboard (byte[] bytes)
+ {
+ try
+ {
+ manager.setText (new String (bytes, "UTF-8"));
+ }
+ catch (UnsupportedEncodingException exception)
+ {
+ Log.w (TAG, "setClipboard: " + exception);
+ }
+ }
+
+ /* Return whether or not Emacs owns the clipboard. Value is 1 if
+ Emacs does, 0 if Emacs does not, and -1 if that information is
+ unavailable. */
+
+ @Override
+ public int
+ ownsClipboard ()
+ {
+ return -1;
+ }
+
+ /* Return whether or not clipboard content currently exists. */
+
+ @Override
+ public boolean
+ clipboardExists ()
+ {
+ return manager.hasText ();
+ }
+
+ /* Return the current content of the clipboard, as plain text, or
+ NULL if no content is available. */
+
+ @Override
+ public byte[]
+ getClipboard ()
+ {
+ String string;
+ CharSequence text;
+
+ text = manager.getText ();
+
+ if (text == null)
+ return null;
+
+ string = text.toString ();
+
+ try
+ {
+ return string.getBytes ("UTF-8");
+ }
+ catch (UnsupportedEncodingException exception)
+ {
+ Log.w (TAG, "getClipboard: " + exception);
+ }
+
+ return null;
+ }
+};
yet responded to. 0 if there is no such outstanding event. */
public long pendingConfigure;
+ /* Whether or not this view is attached to a window. */
+ public boolean isAttachedToWindow;
+
public
EmacsView (EmacsWindow window)
{
if (measuredWidth == 0 || measuredHeight == 0)
return;
+ if (!isAttachedToWindow)
+ return;
+
/* If bitmap is the same width and height as the measured width
and height, there is no need to do anything. Avoid allocating
the extra bitmap. */
public synchronized void
onDetachedFromWindow ()
{
+ isAttachedToWindow = false;
+
synchronized (this)
{
/* Recycle the bitmap and call GC. */
}
}
+ @Override
+ public synchronized void
+ onAttachedToWindow ()
+ {
+ isAttachedToWindow = true;
+
+ /* Dirty the bitmap, as it was destroyed when onDetachedFromWindow
+ was called. */
+ bitmapDirty = true;
+
+ /* Now expose the view contents again. */
+ EmacsNative.sendExpose (this.window.handle, 0, 0,
+ measuredWidth, measuredHeight);
+ }
+
public void
showOnScreenKeyboard ()
{
VPATH = @srcdir@
# This is not empty if this is a Makefile that will be copied to
-# xcompile/lib.
+# cross/lib.
XCONFIGURE = @XCONFIGURE@
# This is required to make sure symbol visibility is correct and
ifeq ($(XCONFIGURE),android)
# The next line is necessary to override -I$(srcdir), which will end
# up pulling in lots of headers from the host.
-ALL_CFLAGS += -I$(top_srcdir)/xcompile -I.
+ALL_CFLAGS += -I$(top_srcdir)/cross -I.
endif
DEPDIR = deps
;; arguments on.
(ignore))
+\f
+;;; Selection support.
+
+(declare-function android-clipboard-exists-p "androidselect.c")
+(declare-function android-get-clipboard "androidselect.c")
+(declare-function android-set-clipboard "androidselect.c")
+(declare-function android-clipboard-owner-p "androidselect.c")
+
+(defvar android-primary-selection nil
+ "The last string placed in the primary selection.
+Nil if there was no such string.
+
+Android does not have a primary selection of its own, so Emacs
+emulates one inside Lisp.")
+
+(defun android-get-clipboard-1 (data-type)
+ "Return the clipboard data.
+DATA-TYPE is a selection conversion target; only STRING and
+TARGETS are supported."
+ (or (and (eq data-type 'STRING)
+ (android-get-clipboard))
+ (and (eq data-type 'TARGETS)
+ (android-clipboard-exists-p)
+ [TARGETS STRING])))
+
+(defun android-get-primary (data-type)
+ "Return the last string placed in the primary selection, or nil.
+Return nil if DATA-TYPE is anything other than STRING or TARGETS."
+ (when android-primary-selection
+ (or (and (eq data-type 'STRING)
+ android-primary-selection)
+ (and (eq data-type 'TARGETS)
+ [TARGETS]))))
+
+(defun android-selection-bounds (value)
+ "Return bounds of selection value VALUE.
+The return value is a list (BEG END BUF) if VALUE is a cons of
+two markers or an overlay. Otherwise, it is nil."
+ (cond ((bufferp value)
+ (with-current-buffer value
+ (when (mark t)
+ (list (mark t) (point) value))))
+ ((and (consp value)
+ (markerp (car value))
+ (markerp (cdr value)))
+ (when (and (marker-buffer (car value))
+ (buffer-name (marker-buffer (car value)))
+ (eq (marker-buffer (car value))
+ (marker-buffer (cdr value))))
+ (list (marker-position (car value))
+ (marker-position (cdr value))
+ (marker-buffer (car value)))))
+ ((overlayp value)
+ (when (overlay-buffer value)
+ (list (overlay-start value)
+ (overlay-end value)
+ (overlay-buffer value))))))
+
+(defun android-encode-select-string (value)
+ "Turn VALUE into a string suitable for placing in the clipboard.
+VALUE should be something suitable for passing to
+`gui-set-selection'."
+ (unless (stringp value)
+ (when-let ((bounds (android-selection-bounds value)))
+ (setq value (ignore-errors
+ (with-current-buffer (nth 2 bounds)
+ (buffer-substring (nth 0 bounds)
+ (nth 1 bounds)))))))
+ value)
+
+(cl-defmethod gui-backend-get-selection (type data-type
+ &context (window-system android))
+ (cond ((eq type 'CLIPBOARD)
+ (android-get-clipboard-1 data-type))
+ ((eq type 'PRIMARY)
+ (android-get-primary data-type))))
+
+(cl-defmethod gui-backend-selection-exists-p (selection
+ &context (window-system android))
+ (cond ((eq selection 'CLIPBOARD)
+ (android-clipboard-exists-p))
+ ((eq selection 'PRIMARY)
+ (not (null android-primary-selection)))))
+
+(cl-defmethod gui-backend-selection-owner-p (selection
+ &context (window-system android))
+ (cond ((eq selection 'CLIPBOARD)
+ (let ((ownership (android-clipboard-owner-p)))
+ ;; If ownership is `lambda', then Emacs couldn't determine
+ ;; whether or not it owns the clipboard.
+ (and (not (eq ownership 'lambda)) ownership)))
+ ((eq selection 'PRIMARY)
+ ;; Emacs always owns its own primary selection as long as it
+ ;; exists.
+ (not (null android-primary-selection)))))
+
+(cl-defmethod gui-backend-set-selection (type value
+ &context (window-system android))
+ ;; First, try to turn value into a string.
+ ;; Don't set anything if that did not work.
+ (when-let ((string (android-encode-select-string value)))
+ (cond ((eq type 'CLIPBOARD)
+ (android-set-clipboard string))
+ ((eq type 'PRIMARY)
+ (setq android-primary-selection string)))))
+
(provide 'android-win)
;; android-win.el ends here.
--- /dev/null
+dnl Copyright (C) 2023 Free Software Foundation, Inc.
+dnl This file is part of GNU Emacs.
+
+dnl GNU Emacs is free software: you can redistribute it and/or modify
+dnl it under the terms of the GNU General Public License as published by
+dnl the Free Software Foundation, either version 3 of the License, or
+dnl (at your option) any later version.
+
+dnl GNU Emacs is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+dnl GNU General Public License for more details.
+
+dnl You should have received a copy of the GNU General Public License
+dnl along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+# Support for building Emacs with dependencies using the Android NDK
+# build system.
+
+AC_ARG_WITH([ndk_path],
+ [AS_HELP_STRING([--with-ndk-path],
+ [find Android libraries in these directories])])
+
+# ndk_INIT(ABI, API, DIR)
+# --------
+# Initialize the Android NDK. ABI is the ABI being built for.
+# API is the API version being built for.
+# As a side effect, set the variable ndk_INITIALIZED to true.
+# DIR should be a directory containing the Makefile.in actually
+# implementing the Android NDK build system.
+
+AC_DEFUN_ONCE([ndk_INIT],
+[
+# Look for Android.mk files.
+ndk_module_files=
+for file in $with_ndk_path; do
+ if test -f $file/Android.mk; then
+ ndk_module_files="$ndk_module_files$file/Android.mk "
+ fi
+done
+
+ndk_ABI=$1
+ndk_MODULES=
+ndk_MAKEFILES=
+ndk_INITIALIZED=yes
+ndk_API=$2
+ndk_DIR=$3
+
+case "$ndk_ABI" in
+ *arm64* )
+ ndk_ARCH=arm64
+ ;;
+ *arm* )
+ ndk_ARCH=arm
+ ;;
+ *x86_64* )
+ ndk_ARCH=x86_64
+ ;;
+ *x86* )
+ ndk_ARCH=x86
+ ;;
+ * )
+ AC_MSG_ERROR([Failed to determine Android device architecture])
+ ;;
+esac
+
+# This is a map between pkg-config style package names and Android
+# ones.
+
+ndk_package_map="libwebpdemux:webpdemux libxml-2.0:libxml2"
+
+# Replace ndk_module with the appropriate Android module name if it is
+# found in ndk_package_map.
+
+ndk_replace_pkg_config_package () {
+ for ndk_stuff in $ndk_package_map; do
+ ndk_key=${ndk_stuff%%:*}
+ ndk_value=${ndk_stuff#*:}
+
+ if test "$ndk_key" = "$ndk_module"; then
+ ndk_module="$ndk_value"
+ break
+ fi
+ done
+}
+
+# Parse a pkg-config style list of modules. Place the resulting list
+# in ndk_modules.
+
+ndk_parse_pkg_config_string () {
+ ndk_input=[$]1
+ ndk_modules=
+ while test -n "$ndk_input"; do
+ ndk_str=$(printf "$ndk_input" | cut -f1 -d' ')
+ ndk_input="$(printf "$ndk_input" | cut -s -f2- -d' ')"
+
+ if test "$ndk_str" = ">=" || test "$ndk_str" = "<=" \
+ || test "$ndk_str" = ">" || test "$ndk_str" = "<"; then
+ ndk_input="$(printf "$ndk_input" | cut -s -f2- -d' ')"
+ else
+ ndk_modules="$ndk_modules$ndk_str "
+ fi
+ done
+}
+
+# Look for a suitable ar in the same directory as the C compiler.
+ndk_where_cc=$(which $CC)
+ndk_ar_search_path=$PATH
+
+# First, try to find $host_alias-ar in PATH.
+AC_PATH_PROGS([AR], [$host_alias-ar], [], [$ndk_ar_search_path])
+
+if test -z "$AR"; then
+ # Next, try finding either that or llvm-ar in the directory holding
+ # CC.
+ ndk_ar_search_path="$(dirname $ndk_where_cc):$ndk_ar_search_path"
+ AC_PATH_PROGS([AR], [$host_alias-ar llvm-ar], [], [$ndk_ar_search_path])
+fi
+
+# These variables have now been found.
+])
+
+# ndk_SEARCH_MODULE(MODULE, NAME, ACTION-IF-FOUND, [ACTION-IF-NOT-FOUND])
+# --------------------------------------------------------------------
+# Search for a module named MODULE in `with_ndk_path'. Add the file
+# name of the module's Android.mk file to the variable ndk_MODULES.
+# Set NAME_CFLAGS and NAME_LIBS to the appropriate values. Then,
+# call ACTION-IF-FOUND, or ACTION-IF-NOT-FOUND upon failure.
+AC_DEFUN([ndk_SEARCH_MODULE],
+[
+module_name=
+ndk_module=$1
+ndk_replace_pkg_config_package
+AC_MSG_CHECKING([for Android.mk that builds $ndk_module])
+
+for ndk_android_mk in $ndk_module_files; do
+ # Read this Android.mk file. Set NDK_ROOT to /tmp: the Android in
+ # tree build system sets it to a meaning value, but build files just
+ # use it to test whether or not the NDK is being used.
+ ndk_commands=$(make -s -f build-aux/ndk-build-helper.mk EMACS_SRCDIR=. \
+ EMACS_ABI=$ndk_ABI ANDROID_MAKEFILE="$ndk_android_mk" \
+ ANDROID_MODULE_DIRECTORY=$(dirname "$ndk_android_mk") \
+ NDK_BUILD_DIR="$ndk_DIR" NDK_ROOT="/tmp" \
+ | awk -f build-aux/ndk-module-extract.awk \
+ MODULE="$ndk_module")
+
+ AS_IF([test -n "${ndk_commands//\n }"], [eval "$ndk_commands"])
+
+ if test -n "$module_name"; then
+ break
+ fi
+done
+
+if test -z "$module_name"; then
+ AC_MSG_RESULT([no])
+ $4
+else
+ $2[]_CFLAGS="[$]$2[]_CFLAGS $module_cflags $module_includes"
+ $2[]_LIBS="[$]$2[]_LIBS $module_ldflags"
+ ndk_MAKEFILES="$ndk_MAKEFILES $ndk_android_mk"
+ ndk_MODULES="$ndk_MODULES $module_target"
+ AC_MSG_RESULT([yes])
+ $3
+fi
+])
+
+# ndk_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],
+# [ACTION-IF-NOT-FOUND])
+# --------------------------------------------------------------
+# Just like `PKG_CHECK_MODULES'. However, it uses the ndk-build
+# system instead.
+
+AC_DEFUN([ndk_CHECK_MODULES],
+[
+ ndk_modules=
+ ndk_parse_pkg_config_string "$2"
+ ndk_found=no
+
+ for module in $ndk_modules; do
+ ndk_SEARCH_MODULE([$module], [$1], [ndk_found=yes], [ndk_found=no])
+ done
+
+ AS_IF([test "$ndk_found" = "yes"],[$3],[$4])
+])
+
+# ndk_CONFIG_FILES
+# -------------------------------------------------------------
+# Write out the NDK build Makefile with the appropriate variables
+# set if the NDK has been initialized.
+
+AC_DEFUN_ONCE([ndk_CONFIG_FILES],
+[
+ if test "$ndk_INITIALIZED" = "yes"; then
+ NDK_BUILD_ANDROID_MK="$ndk_MAKEFILES"
+ NDK_BUILD_ARCH=$ndk_ARCH
+ NDK_BUILD_ABI=$ndk_ABI
+ NDK_BUILD_SDK=$ndk_API
+ NDK_BUILD_CC=$CC
+ NDK_BUILD_AR=$AR
+ NDK_BUILD_MODULES="$ndk_MODULES"
+
+ AC_SUBST([NDK_BUILD_ANDROID_MK])
+ AC_SUBST([NDK_BUILD_ARCH])
+ AC_SUBST([NDK_BUILD_ABI])
+ AC_SUBST([NDK_BUILD_SDK])
+ AC_SUBST([NDK_BUILD_CC])
+ AC_SUBST([NDK_BUILD_AR])
+ AC_SUBST([NDK_BUILD_MODULES])
+
+ AC_CONFIG_FILES([$ndk_DIR/Makefile])
+ AC_CONFIG_FILES([$ndk_DIR/ndk-build.mk])
+ fi
+])
VPATH = $(srcdir)
# This is not empty if this is a Makefile that will be copied to
-# xcompile/src.
+# cross/src.
XCONFIGURE = @XCONFIGURE@
ifneq ($(XCONFIGURE),)
LIBIMAGE=@LIBTIFF@ @LIBJPEG@ @LIBPNG@ @LIBGIF@ @LIBXPM@ @WEBP_LIBS@
+GIF_CFLAGS=@GIF_CFLAGS@
+
XCB_LIBS=@XCB_LIBS@
XFT_LIBS=@XFT_LIBS@
XRENDER_LIBS=@XRENDER_LIBS@
ANDROID_OBJ = @ANDROID_OBJ@
ANDROID_LIBS = @ANDROID_LIBS@
+ANDROID_LDFLAGS = @ANDROID_LDFLAGS@
ANDROID_CFLAGS = @ANDROID_CFLAGS@
DUMPING=@DUMPING@
$(LIBSYSTEMD_CFLAGS) $(JSON_CFLAGS) $(XSYNC_CFLAGS) $(TREE_SITTER_CFLAGS) \
$(LIBGNUTLS_CFLAGS) $(NOTIFY_CFLAGS) $(CAIRO_CFLAGS) \
$(WERROR_CFLAGS) $(HAIKU_CFLAGS) $(XCOMPOSITE_CFLAGS) $(XSHAPE_CFLAGS) \
- $(ANDROID_CFLAGS)
+ $(ANDROID_CFLAGS) $(GIF_CFLAGS)
ALL_CFLAGS = $(EMACS_CFLAGS) $(WARN_CFLAGS) $(CFLAGS)
ALL_OBJC_CFLAGS = $(EMACS_CFLAGS) \
$(filter-out $(NON_OBJC_CFLAGS),$(WARN_CFLAGS)) $(CFLAGS) \
## is not dumped here. Instead, it dumps itself the first time it
## starts on the user's device.
+# Include ndk-build.mk in order to build Emacs dependencies.
+old_top_builddir := $(top_builddir)
+top_builddir := $(old_top_builddir)/..
+include $(old_top_builddir)/ndk-build/ndk-build.mk
+top_builddir := $(old_top_builddir)
+
libemacs.so: $(ALLOBJS) $(LIBEGNU_ARCHIVE) $(EMACSRES) \
- $(MAKE_PDUMPER_FINGERPRINT)
+ $(MAKE_PDUMPER_FINGERPRINT) $(NDK_BUILD_SHARED) \
+ $(NDK_BUILD_STATIC)
$(AM_V_CCLD)$(CC) -o $@ $(ALL_CFLAGS) $(TEMACS_LDFLAGS) \
- $(LDFLAGS) -shared $(ALLOBJS) $(LIBEGNU_ARCHIVE) $(LIBES)
+ $(ANDROID_LDFLAGS) $(LDFLAGS) -shared $(ALLOBJS) \
+ $(LIBEGNU_ARCHIVE) $(LIBES)
$(AM_V_at)$(MAKE_PDUMPER_FINGERPRINT) $@
# There is also a binary named `android-emacs' which simply calls
return fd;
}
+/* Read two bytes from FD and see if they are ``PK'', denoting ZIP
+ archive compressed data.
+
+ If they are not, rewind the file descriptor to offset 0.
+
+ If either operation fails, return -1 and close FD. Else, value is
+ FD. */
+
+static int
+android_check_compressed_file (int fd)
+{
+ char bytes[2];
+
+ if (read (fd, bytes, 2) != 2)
+ goto lseek_back;
+
+ if (bytes[0] != 'P' || bytes[1] != 'K')
+ goto lseek_back;
+
+ /* This could be compressed data! */
+ return -1;
+
+ lseek_back:
+ /* Seek back to offset 0. If this fails, return -1. */
+ if (lseek (fd, 0, SEEK_SET) != 0)
+ {
+ close (fd);
+ return -1;
+ }
+
+ return fd;
+}
+
/* `open' and such are modified even though they exist on Android,
because Emacs treats "/assets/" as a special directory that must
contain all assets in the application package. */
{
const char *name;
AAsset *asset;
- int fd;
+ int fd, oldfd;
off_t out_start, out_length;
bool fd_hacked;
return -1;
}
+ /* If given AASSET_MODE_BUFFER (which is what Emacs probably
+ does, given that a file descriptor is not always available),
+ the framework fails to uncompress the data before it returns
+ a file descriptor. */
asset = AAssetManager_open (asset_manager, name,
- AASSET_MODE_BUFFER);
+ AASSET_MODE_STREAMING);
if (!asset)
{
fd = AAsset_openFileDescriptor (asset, &out_start,
&out_length);
+ /* The platform sometimes returns a file descriptor to ZIP
+ compressed data. Detect that and fall back to creating a
+ shared memory file descriptor. */
+ fd = android_check_compressed_file (fd);
+
if (fd == -1)
{
/* The asset can't be accessed for some reason. Try to
which will close the original file descriptor. */
if (!fd_hacked)
- fd = fcntl (fd, F_DUPFD_CLOEXEC);
+ {
+ oldfd = fd;
+ fd = fcntl (oldfd, F_DUPFD_CLOEXEC);
+
+ /* Close the original file descriptor. */
+ close (oldfd);
+ }
if (fd >= ANDROID_MAX_ASSET_FD || fd < 0)
{
return event_serial;
}
+extern JNIEXPORT jlong JNICALL
+NATIVE_NAME (sendExpose) (JNIEnv *env, jobject object,
+ jshort window, jint x, jint y,
+ jint width, jint height)
+{
+ union android_event event;
+
+ event.xexpose.type = ANDROID_EXPOSE;
+ event.xexpose.serial = ++event_serial;
+ event.xexpose.window = window;
+ event.xexpose.x = x;
+ event.xexpose.y = y;
+ event.xexpose.width = width;
+ event.xexpose.height = height;
+
+ android_write_event (&event);
+ return event_serial;
+}
+
#ifdef __clang__
#pragma clang diagnostic pop
#else
dirent.d_ino = 0;
dirent.d_off = 0;
dirent.d_reclen = sizeof dirent;
- dirent.d_type = DT_UNKNOWN;
+
+ /* If this is not a directory, return DT_UNKNOWN. Otherwise,
+ return DT_DIR. */
+
+ if (android_is_directory (dir->asset_dir))
+ dirent.d_type = DT_DIR;
+ else
+ dirent.d_type = DT_UNKNOWN;
/* Note that dir->asset_dir is actually a NULL terminated
string. */
ANDROID_ICONIFIED,
ANDROID_DEICONIFIED,
ANDROID_CONTEXT_MENU,
+ ANDROID_EXPOSE,
};
struct android_any_event
unsigned int button;
};
+struct android_expose_event
+{
+ enum android_event_type type;
+ unsigned long serial;
+ android_window window;
+ int x, y;
+ int width, height;
+};
+
struct android_touch_event
{
/* Type of the event. */
struct android_crossing_event xcrossing;
struct android_motion_event xmotion;
struct android_button_event xbutton;
+ struct android_expose_event xexpose;
/* This has no parallel in X, since the X model of having
monotonically increasing touch IDs can't work on Android. */
--- /dev/null
+/* Communication module for Android terminals.
+
+Copyright (C) 2023 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 <https://www.gnu.org/licenses/>. */
+
+#include <config.h>
+#include <assert.h>
+
+#include "lisp.h"
+#include "blockinput.h"
+#include "coding.h"
+#include "android.h"
+#include "androidterm.h"
+
+/* Selection support on Android is confined to copying and pasting of
+ plain text from the clipboard. There is no primary selection.
+
+ While newer versions of Android are supposed to have the necessary
+ interfaces for transferring other kinds of selection data, doing so
+ is too complicated, and involves registering ``content providers''
+ and all kinds of other stuff. */
+
+\f
+
+/* Structure describing the EmacsClipboard class. */
+
+struct android_emacs_clipboard
+{
+ jclass class;
+ jmethodID set_clipboard;
+ jmethodID owns_clipboard;
+ jmethodID clipboard_exists;
+ jmethodID get_clipboard;
+ jmethodID make_clipboard;
+};
+
+/* Methods associated with the EmacsClipboard class. */
+static struct android_emacs_clipboard clipboard_class;
+
+/* Reference to the EmacsClipboard object. */
+static jobject clipboard;
+
+\f
+
+static void
+android_init_emacs_clipboard (void)
+{
+ jclass old;
+
+ clipboard_class.class
+ = (*android_java_env)->FindClass (android_java_env,
+ "org/gnu/emacs/EmacsClipboard");
+ eassert (clipboard_class.class);
+
+ old = clipboard_class.class;
+ clipboard_class.class
+ = (jclass) (*android_java_env)->NewGlobalRef (android_java_env,
+ old);
+ ANDROID_DELETE_LOCAL_REF (old);
+
+ if (!clipboard_class.class)
+ emacs_abort ();
+
+#define FIND_METHOD(c_name, name, signature) \
+ clipboard_class.c_name \
+ = (*android_java_env)->GetMethodID (android_java_env, \
+ clipboard_class.class, \
+ name, signature); \
+ assert (clipboard_class.c_name);
+
+ FIND_METHOD (set_clipboard, "setClipboard", "([B)V");
+ FIND_METHOD (owns_clipboard, "ownsClipboard", "()I");
+ FIND_METHOD (clipboard_exists, "clipboardExists", "()Z");
+ FIND_METHOD (get_clipboard, "getClipboard", "()[B");
+
+ clipboard_class.make_clipboard
+ = (*android_java_env)->GetStaticMethodID (android_java_env,
+ clipboard_class.class,
+ "makeClipboard",
+ "()Lorg/gnu/emacs/"
+ "EmacsClipboard;");
+ assert (clipboard_class.make_clipboard);
+
+#undef FIND_METHOD
+}
+
+
+\f
+
+DEFUN ("android-clipboard-owner-p", Fandroid_clipboard_owner_p,
+ Sandroid_clipboard_owner_p, 0, 0, 0,
+ doc: /* Return whether or not Emacs owns the clipboard.
+Alternatively, return the symbol `lambda' if that could not be
+determined. */)
+ (void)
+{
+ jint rc;
+
+ block_input ();
+ rc = (*android_java_env)->CallIntMethod (android_java_env,
+ clipboard,
+ clipboard_class.owns_clipboard);
+ android_exception_check ();
+ unblock_input ();
+
+ /* If rc is 0 or 1, then Emacs knows whether or not it owns the
+ clipboard. If rc is -1, then Emacs does not. */
+
+ if (rc < 0)
+ return Qlambda;
+
+ return rc ? Qt : Qnil;
+}
+
+DEFUN ("android-set-clipboard", Fandroid_set_clipboard,
+ Sandroid_set_clipboard, 1, 1, 0,
+ doc: /* Set the clipboard text to STRING. */)
+ (Lisp_Object string)
+{
+ jarray bytes;
+
+ CHECK_STRING (string);
+ string = ENCODE_UTF_8 (string);
+
+ bytes = (*android_java_env)->NewByteArray (android_java_env,
+ SBYTES (string));
+ android_exception_check ();
+
+ (*android_java_env)->SetByteArrayRegion (android_java_env, bytes,
+ 0, SBYTES (string),
+ (jbyte *) SDATA (string));
+ (*android_java_env)->CallVoidMethod (android_java_env,
+ clipboard,
+ clipboard_class.set_clipboard,
+ bytes);
+ android_exception_check ();
+
+ ANDROID_DELETE_LOCAL_REF (bytes);
+ return Qnil;
+}
+
+DEFUN ("android-get-clipboard", Fandroid_get_clipboard,
+ Sandroid_get_clipboard, 0, 0, 0,
+ doc: /* Return the current contents of the clipboard.
+Value is a multibyte string containing decoded clipboard
+text.
+Alternatively, return nil if the clipboard is empty. */)
+ (void)
+{
+ Lisp_Object string;
+ jarray bytes;
+ jmethodID method;
+ size_t length;
+ jbyte *data;
+
+ method = clipboard_class.get_clipboard;
+ bytes
+ = (*android_java_env)->CallObjectMethod (android_java_env,
+ clipboard,
+ method);
+
+ if (!bytes)
+ {
+ android_exception_check ();
+ return Qnil;
+ }
+
+ length = (*android_java_env)->GetArrayLength (android_java_env,
+ bytes);
+ data = (*android_java_env)->GetByteArrayElements (android_java_env,
+ bytes, NULL);
+ android_exception_check ();
+
+ string = make_unibyte_string ((char *) data, length);
+
+ (*android_java_env)->ReleaseByteArrayElements (android_java_env,
+ bytes, data,
+ JNI_ABORT);
+ ANDROID_DELETE_LOCAL_REF (bytes);
+
+ /* Now decode the resulting string. */
+ return code_convert_string_norecord (string, Qutf_8, Qnil);
+}
+
+DEFUN ("android-clipboard-exists-p", Fandroid_clipboard_exists_p,
+ Sandroid_clipboard_exists_p, 0, 0, 0,
+ doc: /* Return whether or not clipboard contents exist. */)
+ (void)
+{
+ jboolean rc;
+ jmethodID method;
+
+ method = clipboard_class.clipboard_exists;
+ rc = (*android_java_env)->CallBooleanMethod (android_java_env,
+ clipboard,
+ method);
+ android_exception_check ();
+
+ return rc ? Qt : Qnil;
+}
+
+\f
+
+void
+init_androidselect (void)
+{
+ jobject tem;
+ jmethodID make_clipboard;
+
+ android_init_emacs_clipboard ();
+
+ make_clipboard = clipboard_class.make_clipboard;
+ tem
+ = (*android_java_env)->CallStaticObjectMethod (android_java_env,
+ clipboard_class.class,
+ make_clipboard);
+ if (!tem)
+ emacs_abort ();
+
+ clipboard = (*android_java_env)->NewGlobalRef (android_java_env, tem);
+
+ if (!clipboard)
+ emacs_abort ();
+
+ ANDROID_DELETE_LOCAL_REF (tem);
+}
+
+void
+syms_of_androidselect (void)
+{
+ defsubr (&Sandroid_clipboard_owner_p);
+ defsubr (&Sandroid_set_clipboard);
+ defsubr (&Sandroid_get_clipboard);
+ defsubr (&Sandroid_clipboard_exists_p);
+}
goto OTHER;
+ case ANDROID_EXPOSE:
+
+ f = any;
+
+ if (f)
+ {
+ if (!FRAME_VISIBLE_P (f))
+ {
+ f->output_data.android->has_been_visible = true;
+ SET_FRAME_GARBAGED (f);
+ }
+
+ if (!FRAME_GARBAGED_P (f))
+ {
+ expose_frame (f, event->xexpose.x, event->xexpose.y,
+ event->xexpose.width, event->xexpose.height);
+ show_back_buffer (f);
+ }
+ }
+
+ goto OTHER;
+
case ANDROID_BUTTON_PRESS:
case ANDROID_BUTTON_RELEASE:
/* If we decide we want to generate an event to be seen
extern void init_sfntfont_android (void);
extern void syms_of_sfntfont_android (void);
+/* Defined in androidselect.c */
+
+#ifndef ANDROID_STUBIFY
+
+extern void init_androidselect (void);
+extern void syms_of_androidselect (void);
+
+#endif
+
\f
#define RGB_TO_ULONG(r, g, b) (((r) << 16) | ((g) << 8) | (b))
syms_of_fontset ();
#if !defined ANDROID_STUBIFY
syms_of_androidfont ();
+ syms_of_androidselect ();
syms_of_sfntfont ();
syms_of_sfntfont_android ();
#endif /* !ANDROID_STUBIFY */
#if defined HAVE_ANDROID && !defined ANDROID_STUBIFY
init_androidfont ();
+ init_androidselect ();
init_sfntfont ();
init_sfntfont_android ();
#endif