emacs-diffs
[Top][All Lists]
Advanced

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

master 7a0f4de3c18: Improve C++ standard library detection on Android


From: Po Lu
Subject: master 7a0f4de3c18: Improve C++ standard library detection on Android
Date: Sun, 17 Mar 2024 07:56:32 -0400 (EDT)

branch: master
commit 7a0f4de3c18cab43b5bff47fdab4944e006c68e4
Author: Po Lu <luangruo@yahoo.com>
Commit: Po Lu <luangruo@yahoo.com>

    Improve C++ standard library detection on Android
    
    * configure.ac: Stop relaying --with-ndk-cxx-shared to the
    nested invocation of configure.
    
    * build-aux/ndk-build-helper-1.mk (SYSTEM_LIBRARIES):
    
    * build-aux/ndk-build-helper-2.mk (SYSTEM_LIBRARIES): Insert all
    of the C++ libraries available on Android.
    
    * configure.ac: Call ndk_LATE and ndk_LATE_EARLY within if
    statement at toplevel, averting needless calls to AC_PROG_CXX.
    
    * cross/ndk-build/Makefile.in (NDK_BUILD_CXX_STL)
    (NDK_BUILD_CXX_LDFLAGS):
    
    * cross/ndk-build/ndk-build.mk.in (NDK_BUILD_CXX_STL)
    (NDK_BUILD_CXX_LDFLAGS): New variables.
    
    * cross/ndk-build/ndk-resolve.mk (NDK_SYSTEM_LIBRARIES):
    Introduce several other C++ libraries sometimes present on
    Android.
    (NDK_SO_EXTRA_FLAGS_$(LOCAL_MODULE)): Insert NDK_BUILD_CXX_STL
    when any of these new C++ libraries are requested.
    
    * m4/ndk-build.m4: Completely rewrite C++ compiler and library
    detection.
    
    * java/org/gnu/emacs/EmacsNative.java (EmacsNative): Attempt to
    load more libraries from static initializer.
    
    * java/INSTALL: Remove obsolete information.
---
 build-aux/ndk-build-helper-1.mk     |   2 +-
 build-aux/ndk-build-helper-2.mk     |   2 +-
 configure.ac                        |  12 +-
 cross/ndk-build/Makefile.in         |  26 +--
 cross/ndk-build/ndk-build.mk.in     |   2 +
 cross/ndk-build/ndk-resolve.mk      |  32 +++-
 java/INSTALL                        |  34 ++--
 java/org/gnu/emacs/EmacsNative.java |   6 +-
 m4/ndk-build.m4                     | 354 +++++++++++++++++++++++++++---------
 9 files changed, 337 insertions(+), 133 deletions(-)

diff --git a/build-aux/ndk-build-helper-1.mk b/build-aux/ndk-build-helper-1.mk
index 5681728154c..490064b6e32 100644
--- a/build-aux/ndk-build-helper-1.mk
+++ b/build-aux/ndk-build-helper-1.mk
@@ -94,7 +94,7 @@ endef
 # 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 libdl dl stdc++ libstdc++ log liblog android 
libandroid
+SYSTEM_LIBRARIES = z libz libc c libdl dl stdc++ libstdc++ stlport libstlport 
gnustl libgnustl c++ libc++ log liblog android libandroid
 
 $(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_STATIC_LIBRARIES)),$(eval $(call 
add-includes,$(module))))
diff --git a/build-aux/ndk-build-helper-2.mk b/build-aux/ndk-build-helper-2.mk
index 1c2409cfd57..e696fcbdade 100644
--- a/build-aux/ndk-build-helper-2.mk
+++ b/build-aux/ndk-build-helper-2.mk
@@ -87,7 +87,7 @@ endef
 # Resolve additional dependencies based on LOCAL_STATIC_LIBRARIES and
 # LOCAL_SHARED_LIBRARIES.
 
-SYSTEM_LIBRARIES = z libz libc c libdl dl libstdc++ stdc++ log liblog android 
libandroid
+SYSTEM_LIBRARIES = z libz libc c libdl dl libstdc++ stdc++ stlport libstlport 
gnustl libgnustl c++ libc++ log liblog android libandroid
 
 $(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))))
diff --git a/configure.ac b/configure.ac
index 452aa0838f1..bd678ea52a3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -171,7 +171,6 @@ AS_IF([test "$XCONFIGURE" = "android"],[
   # Make sure to pass through the CFLAGS, as older versions of the
   # NDK require them to be able to find system includes.
   with_ndk_path="$android_ndk_path"
-  with_ndk_cxx_shared="$android_ndk_cxx_shared"
   with_ndk_cxx="$android_ndk_cxx"
   ndk_INIT([$android_abi], [$ANDROID_SDK], [cross/ndk-build],
            [$ANDROID_CFLAGS])
@@ -1233,7 +1232,7 @@ package will likely install on older systems but crash on 
startup.])
   passthrough="$passthrough --with-harfbuzz=$with_harfbuzz"
   passthrough="$passthrough --with-threads=$with_threads"
 
