emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

feature/android 4255d7f051 5/5: Update Android port


From: Po Lu
Subject: feature/android 4255d7f051 5/5: Update Android port
Date: Thu, 26 Jan 2023 02:37:44 -0500 (EST)

branch: feature/android
commit 4255d7f0514c5fa1badded6b0bc445ec2d2764c0
Author: Po Lu <luangruo@yahoo.com>
Commit: Po Lu <luangruo@yahoo.com>

    Update Android port
    
    * .gitignore: Ignore lib/math.h.
    * INSTALL.android: Update accordingly.
    * build-aux/ndk-build-helper-1.mk:
    * build-aux/ndk-build-helper-2.mk:
    * build-aux/ndk-build-helper.mk:
    * build-aux/ndk-module-extract.awk: Handle C++ modules.
    * configure.ac: Enable libxml2 on Android.
    
    * cross/ndk-build/Makefile.in:
    * cross/ndk-build/ndk-build-shared-library.mk:
    * cross/ndk-build/ndk-build-static-library.mk:
    * cross/ndk-build/ndk-build.mk.in:
    * cross/ndk-build/ndk-resolve.mk: Fix dependency resolution of
    includes.
    
    * java/org/gnu/emacs/EmacsView.java (popupMenu): Fix minimum SDK
    version for actual popup menus.
    * lib/math.h: Delete file.
    
    * m4/ndk-build.m4 (ndk_SEARCH_MODULE, ndk_CHECK_MODULES): Look
    for nasm and C++ libraries.
    
    * src/android.c (faccessat): Rename to `android_faccessat'.
    * src/android.h: Update prototypes.
    * src/dired.c (file_name_completion_dirp):
    * src/fileio.c (file_access_p, Faccess_file, file_directory_p):
    * src/lisp.h:
    * src/lread.c (openp):
    * src/process.c (allocate_pty): Use sys_faccessat.
    * src/sysdep.c (sys_faccessat): New function.
---
 .gitignore                                  |   2 +
 INSTALL.android                             | 127 +++++++++++++++++++-
 build-aux/ndk-build-helper-1.mk             |  31 +++--
 build-aux/ndk-build-helper-2.mk             |  22 +++-
 build-aux/ndk-build-helper.mk               |  35 +++++-
 build-aux/ndk-module-extract.awk            |  30 ++++-
 configure.ac                                |  26 +++-
 cross/ndk-build/Makefile.in                 |  29 ++++-
 cross/ndk-build/ndk-build-shared-library.mk |  37 +++++-
 cross/ndk-build/ndk-build-static-library.mk |  30 +++++
 cross/ndk-build/ndk-build.mk.in             |  18 +++
 cross/ndk-build/ndk-resolve.mk              |  31 ++++-
 java/org/gnu/emacs/EmacsView.java           |   5 +-
 m4/ndk-build.m4                             | 180 +++++++++++++++++++++++++++-
 src/android.c                               |  24 ++--
 src/android.h                               |   1 +
 src/dired.c                                 |   3 +-
 src/fileio.c                                |   8 +-
 src/lisp.h                                  |   1 +
 src/lread.c                                 |   6 +-
 src/process.c                               |   3 +-
 src/sysdep.c                                |  10 ++
 22 files changed, 598 insertions(+), 61 deletions(-)

diff --git a/.gitignore b/.gitignore
index 6b624767c6..6ca011312e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -84,6 +84,7 @@ lib/limits.h
 lib/malloc/*.gl.h
 lib/signal.h
 lib/std*.h
+lib/math.h
 !lib/std*.in.h
 !lib/stdio-impl.h
 lib/string.h
@@ -115,6 +116,7 @@ cross/lib/signal.h
 cross/lib/std*.h
 !cross/lib/std*.in.h
 !cross/lib/stdio-impl.h
+cross/lib/math.h
 cross/lib/string.h
 cross/lib/sys/
 cross/lib/time.h
diff --git a/INSTALL.android b/INSTALL.android
index 975a6249bb..ed0bd0f68d 100644
--- a/INSTALL.android
+++ b/INSTALL.android
@@ -135,9 +135,19 @@ files, like so:
 
   ./configure "--with-ndk-path=directory1 directory2"
 
+If `configure' complains about not being able to find
+``libc++_shared.so'', then you must locate that file in your copy of
+the NDK, and specify it like so:
+
+  ./configure --with-ndk-cxx-shared=/path/to/sysroot/libc++_shared.so
+
 Emacs will then read the ``Android.mk'' file in each directory, and
 automatically build and use those modules.
 
+When building for Intel systems, some ``ndk-build'' modules require
+the Netwide Assembler, usually installed under ``nasm'', to be present
+on the system that is building Emacs.
+
 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, along with what has to be patched to make them work:
@@ -150,6 +160,16 @@ work, along with what has to be patched to make them work:
   libjpeg-turbo - 
https://android.googlesource.com/platform/external/libjpeg-turbo
      (You must add LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH) before
       its Android.mk includes $(BUILD_SHARED_LIBRARY))
+  libxml2      - https://android.googlesource.com/platform/external/libxml2/
+     (You must also place the dependency icu4c in ``--with-ndk-path'',
+      and apply the patch at the end of this file.)
+  icu4c                - 
https://android.googlesource.com/platform/external/icu/
+     (You must apply the patch at the end of this file.)
+
+Many of these dependencies have been migrated over to the
+``Android.bp'' build system now used to build Android itself.
+However, the old ``Android.mk'' Makefiles are still present in older
+branches, and can be easily adapte to newer versions.
 
 In addition, some Emacs dependencies provide `ndk-build' support
 themselves:
@@ -259,10 +279,11 @@ most important of these are:
   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).
+Then, ``Android.mk'' will include $(CLEAN_VARS), possibly other
+``Android.mk'' files, (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
@@ -300,6 +321,11 @@ The output is arranged as follows:
     that will build the final shared object or library archive of this
     module, along with all of its dependencies.
 
+  - The seventh line is either empty, or the name of a dependency on
+    the C++ standard library.  This is used to determine whether or
+    not Emacs will include the C++ standard library in the application
+    package.
+
 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:
@@ -315,6 +341,8 @@ 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"
+module_cxx_deps=""
+module_imports=""
 
 which is then evaluated by `configure'.         Once the variable
 `module_name' is set, configure apends the remaining
@@ -322,6 +350,37 @@ $(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.
 
+In some cases, an ``Android.mk'' file may chose to import a module
+defined in ``--with-ndk-path'', but not defined inside its own
+``Android.mk'' file.  build-aux/ndk-build-helper.mk defines the
+`import-module' function to add the modules being imported to a
+variable, which is then printed out after ``ndk-build-helper.mk''
+completes.  For example, libxml2 imports the ``libicucc'' module,
+which results in the following text being printed:
+
+Building shared
+libxml2
+/home/oldosfan/libxml2/SAX.c /home/oldosfan/libxml2/entities.c 
/home/oldosfan/libxml2/encoding.c /home/oldosfan/libxml2/error.c 
/home/oldosfan/libxml2/parserInternals.c /home/oldosfan/libxml2/parser.c 
/home/oldosfan/libxml2/tree.c /home/oldosfan/libxml2/hash.c 
/home/oldosfan/libxml2/list.c /home/oldosfan/libxml2/xmlIO.c 
/home/oldosfan/libxml2/xmlmemory.c /home/oldosfan/libxml2/uri.c 
/home/oldosfan/libxml2/valid.c /home/oldosfan/libxml2/xlink.c 
/home/oldosfan/libxml2/debugXML.c /home/oldo [...]
+
+
+  -L/home/oldosfan/emacs-dev/emacs-android/cross/ndk-build -l:libxml2_emacs.so 
-l:libicuuc_emacs.so
+libxml2_emacs.so libicuuc_emacs.so
+End
+Start Imports
+libicuuc
+End Imports
+
+Upon encountering the ``Start Imports'' section,
+build-aux/ndk-module-extract.awk collects all imports until it
+encounters the line ``End Imports'', at which point it prints:
+
+module_imports="libicuuc"
+
+Then, if the list of imports is not empty, ndk_CHECK_MODULES
+additionally calls itself for each import before appending the
+module's own ``Android.mk'', ensuring that the module's imported
+dependencies are included by $ndk_DIR/Makefile before itself.
+
 Finally, immediately before generating src/Makefile.android, configure
 expands:
 
