Improve support for building Android C++ dependencies

* configure.ac: Call ndk_LATE after gl_EARLY.
* cross/ndk-build/Makefile.in (NDK_BUILD_CXX): New variable.
* cross/ndk-build/ndk-build-shared-library.mk:
* cross/ndk-build/ndk-build-static-library.mk: Use it.
* java/INSTALL: Describe how to build C++ dependencies.
* m4/ndk-build.m4 (ndk_LATE): New macro.
(ndk_INIT): Try to find a suitable C++ compiler.
(ndk_CHECK_MODULES): Make sure the C++ compiler works before
allowing C++ dependencies.
This commit is contained in:
Po Lu 2023-03-04 11:19:25 +08:00
parent 0d363aded1
commit 0e995d06a8
6 changed files with 114 additions and 10 deletions

View file

@ -173,6 +173,7 @@ if test "$XCONFIGURE" = "android"; then
# 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])
fi
@ -1155,6 +1156,7 @@ package will likely install on older systems but crash on startup.])
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" \
$0 $passthrough], [],
[AC_MSG_ERROR([Failed to cross-configure Emacs for android.])])
@ -1472,6 +1474,7 @@ AC_DEFUN([gt_TYPE_WINT_T],
# Initialize gnulib right after choosing the compiler.
dnl Amongst other things, this sets AR and ARFLAGS.
gl_EARLY
ndk_LATE
if test "$ac_test_CFLAGS" != set; then
# It's helpful to have C macros available to GDB, so prefer -g3 to -g

View file

@ -29,6 +29,7 @@ NDK_BUILD_ANDROID_MK = @NDK_BUILD_ANDROID_MK@
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@

View file

@ -46,7 +46,7 @@ else
ifeq (x$(suffix $(1)),x.$(or $(LOCAL_CPP_EXTENSION),cpp))
$(call objname,$(LOCAL_MODULE),$(basename $(1))): $(call maybe-absolute,$(1))
$(NDK_BUILD_CC) -c $$< -o $$@ $(NDK_CFLAGS_$(LOCAL_MODULE)) $(NDK_BUILD_CFLAGS_CXX) $(NDK_CXXFLAGS_$(LOCAL_MODULE))
$(NDK_BUILD_CXX) -c $$< -o $$@ $(NDK_CFLAGS_$(LOCAL_MODULE)) $(NDK_BUILD_CFLAGS_CXX) $(NDK_CXXFLAGS_$(LOCAL_MODULE))
else
ifneq ($(or $(call eq,x$(suffix $(1)),x.s),$(call eq,x$(suffix $(1)),x.S)),)
@ -59,7 +59,7 @@ ifneq (x$(suffix $(1)),x.asm)
ifeq (x$(suffix $(1)),x.cc)
$(call objname,$(LOCAL_MODULE),$(basename $(1))): $(call maybe-absolute,$(1),$(2))
$(NDK_BUILD_CC) -c $$< -o $$@ $(NDK_CFLAGS_$(LOCAL_MODULE)) $(NDK_BUILD_CFLAGS_CXX) $(NDK_CXXFLAGS_$(LOCAL_MODULE))
$(NDK_BUILD_CXX) -c $$< -o $$@ $(NDK_CFLAGS_$(LOCAL_MODULE)) $(NDK_BUILD_CFLAGS_CXX) $(NDK_CXXFLAGS_$(LOCAL_MODULE))
else
$$(error Unsupported suffix: $(suffix $(1)))

View file

@ -34,7 +34,7 @@ else
ifeq (x$(suffix $(1)),x.$(or $(LOCAL_CPP_EXTENSION),cpp))
$(call objname,$(LOCAL_MODULE),$(basename $(1))): $(call maybe-absolute,$(1),$(2))
$(NDK_BUILD_CC) -c $$< -o $$@ $(NDK_BUILD_CFLAGS_CXX) $(NDK_CFLAGS_$(LOCAL_MODULE)) $(NDK_CXXFLAGS_$(LOCAL_MODULE))
$(NDK_BUILD_CXX) -c $$< -o $$@ $(NDK_BUILD_CFLAGS_CXX) $(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)),)
@ -47,7 +47,7 @@ ifneq (x$(suffix $(1)),x.asm)
ifeq (x$(suffix $(1)),x.cc)
$(call objname,$(LOCAL_MODULE),$(basename $(1))): $(call maybe-absolute,$(1),$(2))
$(NDK_BUILD_CC) -c $$< -o $$@ $(NDK_BUILD_CFLAGS_CXX) $(NDK_CFLAGS_$(LOCAL_MODULE)) $(NDK_CXXFLAGS_$(LOCAL_MODULE))
$(NDK_BUILD_CXX) -c $$< -o $$@ $(NDK_BUILD_CFLAGS_CXX) $(NDK_CFLAGS_$(LOCAL_MODULE)) $(NDK_CXXFLAGS_$(LOCAL_MODULE))
else
$$(error Unsupported suffix: $(suffix $(1)))

View file

@ -111,6 +111,24 @@ Emacs package cannot be compressed in builds for Android 2.2. As a
result, the Emacs package will be approximately 100 megabytes larger
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 futher 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++
DEBUG AND RELEASE BUILDS