-  # Now pass through some checking options.
+  # Now pass through some checking-related options.
   emacs_val="--enable-check-lisp-object-type=$enable_check_lisp_object_type"
   passthrough="$passthrough $emacs_val"
 
@@ -1243,7 +1242,6 @@ package will likely install on older systems but crash on 
startup.])
   AS_IF([XCONFIGURE=android ANDROID_CC="$ANDROID_CC"           \
          ANDROID_SDK="$android_sdk" android_abi=$android_abi   \
         android_ndk_path="$with_ndk_path"                      \
-        android_ndk_cxx_shared="$with_ndk_cxx_shared"          \
         android_ndk_cxx="$android_ndk_cxx"                     \
         $CONFIG_SHELL $0 $passthrough], [],
     [AC_MSG_ERROR([Failed to cross-configure Emacs for android.])])
@@ -1570,7 +1568,13 @@ AC_DEFUN_ONCE([gl_STDLIB_H],
 # Initialize gnulib right after choosing the compiler.
 dnl Amongst other things, this sets AR and ARFLAGS.
 gl_EARLY
-ndk_LATE
+
+# ndk_LATE must be enclosed in this conditional to prevent the
+# AC_PROG_CXX it indirectly requires from being expanded at top level.
+if test "$ndk_INITIALIZED" = "yes"; then
+  ndk_LATE_EARLY
+  ndk_LATE
+fi
 
 if test "$ac_test_CFLAGS" != set; then
   # It's helpful to have C macros available to GDB, so prefer -g3 to -g
diff --git a/cross/ndk-build/Makefile.in b/cross/ndk-build/Makefile.in
index 8ba2d356f27..0970a765b45 100644
--- a/cross/ndk-build/Makefile.in
+++ b/cross/ndk-build/Makefile.in
@@ -24,15 +24,17 @@
               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_CXX = @NDK_BUILD_CXX@
-        NDK_BUILD_AR = @NDK_BUILD_AR@
-      NDK_BUILD_NASM = @NDK_BUILD_NASM@
-    NDK_BUILD_CFLAGS = @NDK_BUILD_CFLAGS@
+ 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_CXX = @NDK_BUILD_CXX@
+    NDK_BUILD_CXX_STL = @NDK_BUILD_CXX_STL@
+NDK_BUILD_CXX_LDFLAGS = @NDK_BUILD_CXX_LDFLAGS@
+        NDK_BUILD_AR = @NDK_BUILD_AR@
+       NDK_BUILD_NASM = @NDK_BUILD_NASM@
+     NDK_BUILD_CFLAGS = @NDK_BUILD_CFLAGS@
 
 # This is a list of targets to build.
    NDK_BUILD_MODULES = @NDK_BUILD_MODULES@
@@ -58,8 +60,10 @@ NDK_BUILD_ANDROID_MK := $(call 
uniqify,$(NDK_BUILD_ANDROID_MK))
 NDK_BUILD_MODULES := $(call uniqify,$(NDK_BUILD_MODULES))
 
 # Define CFLAGS for compiling C++ code; this involves removing all
-# -std=NNN options.
-NDK_BUILD_CFLAGS_CXX := $(filter-out -std=%,$(NDK_BUILD_CFLAGS))
+# -std=NNN options and inserting compilation options for the C++
+# library.
+NDK_BUILD_CFLAGS_CXX := $(filter-out -std=%,$(NDK_BUILD_CFLAGS)) \
+  $(NDK_BUILD_CXX_STL)
 
 define subr-1
 
diff --git a/cross/ndk-build/ndk-build.mk.in b/cross/ndk-build/ndk-build.mk.in
index 6c85ff5044e..ea1be5af6f1 100644
--- a/cross/ndk-build/ndk-build.mk.in
+++ b/cross/ndk-build/ndk-build.mk.in
@@ -22,6 +22,8 @@
 
 NDK_BUILD_MODULES = @NDK_BUILD_MODULES@
 NDK_BUILD_CXX_SHARED = @NDK_BUILD_CXX_SHARED@
+NDK_BUILD_CXX_STL = @NDK_BUILD_CXX_STL@
+NDK_BUILD_CXX_LDFLAGS = @NDK_BUILD_CXX_LDFLAGS@
 NDK_BUILD_ANY_CXX_MODULE = @NDK_BUILD_ANY_CXX_MODULE@
 NDK_BUILD_SHARED =
 NDK_BUILD_STATIC =
diff --git a/cross/ndk-build/ndk-resolve.mk b/cross/ndk-build/ndk-resolve.mk
index d3b398bca62..4d8ecf8667a 100644
--- a/cross/ndk-build/ndk-resolve.mk
+++ b/cross/ndk-build/ndk-resolve.mk
@@ -20,7 +20,7 @@
 # which actually builds targets.
 
 # List of system libraries to ignore.
-NDK_SYSTEM_LIBRARIES = z libz libc c libdl dl stdc++ libstdc++ log liblog 
android libandroid
+NDK_SYSTEM_LIBRARIES = z libz libc c libdl dl stdc++ libstdc++ stlport 
libstlport gnustl libgnustl c++ libc++ log liblog android libandroid
 
 # Save information.
 NDK_LOCAL_PATH_$(LOCAL_MODULE) := $(LOCAL_PATH)
@@ -90,11 +90,35 @@ endif
 
 # Likewise for libstdc++.
 ifeq ($(strip $(1)),libstdc++)
-NDK_SO_EXTRA_FLAGS_$(LOCAL_MODULE) += -lstdc++
+NDK_SO_EXTRA_FLAGS_$(LOCAL_MODULE) += $(NDK_BUILD_CXX_LDFLAGS)
 endif
 
-ifeq ($(strip $(1)),dl)
-NDK_SO_EXTRA_FLAGS_$(LOCAL_MODULE) += -lstdc++
+ifeq ($(strip $(1)),stdc++)
+NDK_SO_EXTRA_FLAGS_$(LOCAL_MODULE) += $(NDK_BUILD_CXX_LDFLAGS)
+endif
+
+ifeq ($(strip $(1)),libstlport)
+NDK_SO_EXTRA_FLAGS_$(LOCAL_MODULE) += $(NDK_BUILD_CXX_LDFLAGS)
+endif
+
+ifeq ($(strip $(1)),stlport)
+NDK_SO_EXTRA_FLAGS_$(LOCAL_MODULE) += $(NDK_BUILD_CXX_LDFLAGS)
+endif
+
+ifeq ($(strip $(1)),libgnustl)
+NDK_SO_EXTRA_FLAGS_$(LOCAL_MODULE) += $(NDK_BUILD_CXX_LDFLAGS)
+endif
+
+ifeq ($(strip $(1)),gnustl)
+NDK_SO_EXTRA_FLAGS_$(LOCAL_MODULE) += $(NDK_BUILD_CXX_LDFLAGS)
+endif
+
+ifeq ($(strip $(1)),libc++)
+NDK_SO_EXTRA_FLAGS_$(LOCAL_MODULE) += $(NDK_BUILD_CXX_LDFLAGS)
+endif
+
+ifeq ($(strip $(1)),c++)
+NDK_SO_EXTRA_FLAGS_$(LOCAL_MODULE) += $(NDK_BUILD_CXX_LDFLAGS)
 endif
 
 # Likewise for liblog.
diff --git a/java/INSTALL b/java/INSTALL
index 175ff2826b2..f1063b40c25 100644
--- a/java/INSTALL
+++ b/java/INSTALL
@@ -166,25 +166,21 @@ than a compressed package for a newer version of Android.
 
 BUILDING C++ DEPENDENCIES
 
-With a new version of the NDK, dependencies containing C++ code should
-build without any further configuration.  However, older versions
-require that you use the ``make_standalone_toolchain.py'' script in
-the NDK distribution to create a ``standalone toolchain'', and use
-that instead, in order for C++ headers to be found.
-
-See https://developer.android.com/ndk/guides/standalone_toolchain for
-more details; when a ``standalone toolchain'' is specified, the
-configure script will try to determine the location of the C++
-compiler based on the C compiler specified.  If that automatic
-detection does not work, you can specify a C++ compiler yourself, like
-so:
-
-  ./configure --with-ndk-cxx=/path/to/toolchain/bin/i686-linux-android-g++
-
-Some versions of the NDK have a bug, where GCC fails to locate
-``stddef.h'' after being copied to a standalone toolchain.  To work
-around this problem (which normally exhibits itself when building C++
-code), add:
+In normal circumstances, Emacs should automatically detect and configure
+one of the C++ standard libraries part of the NDK when such a library is
+required to build a dependency specified under `--with-ndk-path'.
+
+Nevertheless, this process is not infalliable, and with certain versions
+of the NDK is liable to fail to locate a C++ compiler, requiring that
+you run the `make_standalone_toolchain.py' script in the NDK
+distribution to create a ``standalone toolchain'' and substitute the
+same for the regular compiler toolchain.  See
+https://developer.android.com/ndk/guides/standalone_toolchain for
+further details.
+
+Some versions of the NDK that ship GCC 4.9.x exhibit a bug where the
+compiler cannot locate `stddef.h' after being copied to a standalone
+toolchain.  To work around this problem, add:
 
    -isystem /path/to/toolchain/include/c++/4.9.x
 
diff --git a/java/org/gnu/emacs/EmacsNative.java 
b/java/org/gnu/emacs/EmacsNative.java
index 6845f833908..898eaef41a7 100644
--- a/java/org/gnu/emacs/EmacsNative.java
+++ b/java/org/gnu/emacs/EmacsNative.java
@@ -323,7 +323,9 @@ public final class EmacsNative
        Every time you add a new shared library dependency to Emacs,
        please add it here as well.  */
 
-    libraryDeps = new String[] { "png_emacs", "selinux_emacs",
+    libraryDeps = new String[] { "c++_shared", "gnustl_shared",
+                                "stlport_shared", "gabi++_shared",
+                                "png_emacs", "selinux_emacs",
                                 "crypto_emacs", "pcre_emacs",
                                 "packagelistparser_emacs",
                                 "gnutls_emacs", "gmp_emacs",
@@ -331,7 +333,7 @@ public final class EmacsNative
                                 "tasn1_emacs", "hogweed_emacs",
                                 "jansson_emacs", "jpeg_emacs",
                                 "tiff_emacs", "xml2_emacs",
-                                "icuuc_emacs",
+                                "icuuc_emacs", "harfbuzz_emacs",
                                 "tree-sitter_emacs", };
 
     for (String dependency : libraryDeps)
diff --git a/m4/ndk-build.m4 b/m4/ndk-build.m4
index aacb2ed048b..7012471e046 100644
--- a/m4/ndk-build.m4
+++ b/m4/ndk-build.m4
@@ -21,10 +21,6 @@ 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])])
-
 AC_ARG_WITH([ndk_cxx],
   [AS_HELP_STRING([--with-ndk-cxx],
     [name of the C++ compiler included with the NDK])])
@@ -59,6 +55,7 @@ ndk_DIR=$3
 ndk_ANY_CXX=
 ndk_BUILD_CFLAGS="$4"
 ndk_working_cxx=no
+ndk_CXX_SHARED=
 
 AS_CASE(["$ndk_ABI"],
   [*arm64*], [ndk_ARCH=arm64],
@@ -149,7 +146,7 @@ ndk_resolve_import_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
+    # tree build system sets it to a meaningful value, but build files
     # just use it to test whether or not the NDK is being used.
     ndk_commands=`ndk_run_test`
     eval "$ndk_commands"
@@ -169,13 +166,14 @@ that could not be found in the list of directories 
specified in \
     ndk_ANY_CXX=yes
   fi
 
-  AS_IF([test "$ndk_ANY_CXX" = "yes" && test -z "$with_ndk_cxx_shared"],
-    [AC_MSG_ERROR([The module [$]1 requires the C++ standard library \
-(libc++_shared.so), but it was not found.])])
+  AS_IF([test "$module_cxx_deps" = "yes" && test -z "$ndk_CXX_STL" \
+         && test -z "$ndk_CXX_LDFLAGS"],
+    [AC_MSG_ERROR([The module $1 requires a C++ standard library,
+but none were found.])])
 
-  AS_IF([test "$ndk_ANY_CXX" = "yes" && test "$ndk_working_cxx" != "yes"],
-    [AC_MSG_ERROR([The module [$]1 requires the C++ standard library \
-(libc++_shared.so), but a working C++ compiler was not found.])])
+  AS_IF([test "$module_cxx_deps" = "yes" && test "$ndk_working_cxx" != "yes"],
+    [AC_MSG_ERROR([The module [$]1 requires the C++ standard library,
+but a working C++ compiler was not found.])])
 
   AC_MSG_RESULT([yes])
 
@@ -227,6 +225,88 @@ ndk_subst_cc_onto_cxx () {
   done
 }
 
+# ndk_subst_cflags_onto_cxx
+# ---------------------
+# Print any options in CFLAGS also suitable for a C++ compiler.
+
+ndk_subst_cflags_onto_cxx () {
+  ndk_flag=
+  for ndk_word in $CFLAGS; do
+    AS_IF([test "$ndk_flag" = "yes"],
+      [AS_ECHO_N(["$ndk_word "])
+       ndk_flag=no],
+      [AS_CASE([$ndk_word],
+        [*-sysroot=*],
+          [AS_ECHO_N(["$ndk_word "])],
+       [*-isystem*],
+          [AS_ECHO_N(["$ndk_word "])
+          ndk_flag=yes],
+       [*-I*],
+          [AS_ECHO_N(["$ndk_word "])
+          ndk_flag=yes],
+       [*-sysroot*],
+         [AS_ECHO_N(["$ndk_word "])
+          ndk_flag=yes],
+       [-D__ANDROID_API__*],
+         [AS_ECHO_N(["$ndk_word "])])])
+  done
+}
+
+# Detect the installation directory and type of the NDK being used.
+
+ndk_install_dir=
+ndk_toolchain_type=
+
+AC_MSG_CHECKING([for the directory where the NDK is installed])
+
+dnl If the install directory isn't available, repeat the search over
+dnl each entry in the programs directory.
+ndk_programs_dirs=`$CC -print-search-dirs | sed -n "s/^programs:[[\t 
]]*=\?\(.*\)/\1/p"`
+ndk_save_IFS=$IFS; IFS=:
+for ndk_dir in $ndk_programs_dirs; do
+   if test -d "$ndk_dir"; then :; else
+     continue
+   fi
+   ndk_dir=`cd "$ndk_dir"; pwd`
+   while test "$ndk_dir" != "/" && test -z "$ndk_toolchain_type"; do
+     ndk_dir=`AS_DIRNAME([$ndk_dir])`
+     AS_IF([test -d "$ndk_dir/bin" && test -d "$ndk_dir/lib"],
+      [dnl The directory reached is most likely either the directory
+       dnl holding prebuilt binaries in a combined toolchain or the
+       dnl directory holding a standalone toolchain itself.
+       dnl
+       dnl Distinguish between the two by verifying the name of the
+       dnl parent directory (and its parent).
+       ndk_dir1=`AS_DIRNAME(["$ndk_dir"])`
+       ndk_basename=`AS_BASENAME(["$ndk_dir1"])`
+       AS_IF([test "$ndk_basename" = "prebuilt"],
+        [dnl Directories named "prebuilt" are exclusively present in
+         dnl combined toolchains, where they are children of the
+         dnl base directory or, in recent releases, a directory
+         dnl within the base directory.  Continue searching for the
+         dnl base directory.
+         ndk_toolchain_type=combined
+         while test "$ndk_dir1" != "/"; do
+           AS_IF([test -d "$ndk_dir1/toolchains" \
+                  && test -d "$ndk_dir1/sources"],
+             [ndk_install_dir=$ndk_dir1
+              break])
+           ndk_dir1=`AS_DIRNAME(["$ndk_dir1"])`
+         done],
+        [ndk_toolchain_type=standalone
+         ndk_install_dir=$ndk_dir])])
+   done
+   AS_IF([test -n "$ndk_toolchain_type"],
+     [break])
+done
+IFS=$ndk_save_IFS
+
+AS_IF([test -z "$ndk_install_dir"],
+  [AC_MSG_RESULT([unknown])
+   AC_MSG_WARN([The NDK installation directory could not be \
+derived from the compiler.])],
+  [AC_MSG_RESULT([$ndk_install_dir ($ndk_toolchain_type)])])
+
 # Look for a suitable ar and ranlib in the same directory as the C
 # compiler.
 ndk_cc_firstword=`AS_ECHO(["$CC"]) | cut -d' ' -f1`