@@ -473,3 +532,63 @@ 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/>.
+
+
+
+PATCH FOR LIBXML2
+
+This patch must be applied to the Android.mk in Google's version of
+libxml2 before it can be built for Emacs.  In addition, you must also
+revert the commit `edb5870767fed8712a9b77ef34097209b61ab2db'.
+
+diff --git a/Android.mk b/Android.mk
+index 07c7b372..24f67e49 100644
+--- a/Android.mk
++++ b/Android.mk
+@@ -80,6 +80,7 @@ LOCAL_SHARED_LIBRARIES := libicuuc
+ LOCAL_MODULE:= libxml2
+ LOCAL_CLANG := true
+ LOCAL_ADDITIONAL_DEPENDENCIES += $(LOCAL_PATH)/Android.mk
++LOCAL_EXPORT_C_INCLUDES += $(LOCAL_PATH)
+ include $(BUILD_SHARED_LIBRARY)
+ 
+ # For the host
+@@ -94,3 +95,5 @@ LOCAL_MODULE := libxml2
+ LOCAL_CLANG := true
+ LOCAL_ADDITIONAL_DEPENDENCIES += $(LOCAL_PATH)/Android.mk
+ include $(BUILD_HOST_STATIC_LIBRARY)
++
++$(call import-module,libicuuc)
+
+PATCH FOR ICU
+
+This patch must be applied to icu4j/Android.mk in Google's version of
+icu before it can be built for Emacs.
+
+diff --git a/icu4j/Android.mk b/icu4j/Android.mk
+index d1ab3d5..69eff81 100644
+--- a/icu4j/Android.mk
++++ b/icu4j/Android.mk
+@@ -69,7 +69,7 @@ include $(BUILD_STATIC_JAVA_LIBRARY)
+ # Path to the ICU4C data files in the Android device file system:
+ icu4c_data := /system/usr/icu
+ icu4j_config_root := $(LOCAL_PATH)/main/classes/core/src
+-include external/icu/icu4j/adjust_icudt_path.mk
++include $(LOCAL_PATH)/adjust_icudt_path.mk
+ 
+ include $(CLEAR_VARS)
+ LOCAL_SRC_FILES := $(icu4j_src_files)
+
+diff --git a/icu4c/source/common/Android.mk b/icu4c/source/common/Android.mk
+index 8e5f757..44bb130 100644
+--- a/icu4c/source/common/Android.mk
++++ b/icu4c/source/common/Android.mk
+@@ -231,7 +231,7 @@ include $(CLEAR_VARS)
+ LOCAL_SRC_FILES += $(src_files)
+ LOCAL_C_INCLUDES += $(c_includes) $(optional_android_logging_includes)
+ LOCAL_CFLAGS += $(local_cflags) -DPIC -fPIC
+-LOCAL_SHARED_LIBRARIES += libdl $(optional_android_logging_libraries)
++LOCAL_SHARED_LIBRARIES += libdl libstdc++ 
$(optional_android_logging_libraries)
+ LOCAL_MODULE_TAGS := optional
+ LOCAL_MODULE := libicuuc
+ LOCAL_RTTI_FLAG := -frtti
diff --git a/build-aux/ndk-build-helper-1.mk b/build-aux/ndk-build-helper-1.mk
index 86e3ebd655..4ffe0d423e 100644
--- a/build-aux/ndk-build-helper-1.mk
+++ b/build-aux/ndk-build-helper-1.mk
@@ -30,13 +30,12 @@ NDK_A_NAMES =
 # 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)
+NDK_$(LOCAL_MODULE)_EXPORT_INCLUDES := $(LOCAL_EXPORT_C_INCLUDE_DIRS) 
$(LOCAL_EXPORT_C_INCLUDES)
 
 $(info Building $(build_kind))
 $(info $(LOCAL_MODULE))
-$(info $(addprefix $(ANDROID_MODULE_DIRECTORY)/,$(LOCAL_SRC_FILES) 
$(LOCAL_SRC_FILES$(EMACS_ABI))))
+$(info $(addprefix $(LOCAL_PATH)/,$(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
@@ -62,15 +61,31 @@ $$(foreach module,$$(filter-out $$(SYSTEM_LIBRARIES), 
$$(NDK_$(1)_SHARED_LIBRARI
 endif
 endef
 
-# Resolve additional dependencies based on LOCAL_STATIC_LIBRARIES and
-# LOCAL_SHARED_LIBRARIES.  Static library dependencies can be ignored
-# while building a shared library, as they will be linked in to the
-# resulting shared object file later.
+# Figure out includes from dependencies as well.
+NDK_INCLUDES := $(LOCAL_EXPORT_C_INCLUDE_DIRS) $(LOCAL_EXPORT_C_INCLUDES)
+
+define add-includes
+ifeq ($$(findstring $$(NDK_$(1)_EXPORT_INCLUDES),$$(NDK_INCLUDES)),)
+NDK_INCLUDES += $$(NDK_$(1)_EXPORT_INCLUDES)
+
+$$(foreach module,$$(filter-out $$(SYSTEM_LIBRARIES), 
$$(NDK_$(1)_SHARED_LIBRARIES)) $$(NDK_$(1)_STATIC_LIBRARIES),$$(eval $$(call 
add-includes,$$(module))))
+endif
+endef
+
+# Resolve additional dependencies and their export includes based on
+# LOCAL_STATIC_LIBRARIES and LOCAL_SHARED_LIBRARIES.  Static library
+# dependencies can be ignored while building a shared library, as they
+# will be linked in to the resulting shared object file later.
 
-SYSTEM_LIBRARIES = z libz libc c
+SYSTEM_LIBRARIES = z libz libc c libdl dl stdc++ libstdc++
 
 $(foreach module,$(filter-out $(SYSTEM_LIBRARIES), 
$(LOCAL_SHARED_LIBRARIES)),$(eval $(call add-so-name,$(module))))
+$(foreach module,$(filter-out $(SYSTEM_LIBRARIES), $(LOCAL_SHARED_LIBRARIES) 
$(LOCAL_STATIC_LIBRARIES) $(LOCAL_WHOLE_LIBRARIES)),$(eval $(call 
add-includes,$(module))))
+
+$(info $(foreach dir,$(NDK_INCLUDES),-I$(dir)))
+$(info $(LOCAL_EXPORT_CFLAGS))
 
 $(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 $(filter %stdc++,$(LOCAL_SHARED_LIBRARIES)))
 $(info End)
diff --git a/build-aux/ndk-build-helper-2.mk b/build-aux/ndk-build-helper-2.mk
index bd50e8b3ef..9c9e7cf09a 100644
--- a/build-aux/ndk-build-helper-2.mk
+++ b/build-aux/ndk-build-helper-2.mk
@@ -24,13 +24,12 @@ NDK_A_NAMES =
 # 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)
+NDK_$(LOCAL_MODULE)_EXPORT_INCLUDES := $(LOCAL_EXPORT_C_INCLUDE_DIRS) 
$(LOCAL_EXPORT_C_INCLUDES)
 
 $(info Building $(build_kind))
 $(info $(LOCAL_MODULE))
-$(info $(addprefix $(ANDROID_MODULE_DIRECTORY)/,$(LOCAL_SRC_FILES) 
$(LOCAL_SRC_FILES$(EMACS_ABI))))
+$(info $(addprefix $(LOCAL_PATH)/,$(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)
@@ -74,14 +73,29 @@ $$(foreach module,$$(filter-out $$(SYSTEM_LIBRARIES), 
$$(NDK_$(1)_SHARED_LIBRARI
 endif
 endef
 
+# Figure out includes from dependencies as well.
+NDK_INCLUDES := $(LOCAL_EXPORT_C_INCLUDE_DIRS) $(LOCAL_EXPORT_C_INCLUDES)
+
+define add-includes
+ifeq ($$(findstring $$(NDK_$(1)_EXPORT_INCLUDES),$$(NDK_INCLUDES)),)
+NDK_INCLUDES += $$(NDK_$(1)_EXPORT_INCLUDES)
+
+$$(foreach module,$$(filter-out $$(SYSTEM_LIBRARIES), 
$$(NDK_$(1)_SHARED_LIBRARIES)) $$(NDK_$(1)_STATIC_LIBRARIES),$$(eval $$(call 
add-includes,$$(module))))
+endif
+endef
+
 # Resolve additional dependencies based on LOCAL_STATIC_LIBRARIES and
 # LOCAL_SHARED_LIBRARIES.
 
-SYSTEM_LIBRARIES = z libz
+SYSTEM_LIBRARIES = z libz libc c libdl dl libstdc++ stdc++
 
 $(foreach module,$(filter-out $(SYSTEM_LIBRARIES), $(LOCAL_STATIC_LIBRARIES) 
$(LOCAL_WHOLE_STATIC_LIBRARIES)),$(eval $(call add-a-name,$(module))))
 $(foreach module,$(filter-out $(SYSTEM_LIBRARIES), 
$(LOCAL_SHARED_LIBRARIES)),$(eval $(call add-so-name,$(module))))
+$(foreach module,$(filter-out $(SYSTEM_LIBRARIES), $(LOCAL_SHARED_LIBRARIES) 
$(LOCAL_STATIC_LIBRARIES) $(LOCAL_WHOLE_LIBRARIES)),$(eval $(call 
add-includes,$(module))))
 
+$(info $(foreach dir,$(NDK_INCLUDES),-I$(dir)))
+$(info $(LOCAL_EXPORT_CFLAGS))
 $(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 $(filter %stdc++,$(LOCAL_SHARED_LIBRARIES)))
 $(info End)
diff --git a/build-aux/ndk-build-helper.mk b/build-aux/ndk-build-helper.mk
index beb32cae3f..886459b137 100644
--- a/build-aux/ndk-build-helper.mk
+++ b/build-aux/ndk-build-helper.mk
@@ -21,20 +21,38 @@
 # See the text under ``NDK BUILD SYSTEM IMPLEMENTATION'' in
 # INSTALL.android for more details.
 
+# NDK_LAST_MAKEFILE is the last Makefile that was included.
+NDK_LAST_MAKEFILE = $(lastword $(filter %Android.mk,$(MAKEFILE_LIST)))
+
+# local-makefile is the current Makefile being loaded.
+local-makefile = $(NDK_LAST_MAKEFILE)
+
 # 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)
+# Make EMACS_SRCDIR absolute.  This must be absolute, or nested
+# Android.mk files will not be able to find CLEAR_VARS.
+EMACS_SRCDIR := $(absname $(EMACS_SRCDIR))
+
+# my-dir is a function that returns the Android module directory.  If
+# no Android.mk has been loaded, use ANDROID_MODULE_DIRECTORY.
+my-dir = $(or $(and $(local-makefile),$(dir 
$(local-makefile))),$(ANDROID_MODULE_DIRECTORY))
+
+# Return all Android.mk files under the first arg.
+all-makefiles-under = $(wildcard $(1)/*/Android.mk)
 
-# all-subdir-makefiles is a function which returns all Android.mk
-# files within this directory.
-all-subdir-makefiles = $(shell find . -name "Android.mk")
+# Return all Android.mk files in subdirectories of this Makefile's
+# location.
+all-subdir-makefiles = $(call all-makefiles-under,$(call my-dir))
 
 # These functions are not implemented.
 parent-makefile =
 grand-parent-makefile =
-import-module =
+
+NDK_IMPORTS :=
+
+# Add the specified module (arg 1) to NDK_IMPORTS.
+import-module = $(eval NDK_IMPORTS += $(1))
 
 # Print out module information every time BUILD_SHARED_LIBRARY is
 # called.
@@ -48,5 +66,10 @@ CLEAR_VARS=$(EMACS_SRCDIR)/build-aux/ndk-build-helper-4.mk
 
 include $(ANDROID_MAKEFILE)
 
+# Finally, print out the imports.
+$(info Start Imports)
+$(info $(NDK_IMPORTS))
+$(info End Imports)
+
 # Dummy target.
 all:
diff --git a/build-aux/ndk-module-extract.awk b/build-aux/ndk-module-extract.awk
index eaea3e96dd..681f20237f 100644
--- a/build-aux/ndk-module-extract.awk
+++ b/build-aux/ndk-module-extract.awk
@@ -2,13 +2,27 @@
   kind = $2
 }
 
+/^Start Imports$/ {
+  imports = 1
+}
+
 // {
-  if (!match ($0, /^End$/) && !match ($0, /^Building.+$/))
+  if (imports && ++imports > 2)
+    {
+      if (!match ($0, /^End Imports$/))
+       makefile_imports = makefile_imports " " $1
+    }
+  else if (!match ($0, /^End$/) && !match ($0, /^Building.+$/))
     {
       if (kind)
        {
-         if (ldflags_found)
-           target = $0
+         if (target_found)
+           cxx_deps = $0
+         else if (ldflags_found)
+           {
+             target = $0
+             target_found = 1
+           }
          else if (cflags_found)
            {
              ldflags = $0
@@ -48,6 +62,7 @@
       printf "module_cflags=\"%s\"\n", cflags
       printf "module_ldflags=\"%s\"\n", ldflags
       printf "module_target=\"%s\"\n", target
+      printf "module_cxx_deps=\"%s\"\n", cxx_deps
     }
 
   src = ""
@@ -61,4 +76,13 @@
   includes_found = ""
   cflags_found = ""
   ldflags_found = ""
+  target_found = ""
+}
+
+/^End Imports$/ {
+  imports = ""
+  # Strip off leading whitespace.
+  gsub (/^[ \t]+/, "", makefile_imports)
+  printf "module_imports=\"%s\"\n", makefile_imports
+  makefile_imports = ""
 }
diff --git a/configure.ac b/configure.ac
index 983fa3ebab..95bb0cfca8 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1041,12 +1041,16 @@ package will likely install on older systems but crash 
on startup.])
   mv -f confdefs.h _confdefs.h
   mv -f config.log _config.log
 
+  # Make sure these files are removed upon exit.
+  trap "rm -rf _confdefs.h _config.log" 0
+
   # 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"
   passthrough="$passthrough --with-json=$with_json"
   passthrough="$passthrough --with-jpeg=$with_jpeg"
+  passthrough="$passthrough --with-xml2=$with_xml2"
 
   AS_IF([XCONFIGURE=android ANDROID_CC="$ANDROID_CC" \
          ANDROID_SDK="$android_sdk" android_abi=$android_abi \
@@ -1115,9 +1119,9 @@ if test "$ANDROID" = "yes"; then
     with_gif=no
     with_json=no
     with_jpeg=no
+    with_xml2=no
   fi
 
-  with_xml2=no
   with_rsvg=no
   with_sqlite3=no
   with_lcms2=no
@@ -2256,6 +2260,18 @@ AC_DEFUN([EMACS_CHECK_MODULES],
         m4_default([$3], [HAVE_$1=yes])],
        [m4_default([$4], [HAVE_$1=no])])])])
 
+dnl EMACS_CHECK_LIB(NAME, FUNCTION, ACTION-IF-FOUND, ACTION-IF-NOT-FOUND,
+dnl OTHER-LIBRARIES, INCLUDES)
+dnl ---------------------------------------------------------------------
+dnl This is like AC_CHECK_LIB; however, there is no default action, and
+dnl when cross-configuring for Android, AC_CHECK_DECLS is called with NAME
+dnl and INCLUDES instead, as the library being checked against will likely
+dnl be built together with Emacs.
+AC_DEFUN([EMACS_CHECK_LIB],
+  [AS_IF([test -n "$ndk_INITIALIZED"],
+    [AC_CHECK_DECL([$2], [$3], [$4], [$6])],
+    [AC_CHECK_LIB([$1], [$2], [$3], [$4], [$5])])])
+
 HAVE_SOUND=no
 if test "${with_sound}" != "no"; then
   # Sound support for GNU/Linux, the free BSDs, MinGW, and Cygwin.
@@ -3323,7 +3339,6 @@ if test "${with_webp}" != "no"; then
    fi
    if test $HAVE_WEBP = yes; then
       AC_DEFINE([HAVE_WEBP], [1], [Define to 1 if using libwebp.])
-      CFLAGS="$CFLAGS $WEBP_CFLAGS"
       # Windows loads libwebp dynamically
       if test "${opsys}" = "mingw32"; then
        WEBP_LIBS=
@@ -5400,10 +5415,13 @@ if test "${with_xml2}" != "no"; then
   fi
   if test "${HAVE_LIBXML2}" = "yes"; then
     if test "${opsys}" != "mingw32"; then
-      AC_CHECK_LIB([xml2], [htmlReadMemory],
+      SAVE_CFLAGS=$CFLAGS
+      CFLAGS="$CFLAGS $LIBXML2_CFLAGS"
+      EMACS_CHECK_LIB([xml2], [htmlReadMemory],
        [HAVE_LIBXML2=yes],
        [HAVE_LIBXML2=no],
-        [$LIBXML2_LIBS])
+        [$LIBXML2_LIBS], [#include <libxml/HTMLparser.h>])
+      CFLAGS="$SAVE_CFLAGS"
     else
       LIBXML2_LIBS=""
     fi
diff --git a/cross/ndk-build/Makefile.in b/cross/ndk-build/Makefile.in
index ec8e620568..125c825e50 100644
--- a/cross/ndk-build/Makefile.in
+++ b/cross/ndk-build/Makefile.in
@@ -30,6 +30,7 @@ NDK_BUILD_ANDROID_MK = @NDK_BUILD_ANDROID_MK@
        NDK_BUILD_SDK = @NDK_BUILD_SDK@
         NDK_BUILD_CC = @NDK_BUILD_CC@
         NDK_BUILD_AR = @NDK_BUILD_AR@
+      NDK_BUILD_NASM = @NDK_BUILD_NASM@
 
 # This is a list of targets to build.
    NDK_BUILD_MODULES = @NDK_BUILD_MODULES@
@@ -49,13 +50,33 @@ endef
 # Remove duplicate files.
 NDK_BUILD_ANDROID_MK := $(call uniqify,$(NDK_BUILD_ANDROID_MK))
 
+# Remove duplicate modules as well.  These can occur when a single
+# module imports a module and also declares it in
+# LOCAL_SHARED_LIBRARIES.
+NDK_BUILD_MODULES := $(call uniqify,$(NDK_BUILD_MODULES))
+
 define subr-1
 
-# Define ndk-build functions.
+# Define ndk-build functions.  Many of these are identical to those in
+# build-aux/ndk-build-helper.mk.
 
-define my-dir
-$(dir $(abspath $(1)))
-endef
+# NDK_LAST_MAKEFILE is the last Makefile that was included.
+NDK_LAST_MAKEFILE = $$(lastword $$(filter %Android.mk,$$(MAKEFILE_LIST)))
+
+# local-makefile is the current Makefile being loaded.
+local-makefile = $$(NDK_LAST_MAKEFILE)
+
+# my-dir is a function that returns the Android module directory.  If
+# no Android.mk has been loaded, use the directory of the Makefile
+# being included.
+my-dir = $$(or $$(and $$(local-makefile),$$(dir $$(local-makefile))),$(dir 
$(1)))
+
+# Return all Android.mk files under the first arg.
+all-makefiles-under = $$(wildcard $$(1)/*/Android.mk)
+
+# Return all Android.mk files in subdirectories of this Makefile's
+# location.
+all-subdir-makefiles = $$(call all-makefiles-under,$$(call my-dir))
 
 # NDK-defined include variables.
 
diff --git a/cross/ndk-build/ndk-build-shared-library.mk 
b/cross/ndk-build/ndk-build-shared-library.mk
index 6a607049a9..a4b7b47f74 100644
--- a/cross/ndk-build/ndk-build-shared-library.mk
+++ b/cross/ndk-build/ndk-build-shared-library.mk
@@ -22,6 +22,9 @@
 eq = $(and $(findstring $(1),$(2)),$(findstring $(2),$(1)))
 objname = $(1)-$(subst /,_,$(2).o)
 
+# Here are the default flags to link shared libraries with.
+NDK_SO_DEFAULT_LDFLAGS := -lc -lm
+
 define single-object-target
 
 ifeq (x$(suffix $(1)),x.c)
@@ -29,6 +32,12 @@ 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
+ifeq (x$(suffix $(1)),x.$(or $(LOCAL_CPP_EXTENSION),cpp))
+
+$(call objname,$(LOCAL_MODULE),$(basename $(1))): $(LOCAL_PATH)/$(1)
+       $(NDK_BUILD_CC) -c $$< -o $$@ $(NDK_CFLAGS_$(LOCAL_MODULE)) 
$(NDK_CXXFLAGS_$(LOCAL_MODULE))
+
 else
 ifneq ($(or $(call eq,x$(suffix $(1)),x.s),$(call eq,x$(suffix $(1)),x.S)),)
 
@@ -36,7 +45,19 @@ $(call objname,$(LOCAL_MODULE),$(basename $(1))): 
$(LOCAL_PATH)/$(1)
        $(NDK_BUILD_CC) -c $$< -o $$@ $(NDK_ASFLAGS_$(LOCAL_MODULE))
 
 else
+ifneq (x$(suffix $(1)),x.asm)
 $$(error Unsupported suffix: $(suffix $(1)))
+else
+ifeq ($(findstring x86,$(NDK_BUILD_ARCH)),)
+$$(error Trying to build nasm file on non-Intel platform!)
+else
+
+$(call objname,$(LOCAL_MODULE),$(basename $(1))): $(LOCAL_PATH)/$(1)
+       $(NDK_BUILD_NASM) -o $$@ -i $(LOCAL_PATH) -i $$(dir $$<) 
$(NDK_ASFLAGS_$(LOCAL_MODULE)) $$<
+
+endif
+endif
+endif
 endif
 endif
 
@@ -47,9 +68,21 @@ endef
 # Make sure to not add a prefix to local includes that already specify
 # $(LOCAL_PATH).
 NDK_CFLAGS_$(LOCAL_MODULE)      := $(addprefix -I,$(LOCAL_C_INCLUDES))
-NDK_CFLAGS_$(LOCAL_MODULE)      += -fPIC -iquote $(LOCAL_PATH) 
$(LOCAL_EXPORT_CFLAGS) $(LOCAL_CFLAGS) $(LOCAL_CFLAGS$(NDK_BUILD_ARCH))
+NDK_CFLAGS_$(LOCAL_MODULE)      += -fPIC -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) $(LOCAL_LDFLAGS)
+NDK_CXXFLAGS_$(LOCAL_MODULE) := $(LOCAL_CPPFLAGS) $(LOCAL_RTTI_FLAG)
+
+# Now look for features in LOCAL_CPP_FEATURES and enable them.
+
+ifneq ($(findstring exceptions,$(LOCAL_CPPFLAGS)),)
+NDK_CXXFLAGS_$(LOCAL_MODULE) += -fexceptions
+endif
+
+ifneq ($(findstring rtti,$(LOCAL_CPPFLAGS)),)
+NDK_CXXFLAGS_$(LOCAL_MODULE) += -frtti
+endif
+
 ALL_OBJECT_FILES$(LOCAL_MODULE) :=
 
 ifeq ($(NDK_BUILD_ARCH)$(NDK_ARM_MODE),armarm)
@@ -91,7 +124,7 @@ $(foreach source,$(ALL_SOURCE_FILES),$(eval $(call 
single-object-target,$(source
 
 define define-module-rule
 $(LOCAL_MODULE_FILENAME): $(ALL_OBJECT_FILES$(LOCAL_MODULE)) 
$(NDK_LOCAL_A_NAMES_$(LOCAL_MODULE)) $(NDK_WHOLE_A_NAMES_$(LOCAL_MODULE))
-       $(NDK_BUILD_CC) $(1) $(2) -o $$@ -shared $(NDK_LDFLAGS$(LOCAL_MODULE))
+       $(NDK_BUILD_CC) $(1) $(2) -o $$@ -shared $(NDK_LDFLAGS$(LOCAL_MODULE)) 
$(NDK_SO_EXTRA_FLAGS_$(LOCAL_MODULE)) $(NDK_SO_DEFAULT_LDFLAGS)
 endef
 
 NDK_WHOLE_ARCHIVE_PREFIX = -Wl,--whole-archive
diff --git a/cross/ndk-build/ndk-build-static-library.mk 
b/cross/ndk-build/ndk-build-static-library.mk
index 2e4893a997..4d16d81330 100644
--- a/cross/ndk-build/ndk-build-static-library.mk
+++ b/cross/ndk-build/ndk-build-static-library.mk
@@ -29,6 +29,12 @@ 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
+ifeq (x$(suffix $(1)),x.$(or $(LOCAL_CPP_EXTENSION),cpp))
+
+$(call objname,$(LOCAL_MODULE),$(basename $(1))): $(LOCAL_PATH)/$(1)
+       $(NDK_BUILD_CC) -c $$< -o $$@ $(NDK_CFLAGS_$(LOCAL_MODULE)) 
$(NDK_CXXFLAGS_$(LOCAL_MODULE))
+
 else
 ifneq ($(or $(call eq,x$(suffix $(1)),x.s),$(call eq,x$(suffix $(1)),x.S)),)
 
@@ -36,7 +42,19 @@ $(call objname,$(LOCAL_MODULE),$(basename $(1))): 
$(LOCAL_PATH)/$(1)
        $(NDK_BUILD_CC) -c $$< -o $$@ $(NDK_ASFLAGS_$(LOCAL_MODULE))
 
 else
+ifneq (x$(suffix $(1)),x.asm)
 $$(error Unsupported suffix: $(suffix $(1)))
+else
+ifeq ($(findstring x86,$(NDK_BUILD_ARCH)),)
+$$(error Trying to build nasm file on non-Intel platform!)
+else
+
+$(call objname,$(LOCAL_MODULE),$(basename $(1))): $(LOCAL_PATH)/$(1)
+       $(NDK_BUILD_NASM) -o $$@ -i $(LOCAL_PATH) -i $$(dir $$<) 
$(NDK_ASFLAGS_$(LOCAL_MODULE)) $$<
+
+endif
+endif
+endif
 endif
 endif
 
@@ -47,8 +65,20 @@ NDK_CFLAGS_$(LOCAL_MODULE)  := $(addprefix 
-I,$(LOCAL_C_INCLUDES))
 NDK_CFLAGS_$(LOCAL_MODULE)  += -fPIC -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) $(LOCAL_LDFLAGS)
+NDK_CXXFLAGS_$(LOCAL_MODULE) := $(LOCAL_CPPFLAGS) $(LOCAL_RTTI_FLAG)
 ALL_OBJECT_FILES$(LOCAL_MODULE) :=
 
+# Now look for features in LOCAL_CPP_FEATURES and enable them.
+
+ifneq ($(findstring exceptions,$(LOCAL_CPPFLAGS)),)
+NDK_CXXFLAGS_$(LOCAL_MODULE) += -fexceptions
+endif
+
+ifneq ($(findstring rtti,$(LOCAL_CPPFLAGS)),)
+NDK_CXXFLAGS_$(LOCAL_MODULE) += -frtti
+endif
+
+
 ifeq ($(NDK_BUILD_ARCH)$(NDK_ARM_MODE),armarm)
 NDK_CFLAGS ::= -marm
 else
diff --git a/cross/ndk-build/ndk-build.mk.in b/cross/ndk-build/ndk-build.mk.in
index 6ad577ccc3..798dcf6c19 100644
--- a/cross/ndk-build/ndk-build.mk.in
+++ b/cross/ndk-build/ndk-build.mk.in
@@ -20,9 +20,27 @@
 # This file is included all over the place to build prerequisites.
 
 NDK_BUILD_MODULES = @NDK_BUILD_MODULES@
+NDK_BUILD_CXX_SHARED = @NDK_BUILD_CXX_SHARED@
+NDK_BUILD_ANY_CXX_MODULE = @NDK_BUILD_ANY_CXX_MODULE@
 NDK_BUILD_SHARED =
 NDK_BUILD_STATIC =
 
+define uniqify
+$(if $1,$(firstword $1) $(call uniqify,$(filter-out $(firstword $1),$1)))
+endef
+
+# Remove duplicate modules.  These can occur when a single module
+# imports a module and also declares it in LOCAL_SHARED_LIBRARIES.
+NDK_BUILD_MODULES := $(call uniqify,$(NDK_BUILD_MODULES))
+
+# The C++ standard library must be extracted from the Android NDK
+# directories and included in the application package, if any module
+# requires the C++ standard library.
+
+ifneq ($(NDK_BUILD_ANY_CXX_MODULE),)
+NDK_BUILD_SHARED += $(NDK_BUILD_ANY_CXX_SHARED)
+endif
+
 define subr-1
 
 $(top_builddir)/cross/ndk-build/$(1):
diff --git a/cross/ndk-build/ndk-resolve.mk b/cross/ndk-build/ndk-resolve.mk
index 7fe807e35c..910be8dab5 100644
--- a/cross/ndk-build/ndk-resolve.mk
+++ b/cross/ndk-build/ndk-resolve.mk
@@ -25,9 +25,10 @@ NDK_LOCAL_STATIC_LIBRARIES_$(LOCAL_MODULE) := 
$(LOCAL_STATIC_LIBRARIES) $(LOCAL_
 NDK_LOCAL_WHOLE_LIBRARIES_$(LOCAL_MODULE) := $(LOCAL_WHOLE_STATIC_LIBRARIES)
 NDK_LOCAL_SHARED_LIBRARIES_$(LOCAL_MODULE) := $(LOCAL_SHARED_LIBRARIES)
 NDK_LOCAL_EXPORT_CFLAGS_$(LOCAL_MODULE) := $(LOCAL_EXPORT_CFLAGS)
-NDK_LOCAL_EXPORT_C_INCLUDES_$(LOCAL_MODULE) := $(LOCAL_EXPORT_C_INCLUDES)
+NDK_LOCAL_EXPORT_C_INCLUDES_$(LOCAL_MODULE) := $(LOCAL_EXPORT_C_INCLUDES) 
$(LOCAL_EXPORT_C_INCLUDE_DIRS)
 NDK_LOCAL_A_NAMES_$(LOCAL_MODULE) :=
 NDK_WHOLE_A_NAMES_$(LOCAL_MODULE) :=
+NDK_SO_EXTRA_FLAGS_$(LOCAL_MODULE) :=
 
 # List of all dependencies resolved for this module thus far.
 # Used to avoid infinite recursion.
@@ -40,6 +41,34 @@ NDK_RESOLVED_$(LOCAL_MODULE) += $(1)
 NDK_CFLAGS_$(LOCAL_MODULE) += $(NDK_LOCAL_EXPORT_CFLAGS_$(1))
 NDK_CFLAGS_$(LOCAL_MODULE) += $(addprefix 
-I,$(NDK_LOCAL_EXPORT_C_INCLUDES_$(1)))
 
+# If the module happens to be zlib, then add -lz to the shared library
+# flags.
+ifneq ($(strip $(1)),libz)
+NDK_SO_EXTRA_FLAGS_$(LOCAL_MODULE) += -lz
+endif
+
+ifneq ($(strip $(1)),z)
+NDK_SO_EXTRA_FLAGS_$(LOCAL_MODULE) += -lz
+endif
+
+# Likewise for libdl.
+ifneq ($(strip $(1)),libdl)
+NDK_SO_EXTRA_FLAGS_$(LOCAL_MODULE) += -ldl
+endif
+
+ifneq ($(strip $(1)),dl)
+NDK_SO_EXTRA_FLAGS_$(LOCAL_MODULE) += -ldl
+endif
+
+# Likewise for libstdc++.
+ifneq ($(strip $(1)),libstdc++)
+NDK_SO_EXTRA_FLAGS_$(LOCAL_MODULE) += -lstdc++
+endif
+
+ifneq ($(strip $(1)),dl)
+NDK_SO_EXTRA_FLAGS_$(LOCAL_MODULE) += -lstdc++
+endif
+
 ifneq ($(2),)
 ifneq ($(findstring lib,$(1)),)
 NDK_LOCAL_A_NAMES_$(LOCAL_MODULE) += $(1).a
diff --git a/java/org/gnu/emacs/EmacsView.java 
b/java/org/gnu/emacs/EmacsView.java
index 881cbc363b..a1953f683b 100644
--- a/java/org/gnu/emacs/EmacsView.java
+++ b/java/org/gnu/emacs/EmacsView.java
@@ -531,8 +531,9 @@ public class EmacsView extends ViewGroup
     contextMenu = menu;
     popupActive = true;
 
-    /* On API 21 or later, use showContextMenu (float, float).  */
-    if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP)
+    /* Use showContextMenu (float, float) on N to get actual popup
+       behavior.  */
+    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
       return showContextMenu ((float) xPosition, (float) yPosition);
     else
       return showContextMenu ();
diff --git a/m4/ndk-build.m4 b/m4/ndk-build.m4
index d3614a9f49..27092e4b40 100644
--- a/m4/ndk-build.m4
+++ b/m4/ndk-build.m4
@@ -21,6 +21,10 @@ AC_ARG_WITH([ndk_path],
   [AS_HELP_STRING([--with-ndk-path],
     [find Android libraries in these directories])])
 
+AC_ARG_WITH([ndk_cxx_shared],
+  [AS_HELP_STRING([--with-ndk-cxx-shared],
+    [name of the C++ standard library included with the NDK])])
+
 # ndk_INIT(ABI, API, DIR)
 # --------
 # Initialize the Android NDK.  ABI is the ABI being built for.
@@ -45,6 +49,7 @@ ndk_MAKEFILES=
 ndk_INITIALIZED=yes
 ndk_API=$2
 ndk_DIR=$3
+ndk_ANY_CXX=
 
 case "$ndk_ABI" in
  *arm64* )
@@ -103,6 +108,62 @@ ndk_parse_pkg_config_string () {
   done
 }
 
+# Resolve $1, a single import.  Prepend its makefile to ndk_MAKEFILES
+# if found.  Also, prepend all includes to the variable
+# ndk_import_includes.
+
+ndk_resolve_import_module () {
+  module_name=
+  ndk_module=[$]1
+
+  AC_MSG_CHECKING([for imported $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])
+    AC_MSG_ERROR([The module currently being built depends on [$]1, but \
+that could not be found in the list of directories specified in \
+`--with-ndk-path'.])
+  fi
+
+  if test -n "$module_cxx_deps"; then
+    ndk_ANY_CXX=yes
+  fi
+
+  if test "$ndk_ANY_CXX" = "yes" && test -z "$with_ndk_cxx_shared"; then
+    AC_MSG_ERROR([The module [$]1 requires the C++ standard library \
+(libc++_shared.so), but it was not found.])
+  fi
+
+  AC_MSG_RESULT([yes])
+
+  # Make sure the module is prepended.
+  ndk_MAKEFILES="$ndk_android_mk $ndk_MAKEFILES"
+  ndk_import_includes="$module_includes $ndk_import_includes"
+
+  # Now recursively resolve this module's imports.
+  for ndk_module in $module_imports; do
+    ndk_resolve_import_module $ndk_module
+  done
+}
+
 # Look for a suitable ar in the same directory as the C compiler.
 ndk_where_cc=$(which $CC)
 ndk_ar_search_path=$PATH