View file

@ -25,6 +25,10 @@ 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])])
# ndk_INIT(ABI, API, DIR, CFLAGS)
# -------------------------------
# Initialize the Android NDK. ABI is the ABI being built for.
@ -54,6 +58,7 @@ ndk_API=$2
ndk_DIR=$3
ndk_ANY_CXX=
ndk_BUILD_CFLAGS="$4"
ndk_working_cxx=no
AS_CASE(["$ndk_ABI"],
[*arm64*], [ndk_ARCH=arm64],
@ -169,6 +174,10 @@ that could not be found in the list of directories specified in \
[AC_MSG_ERROR([The module [$]1 requires the C++ standard library \
(libc++_shared.so), but it was not 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.])])
AC_MSG_RESULT([yes])
# Make sure the module is prepended.
@ -181,6 +190,44 @@ that could not be found in the list of directories specified in \
done
}
# ndk_filter_cc_for_cxx
# ---------------------
# Run through $CC, removing any options that are not suitable for
# use in a C++ compiler.
ndk_filter_cc_for_cxx () {
for ndk_word in $CC; do
AS_CASE([$ndk_word], [*-std=*], [],
[AS_ECHO_N(["$ndk_word "])])
done
}
# ndk_subst_cc_onto_cxx
# ---------------------
# Print the value of $CXX, followed by any innocent looking options
# in $CC.
ndk_subst_cc_onto_cxx () {
AS_ECHO_N(["$CXX "])
ndk_flag=
for ndk_word in `AS_ECHO_N(["$CC"]) | cut -s -f2- -d' '`; do
AS_IF([test "$ndk_flag" = "yes"],
[AS_ECHO_N(["$ndk_word "])],
[AS_CASE([$ndk_word],
[*-sysroot=*],
[AS_ECHO_N(["$ndk_word "])],
[*-isystem*],
[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 "])])])
ndk_flag=no
done
}
# Look for a suitable ar in the same directory as the C compiler.
ndk_cc_firstword=`AS_ECHO(["$CC"]) | cut -d' ' -f1`
ndk_where_cc=`which $ndk_cc_firstword`
@ -209,7 +256,7 @@ 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 `dirname "$ndk_where_cc"`
cd `AS_DIRNAME(["$ndk_where_cc"])`
# Now, keep moving backwards until pwd ends with ``toolchains''.
while :; do
@ -264,7 +311,37 @@ name of an appropriate ``libc++_shared.so'' binary.])],
ndk_CXX_SHARED=$with_ndk_cxx_shared
# These variables have now been found.
# 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.
ndk_cc_name=`AS_BASENAME(["${ndk_cc_firstword}"])`
ndk_cxx_name=
AS_CASE([$ndk_cc_name], [*-gcc],
[ndk_cxx_name=`AS_ECHO([$ndk_cc_name]) | sed 's/gcc/g++/'`],
[ndk_cxx_name="${ndk_cc_name}++"])
AS_IF([test -n "$with_ndk_cxx"], [CXX=$with_ndk_cxx],
[AC_PATH_PROGS([CXX], [$ndk_cxx_name],
[], [`AS_DIRNAME(["$ndk_where_cc"])`:$PATH])
AS_IF([test -z "$CXX"], [CXX=`ndk_filter_cc_for_cxx`],
[CXX=`ndk_subst_cc_onto_cxx`])])
])
# ndk_LATE
# --------
# Perform late initialization of the ndk-build system by checking for
# required C and C++ headers.
AC_DEFUN([ndk_LATE],
[
AS_IF([test "$ndk_INITIALIZED" = "yes"],[
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_LANG_POP([C++])])])
])
# ndk_SEARCH_MODULE(MODULE, NAME, ACTION-IF-FOUND, [ACTION-IF-NOT-FOUND])
@ -303,10 +380,13 @@ else
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
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 "$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.])])
$2[]_CFLAGS="[$]$2[]_CFLAGS $module_cflags $module_includes"
$2[]_LIBS="[$]$2[]_LIBS $module_ldflags"
@ -357,6 +437,7 @@ AC_DEFUN_ONCE([ndk_CONFIG_FILES],
NDK_BUILD_ABI=$ndk_ABI
NDK_BUILD_SDK=$ndk_API
NDK_BUILD_CC=$CC
NDK_BUILD_CXX=$CXX
NDK_BUILD_AR=$AR
NDK_BUILD_MODULES="$ndk_MODULES"
NDK_BUILD_CXX_SHARED="$ndk_CXX_SHARED"
@ -368,6 +449,7 @@ AC_DEFUN_ONCE([ndk_CONFIG_FILES],
AC_SUBST([NDK_BUILD_ABI])
AC_SUBST([NDK_BUILD_SDK])
AC_SUBST([NDK_BUILD_CC])
AC_SUBST([NDK_BUILD_CXX])
AC_SUBST([NDK_BUILD_AR])
AC_SUBST([NDK_BUILD_NASM])
AC_SUBST([NDK_BUILD_MODULES])