@@ -259,72 +339,8 @@ NDK_BUILD_NASM=
 AS_IF([test "$ndk_ARCH" = "x86" || test "$ndk_ARCH" = "x86_64"],
   [AC_CHECK_PROGS([NDK_BUILD_NASM], [nasm])])
 
-# 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=
-AS_IF([test -z "$with_ndk_cxx_shared" && test -n "$ndk_where_cc"],[
-  # Find the NDK root directory.  Go to $ndk_where_cc.
-  SAVE_PWD=`pwd`
-  cd `AS_DIRNAME(["$ndk_where_cc"])`
-
-  # Now, keep moving backwards until pwd ends with ``toolchains''.
-  while :; do
-    if test "`pwd`" = "/"; then
-      cd "$SAVE_PWD"
-      break
-    fi
-
-    ndk_pwd=`pwd`
-    if test "`AS_BASENAME([$ndk_pwd])`" = "toolchains"; then
-      ndk_where_toolchain=$ndk_pwd
-      cd "$SAVE_PWD"
-      break
-    fi
-
-    cd ..
-  done
-
-  ndk_matching_libcxx_shared_so=
-
-  # The toolchain directory should be in "$ndk_where_toolchain".
-  AS_IF([test -n "$ndk_where_toolchain"],[
-    # 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
-      AS_CASE([$ndk_candidate],
-        [*arm-linux-android*],
-         [AS_IF([test "$ndk_ARCH" = "arm"],
-           [ndk_matching_libcxx_shared_so=$ndk_candidate])],
-       [*aarch64-linux-android*],
-         [AS_IF([test "$ndk_ARCH" = "arm64"],
-           [ndk_matching_libcxx_shared_so=$ndk_candidate])],
-       [*i[[3-6]]86-linux-android*],
-         [AS_IF([test "$ndk_ARCH" = "x86"],
-           [ndk_matching_libcxx_shared_so=$ndk_candidate])],
-       [*x86_64-linux-android*],
-         [AS_IF([test "$ndk_ARCH" = "x86_64"],
-           [ndk_matching_libcxx_shared_so=$ndk_candidate])])
-
-      AS_IF([test -n "$ndk_matching_libcxx_shared_so"],
-        [with_ndk_cxx_shared=$ndk_matching_libcxx_shared_so])
-    done])])
-
-AS_IF([test -z "$with_ndk_cxx_shared"],[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.])],
-  [AC_MSG_RESULT([$with_ndk_cxx_shared])])
-
-ndk_CXX_SHARED=$with_ndk_cxx_shared
-
-# These variables have now been found.  Now look for a C++ compiler.
-# Upon failure, pretend the C compiler is a C++ compiler and use that
-# instead.
+# Search for a C++ compiler.  Upon failure, pretend the C compiler is a
+# C++ compiler and use that instead.
 
 ndk_cc_name=`AS_BASENAME(["${ndk_cc_firstword}"])`
 ndk_cxx_name=