@@ -117,15 +178,102 @@ if test -z "$AR"; then
   AC_PATH_PROGS([AR], [$host_alias-ar llvm-ar], [], [$ndk_ar_search_path])
 fi
 
+NDK_BUILD_NASM=
+
+# Next, try to find nasm on x86.  This doesn't ship with the NDK.
+if test "$ndk_ARCH" = "x86" || test "$ndk_ARCH" = "x86_64"; then
+  AC_CHECK_PROGS([NDK_BUILD_NASM], [nasm])
+fi
+
+# Look for a file named ``libc++_shared.so'' in a subdirectory of
+# $ndk_where_cc if it was not specified.
+AC_MSG_CHECKING([for libc++_shared.so])
+
+ndk_where_toolchain=
+if test -z "$with_ndk_cxx_shared" && test -n "$ndk_where_cc"; then
+  # Find the NDK root directory.  Go to $ndk_where_cc.
+  SAVE_PWD=`pwd`
+  cd $(dirname "$ndk_where_cc")
+
+  # Now, keep moving backwards until pwd ends with ``toolchains''.
+  while :; do
+    if test "`pwd`" = "/"; then
+      cd "$SAVE_PWD"
+      break
+    fi
+
+    if test "`basename $(pwd)`" = "toolchains"; then
+      ndk_where_toolchain=`pwd`
+      cd "$SAVE_PWD"
+      break
+    fi
+
+    cd ..
+  done
+
+  ndk_matching_libcxx_shared_so=
+
+  # The toolchain directory should be in "$ndk_where_toolchain".
+  if test -n "$ndk_where_toolchain"; then
+    # Now, look in the directory behind it.
+    ndk_cxx_shared_so=`find "$ndk_where_toolchain" -name libc++_shared.so`
+
+    # Look for one with the correct architecture.
+    for ndk_candidate in $ndk_cxx_shared_so; do
+      case "$ndk_candidate" in
+        *arm-linux-android* )
+         if test "$ndk_ARCH" = "arm"; then
+           ndk_matching_libcxx_shared_so=$ndk_candidate
+         fi
+         ;;
+       *aarch64-linux-android* )
+         if test "$ndk_ARCH" = "arm64"; then
+           ndk_matching_libcxx_shared_so=$ndk_candidate
+         fi
+         ;;
+       *i[[3-6]]86-linux-android* )
+         if test "$ndk_ARCH" = "x86"; then
+           ndk_matching_libcxx_shared_so=$ndk_candidate
+         fi
+         ;;
+       *x86_64-linux-android* )
+         if test "$ndk_ARCH" = "x86_64"; then
+           ndk_matching_libcxx_shared_so=$ndk_candidate
+         fi
+         ;;
+      esac
+
+      if test -n "$ndk_matching_libcxx_shared_so"; then
+        with_ndk_cxx_shared=$ndk_matching_libcxx_shared_so
+      fi
+    done
+  fi
+fi
+
+if test -z "$with_ndk_cxx_shared"; then
+  AC_MSG_RESULT([no])
+  AC_MSG_WARN([The C++ standard library could not be found.  \
+If you try to build Emacs with a dependency that requires the C++ standard \
+library, Emacs will not build correctly, unless you manually specify the \
+name of an appropriate ``libc++_shared.so'' binary.])
+else
+  AC_MSG_RESULT([$with_ndk_cxx_shared])
+fi
+
+ndk_CXX_SHARED=$with_ndk_cxx_shared
+
 # 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.