@@ -338,8 +354,162 @@ AS_IF([test -n "$with_ndk_cxx"], [CXX=$with_ndk_cxx],
      [], [`AS_DIRNAME(["$ndk_where_cc"])`:$PATH])
    AS_IF([test -z "$CXX"], [CXX=`ndk_filter_cc_for_cxx`],
      [CXX=`ndk_subst_cc_onto_cxx`])])
+
+# None of the C++ standard libraries installed with Android are
+# available to NDK programs, which are expected to select one of several
+# standard libraries distributed with the NDK.  This library must be
+# extracted from the NDK by the program's build system and copied into
+# the application directory, and the build system is also expected to
+# provide the compiler with suitable options to enable it.
+#
+# Emacs, on recent releases of the NDK, prefers the libc++ library, the
+# most complete of the libraries available, when it detects the presence
+# of its headers and libraries in the compiler's search path.  Next in
+# line are the several libraries located in a directory named `cxx-stl'
+# inside the NDK distribution, of which Emacs prefers, in this order,
+# the GNU libstdc++, stlport, gabi and the system C++ library.  The
+# scope of the last two is confined to providing runtime support for
+# basic C++ operations, and is useless for compiling most C++
+# dependencies whose requirements go beyond such operations.
+#
+# The NDK comes in two forms.  In a "combined toolchain", all C++
+# libraries are present in the NDK directory and the responsibility is
+# left to the build system to locate and select the best C++ library,
+# whereas in a "standalone toolchain" an STL will have already been
+# specified a C++ library, besides which no others will be present.
+#
+# Though Android.mk files are provided by the NDK for each such library,
+# Emacs cannot use any of these, both for lack of prebuilt support in
+# its ndk-build implementation, and since they are absent from combined
+# toolchains.
+
+ndk_CXX_SHARED=
+ndk_CXX_STL=
+ndk_CXX_LDFLAGS=
+
+AS_IF([test -n "$CXX" && test -n "$ndk_install_dir"],
+  [ndk_library_dirs=`$CXX -print-search-dirs \
+                      | sed -n "s/^libraries:[[\t ]]*=\?\(.*\)/\1/p"`
+   AS_IF([test "$ndk_toolchain_type" = "standalone"],
+    [dnl With a standalone toolchain, just use the first C++ library
+     dnl present in the compiler's library search path, that being the
+     dnl only C++ library that will ever be present.
+     ndk_save_IFS=$IFS; IFS=:
+     for ndk_dir in $ndk_library_dirs; do
+       if test -d "$ndk_dir"; then :; else
+        continue
+       fi
+       ndk_dir=`cd "$ndk_dir"; pwd`
+       if test -f "$ndk_dir/libc++_shared.so"; then
+         ndk_CXX_SHARED="$ndk_dir/libc++_shared.so"
+         ndk_CXX_LDFLAGS=-lc++_shared; break
+       elif test -f "$ndk_dir/libgnustl_shared.so"; then
+         ndk_CXX_SHARED="$ndk_dir/libgnustl_shared.so"
+         ndk_CXX_LDFLAGS=-lgnustl_shared; break
+       elif test -f "$ndk_dir/libstlport_shared.so"; then
+         ndk_CXX_SHARED="$ndk_dir/libstlport_shared.so"
+        ndk_CXX_LDFLAGS=-lstlport_shared; break
+       fi
+     done
+     IFS=$ndk_save_IFS],
+    [dnl Otherwise, search for a suitable standard library
+     dnl in the order stated above.
+     dnl
+     dnl Detect if this compiler is configured to link against libc++ by
+     dnl default.
+     AC_MSG_CHECKING([whether compiler defaults to libc++])
+     cat <<_ACEOF >conftest.cc
+#include <string>
+#ifndef _LIBCPP_VERSION
+Not libc++!
+#endif /* _LIBCPP_VERSION */
+
+int
+main (void)
+{
+
+}
+_ACEOF
+     AS_IF([$CXX conftest.cc -o conftest.o >&AS_MESSAGE_LOG_FD 2>&1],
+       [dnl The compiler defaults to libc++.
+        AC_MSG_RESULT([yes])
+       ndk_save_IFS=$IFS; IFS=:
+       for ndk_dir in $ndk_library_dirs; do
+         if test -f "$ndk_dir/libc++_shared.so"; then
+           ndk_CXX_SHARED="$ndk_dir/libc++_shared.so"
+           ndk_CXX_LDFLAGS=-lc++_shared; break
+         fi
+       done
+       IFS=$ndk_save_IFS],
+       [dnl Search for gnustl, stlport, gabi, and failing that, system.
+        dnl The name of the gabi system root directory varies by GCC
+        dnl version.
+        AC_MSG_RESULT([no])
+        ndk_gcc_version=`($CXX -v 2>&1) \
+        | sed -n "s/^gcc version \([[0123456789]\+.[0123456789]\+]\).*/\1/p"`
+       cxx_stl="$ndk_install_dir/sources/cxx-stl"
+       ndk_cxx_stl_base="$cxx_stl/gnu-libstdc++/$ndk_gcc_version"
+       AS_IF([test -n "$ndk_gcc_version" \
+              && test -d "$ndk_cxx_stl_base/libs/$ndk_ABI"],
+         [ndk_CXX_LDFLAGS="-L$ndk_cxx_stl_base/libs/$ndk_ABI -lgnustl_shared"
+          ndk_CXX_LDFLAGS="$ndk_CXX_LDFLAGS -lsupc++"
+          ndk_CXX_STL="-isystem $ndk_cxx_stl_base/include"
+          ndk_CXX_STL="$ndk_CXX_STL -isystem 
$ndk_cxx_stl_base/libs/$ndk_ABI/include"
+          
ndk_CXX_SHARED="$ndk_cxx_stl_base/libs/$ndk_ABI/libgnustl_shared.so"])
+       AS_IF([test -f "$ndk_CXX_SHARED"], [],
+         [dnl No STL was located or the library is not reachable.
+          dnl Search for alternatives.
+          ndk_CXX_STL=
+          ndk_CXX_SHARED=
+          ndk_CXX_LDFLAGS=
+          ndk_cxx_stl_base="$cxx_stl/stlport"
+          AS_IF([test -d "$ndk_cxx_stl_base"],
+            [ndk_CXX_LDFLAGS="-L$ndk_cxx_stl_base/libs/$ndk_ABI 
-lstlport_shared"
+             ndk_CXX_STL="-isystem $ndk_cxx_stl_base/stlport"
+             
ndk_CXX_SHARED="$ndk_cxx_stl_base/libs/$ndk_ABI/libstlport_shared.so"])
+           AS_IF([test -f "$ndk_CXX_SHARED"], [],
+            [ndk_CXX_STL=
+             ndk_CXX_SHARED=
+             ndk_CXX_LDFLAGS=
+             ndk_cxx_stl_base="$cxx_stl/gabi++"
+             AS_IF([test -d "$ndk_cxx_stl_base"],
+              [ndk_CXX_LDFLAGS="-L$ndk_cxx_stl_base/libs/$ndk_ABI 
-lgabi++_shared"
+               ndk_CXX_STL="$ndk_CXX_STL -isystem $ndk_cxx_stl_base/include"
+               
ndk_CXX_SHARED="$ndk_cxx_stl_base/libs/$ndk_ABI/lgabi++_shared.so"])])
+           AS_IF([test -f "$ndk_CXX_SHARED"], [],
+            [ndk_CXX_STL=
+             ndk_CXX_SHARED=
+             ndk_CXX_LDFLAGS=
+             ndk_cxx_stl_base="$cxx_stl/system"
+             AS_IF([test -d "$ndk_cxx_stl_base"],
+              [ndk_CXX_LDFLAGS="-L$ndk_cxx_stl_base/libs/$ndk_ABI -lstdc++"
+                ndk_CXX_STL="-isystem $ndk_cxx_stl_base/include"
+               dnl The "system" library is distributed with Android and
+               dnl need not be present in app packages.
+               ndk_CXX_SHARED=
+               dnl Done.
+               ])])])])
+     rm -f conftest.o])])
+
+AS_ECHO([])
+AS_ECHO(["C++ compiler configuration: "])
+AS_ECHO([])
+AS_ECHO(["Library includes        : $ndk_CXX_STL"])
+AS_ECHO(["Linker options          : $ndk_CXX_LDFLAGS"])
+AS_ECHO(["Library file (if any)   : $ndk_CXX_SHARED"])
+AS_ECHO([])
 ])
 
+# ndk_LATE_EARLY
+# --------------
+# Call before ndk_LATE to establish certain variables in time for
+# ndk_LATE's C++ compiler detection.
+
+AC_DEFUN([ndk_LATE_EARLY],
+[ndk_save_LDFLAGS="$LDFLAGS"
+ LDFLAGS="$LDFLAGS $ndk_CXX_LDFLAGS"
+ CXXFLAGS="$CXXFLAGS `ndk_subst_cflags_onto_cxx` $ndk_CXX_STL"])
+
 # ndk_LATE
 # --------
 # Perform late initialization of the ndk-build system by checking for
@@ -347,17 +517,14 @@ AS_IF([test -n "$with_ndk_cxx"], [CXX=$with_ndk_cxx],
 
 AC_DEFUN([ndk_LATE],
 [dnl
-dnl This calls AC_REQUIRE([AC_PROG_CXX]), leading to configure looking
-dnl for a C++ compiler.  However, the language is not restored
-dnl afterwards if not `$ndk_INITIALIZED'.
 AS_IF([test "$ndk_INITIALIZED" = "yes"],[
-  AS_IF([test -n "$CXX"], [AC_LANG_PUSH([C++])
+  AS_IF([test -n "$CXX"], [
+    AC_LANG_PUSH([C++])
     AC_CHECK_HEADER([string], [ndk_working_cxx=yes],
-      [AC_MSG_WARN([Your C++ compiler is not properly set up, and\
- the standard library headers could not be found.])])
+      [AC_MSG_WARN([Your C++ compiler is not properly configured, as \
+the standard library headers could not be found.])])
     AC_LANG_POP([C++])])])
-dnl Thus, manually switch back to C here.
-AC_LANG([C])
+LDFLAGS="$ndk_save_LDFLAGS"
 ])
 
 # ndk_SEARCH_MODULE(MODULE, NAME, ACTION-IF-FOUND, [ACTION-IF-NOT-FOUND])
@@ -396,13 +563,14 @@ else
     ndk_ANY_CXX=yes
   fi
 
-  AS_IF([test "$ndk_ANY_CXX" = "yes" && test -z "$with_ndk_cxx_shared"],
-    [AC_MSG_ERROR([The module $1 requires the C++ standard library \
-(libc++_shared.so), but it was not found.])])
+  AS_IF([test "$module_cxx_deps" = "yes" && test -z "$ndk_CXX_STL" \
+         && test -z "$ndk_CXX_LDFLAGS"],
+    [AC_MSG_ERROR([The module $1 requires a C++ standard library,
+but none were found.])])
 
-  AS_IF([test "$ndk_ANY_CXX" = "yes" && test "$ndk_working_cxx" != "yes"],
-    [AC_MSG_ERROR([The module [$]1 requires the C++ standard library \
-(libc++_shared.so), but a working C++ compiler was not found.])])
+  AS_IF([test "$module_cxx_deps" = "yes" && test "$ndk_working_cxx" != "yes"],
+    [AC_MSG_ERROR([The module [$]1 requires the C++ standard library,
+but a working C++ compiler was not found.])])
 
   $2[]_CFLAGS="[$]$2[]_CFLAGS $module_cflags $module_includes"
   $2[]_LIBS="[$]$2[]_LIBS $module_ldflags"
@@ -457,6 +625,8 @@ AC_DEFUN_ONCE([ndk_CONFIG_FILES],
     NDK_BUILD_AR=$AR
     NDK_BUILD_MODULES="$ndk_MODULES"
     NDK_BUILD_CXX_SHARED="$ndk_CXX_SHARED"
+    NDK_BUILD_CXX_STL="$ndk_CXX_STL"
+    NDK_BUILD_CXX_LDFLAGS="$ndk_CXX_LDFLAGS"
     NDK_BUILD_ANY_CXX_MODULE=$ndk_ANY_CXX
     NDK_BUILD_CFLAGS="$ndk_BUILD_CFLAGS"
 
@@ -470,6 +640,8 @@ AC_DEFUN_ONCE([ndk_CONFIG_FILES],
     AC_SUBST([NDK_BUILD_NASM])
     AC_SUBST([NDK_BUILD_MODULES])
     AC_SUBST([NDK_BUILD_CXX_SHARED])
+    AC_SUBST([NDK_BUILD_CXX_STL])
+    AC_SUBST([NDK_BUILD_CXX_LDFLAGS])
     AC_SUBST([NDK_BUILD_ANY_CXX_MODULE])
     AC_SUBST([NDK_BUILD_CFLAGS])
 



reply via email to

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