+# name of the module's Android.mk file to the variable ndk_MAKEFILES.
+# Set NAME_CFLAGS and NAME_LIBS to the appropriate values.  Then, call
+# ACTION-IF-FOUND, or ACTION-IF-NOT-FOUND upon failure.
+#
+# Resolve any imports specified by MODULE, and expand AC_MSG_ERROR
+# with a suitable error message if imports were not found.
 AC_DEFUN([ndk_SEARCH_MODULE],
 [
 module_name=
@@ -137,7 +285,7 @@ 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=.     \
+  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"                    \
@@ -155,12 +303,29 @@ if test -z "$module_name"; then
   AC_MSG_RESULT([no])
   $4
 else
+  if test -n "$module_cxx_deps"; then
+    ndk_ANY_CXX=yes
+  fi
+
+  if test "$ndk_ANY_CXX" = "yes" && test -z "$with_ndk_cxx_shared"; then
+    AC_MSG_ERROR([The module $1 requires the C++ standard library \
+(libc++_shared.so), but it was not found.])
+  fi
+
   $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
+
+  # Now, resolve imports.  Make sure the imports' Makefiles comes
+  # before ndk_MAKEFILES; likewise for its includes.
+  ndk_import_includes=
+  for ndk_module in $module_imports; do
+    ndk_resolve_import_module $ndk_module
+    $2[]_CFLAGS="$ndk_import_includes [$]$2[]_CFLAGS"
+  done
 fi
 ])
 
@@ -198,6 +363,8 @@ AC_DEFUN_ONCE([ndk_CONFIG_FILES],
     NDK_BUILD_CC=$CC
     NDK_BUILD_AR=$AR
     NDK_BUILD_MODULES="$ndk_MODULES"
+    NDK_BUILD_CXX_SHARED="$ndk_CXX_SHARED"
+    NDK_BUILD_ANY_CXX_MODULE=$ndk_ANY_CXX
 
     AC_SUBST([NDK_BUILD_ANDROID_MK])
     AC_SUBST([NDK_BUILD_ARCH])
@@ -205,7 +372,10 @@ AC_DEFUN_ONCE([ndk_CONFIG_FILES],
     AC_SUBST([NDK_BUILD_SDK])
     AC_SUBST([NDK_BUILD_CC])
     AC_SUBST([NDK_BUILD_AR])
+    AC_SUBST([NDK_BUILD_NASM])
     AC_SUBST([NDK_BUILD_MODULES])
+    AC_SUBST([NDK_BUILD_CXX_SHARED])
+    AC_SUBST([NDK_BUILD_ANY_CXX_MODULE])
 
     AC_CONFIG_FILES([$ndk_DIR/Makefile])
     AC_CONFIG_FILES([$ndk_DIR/ndk-build.mk])
diff --git a/src/android.c b/src/android.c
index 2f21a03b53..52de153eef 100644
--- a/src/android.c
+++ b/src/android.c
@@ -4214,30 +4214,34 @@ android_window_updated (android_window window, unsigned 
long serial)
 
 
 
-#if __ANDROID_API__ >= 17
-
-#undef faccessat
+#if __ANDROID_API__ >= 16
 
 /* Replace the system faccessat with one which understands AT_EACCESS.
    Android's faccessat simply fails upon using AT_EACCESS, so replace
    it with zero here.  This isn't caught during configuration.
 
-   This replacement is only done when building for Android 17 or
+   This replacement is only done when building for Android 16 or
    later, because earlier versions use the gnulib replacement that
    lacks these issues.  */
 
 int
-faccessat (int dirfd, const char *pathname, int mode, int flags)
+android_faccessat (int dirfd, const char *pathname, int mode, int flags)
 {
-  static int (*real_faccessat) (int, const char *, int, int);
+  return faccessat (dirfd, pathname, mode, flags & ~AT_EACCESS);
+}
+
+#else /* __ANDROID_API__ < 16 */
 
-  if (!real_faccessat)
-    real_faccessat = dlsym (RTLD_NEXT, "faccessat");
+/* This is unnecessary on earlier API versions, as gnulib's
+   rpl_faccessat will be used instead.  */
 
-  return real_faccessat (dirfd, pathname, mode, flags & ~AT_EACCESS);
+int
+android_faccessat (int dirfd, const char *pathname, int mode, int flags)
+{
+  return faccessat (dirfd, pathname, mode, flags);
 }
 
-#endif /* __ANDROID_API__ >= 17 */
+#endif
 
 
 
diff --git a/src/android.h b/src/android.h
index 6c20995e4a..33fad512d4 100644
--- a/src/android.h
+++ b/src/android.h
@@ -52,6 +52,7 @@ extern char *android_user_full_name (struct passwd *);
 extern int android_fstat (int, struct stat *);
 extern int android_fstatat (int, const char *restrict,
                            struct stat *restrict, int);
+extern int android_faccessat (int, const char *, int, int);
 extern int android_close (int);
 extern int android_fclose (FILE *);
 extern const char *android_get_home_directory (void);
diff --git a/src/dired.c b/src/dired.c
index ced08a3564..b38416e981 100644
--- a/src/dired.c
+++ b/src/dired.c
@@ -894,7 +894,8 @@ file_name_completion_dirp (int fd, struct dirent *dp, 
ptrdiff_t len)
     return true;
 #endif
 
-  bool dirp = faccessat (fd, subdir_name, F_OK, AT_EACCESS) == 0;
+  bool dirp = sys_faccessat (fd, subdir_name,
+                            F_OK, AT_EACCESS) == 0;
   SAFE_FREE ();
   return dirp;
 }
diff --git a/src/fileio.c b/src/fileio.c
index 492a43d74c..6f25506dbc 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -188,7 +188,7 @@ file_access_p (char const *file, int amode)
     return true;
 #endif
 
-  if (faccessat (AT_FDCWD, file, amode, AT_EACCESS) == 0)
+  if (sys_faccessat (AT_FDCWD, file, amode, AT_EACCESS) == 0)
     return true;
 
 #ifdef CYGWIN
@@ -3024,7 +3024,8 @@ If there is no error, returns nil.  */)
     return Qnil;
 #endif
 
-  if (faccessat (AT_FDCWD, SSDATA (encoded_filename), R_OK, AT_EACCESS) != 0)
+  if (sys_faccessat (AT_FDCWD, SSDATA (encoded_filename), R_OK,
+                    AT_EACCESS) != 0)
     report_file_error (SSDATA (string), filename);
 
   return Qnil;
@@ -3126,7 +3127,8 @@ file_directory_p (Lisp_Object file)
 {
 #ifdef DOS_NT
   /* This is cheaper than 'stat'.  */
-  bool retval = faccessat (AT_FDCWD, SSDATA (file), D_OK, AT_EACCESS) == 0;
+  bool retval = sys_faccessat (AT_FDCWD, SSDATA (file),
+                              D_OK, AT_EACCESS) == 0;
   if (!retval && errno == EACCES)
     errno = ENOTDIR;   /* like the non-DOS_NT branch below does */
   return retval;
diff --git a/src/lisp.h b/src/lisp.h
index f64a27ce11..6fda1e9550 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -5071,6 +5071,7 @@ extern int emacs_fstatat (int, char const *, void *, int);
 #ifdef HAVE_SYS_STAT_H
 extern int sys_fstat (int, struct stat *);
 #endif
+extern int sys_faccessat (int, const char *, int, int);
 #if !(defined HAVE_ANDROID && !defined ANDROID_STUBIFY)
 extern int emacs_openat (int, char const *, int, int);
 #endif
diff --git a/src/lread.c b/src/lread.c
index d585dece39..6abcea556b 100644
--- a/src/lread.c
+++ b/src/lread.c
@@ -1964,8 +1964,8 @@ openp (Lisp_Object path, Lisp_Object str, Lisp_Object 
suffixes,
                fd = -1;
                if (INT_MAX < XFIXNAT (predicate))
                  last_errno = EINVAL;
-               else if (faccessat (AT_FDCWD, pfn, XFIXNAT (predicate),
-                                   AT_EACCESS)
+               else if (sys_faccessat (AT_FDCWD, pfn, XFIXNAT (predicate),
+                                       AT_EACCESS)
                         == 0)
                  {
                    if (file_directory_p (encoded_fn))
@@ -1985,7 +1985,7 @@ openp (Lisp_Object path, Lisp_Object str, Lisp_Object 
suffixes,
                     it.  Only open the file when we are sure that it
                     exists.  */
 #ifdef WINDOWSNT
-                if (faccessat (AT_FDCWD, pfn, R_OK, AT_EACCESS))
+                if (sys_faccessat (AT_FDCWD, pfn, R_OK, AT_EACCESS))
                   fd = -1;
                 else
 #endif
diff --git a/src/process.c b/src/process.c
index 651b5fa035..9a8b0d7fd8 100644
--- a/src/process.c
+++ b/src/process.c
@@ -880,7 +880,8 @@ allocate_pty (char pty_name[PTY_NAME_SIZE])
 
            /* Check to make certain that both sides are available.
               This avoids a nasty yet stupid bug in rlogins.  */
-           if (faccessat (AT_FDCWD, pty_name, R_OK | W_OK, AT_EACCESS) != 0)
+           if (sys_faccessat (AT_FDCWD, pty_name,
+                              R_OK | W_OK, AT_EACCESS) != 0)
              {
                emacs_close (fd);
                continue;
diff --git a/src/sysdep.c b/src/sysdep.c
index 4d89d4f25a..ac26b12e9a 100644
--- a/src/sysdep.c
+++ b/src/sysdep.c
@@ -2398,6 +2398,16 @@ sys_fstat (int fd, struct stat *statb)
 #endif
 }
 
+int
+sys_faccessat (int fd, const char *pathname, int mode, int flags)
+{
+#if !(defined HAVE_ANDROID && !defined ANDROID_STUBIFY)
+  return faccessat (fd, pathname, mode, flags);
+#else
+  return android_faccessat (fd, pathname, mode, flags);
+#endif
+}
+
 /* Assuming the directory DIRFD, open FILE for Emacs use,
    using open flags OFLAGS and mode MODE.
    Use binary I/O on systems that care about text vs binary I/O.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]