Android: Use unified toolchain in NDK r19+

The NDK build system now uses only a single toolchain in

    <ndk>/toolchains/llvm/prebuilt/<host>

Its compilers are always `bin/{clang,clang++}` and its binutils are
always `bin/<triple>-*`.  It is a standalone toolchain:

* The Anrdoid API level is specified at the end of `--target=`.
* The standard library may be specified via `-stdlib=`.
* No need to pass system includes or libraries explicitly.
* No need to pass `--sysroot` or `-gcc-toolchain`.

Teach CMake to recognize NDK versions that have a unified
toolchain with its own sysroot and use the above approach.

Fixes: #18739
This commit is contained in:
Brad King
2019-07-26 12:48:35 -04:00
parent 19f36c5fb2
commit 97bca2f9fa
18 changed files with 106 additions and 18 deletions

View File

@@ -40,6 +40,9 @@ macro(__android_compiler_clang lang)
endif()
if(NOT CMAKE_${lang}_COMPILER_TARGET)
set(CMAKE_${lang}_COMPILER_TARGET "${_ANDROID_ABI_CLANG_TARGET}")
if(CMAKE_ANDROID_NDK_TOOLCHAIN_UNIFIED)
string(APPEND CMAKE_${lang}_COMPILER_TARGET "${CMAKE_SYSTEM_VERSION}")
endif()
list(APPEND CMAKE_${lang}_COMPILER_PREDEFINES_COMMAND "--target=${CMAKE_${lang}_COMPILER_TARGET}")
endif()
endmacro()

View File

@@ -47,7 +47,41 @@ if(CMAKE_ANDROID_NDK)
endif()
if(CMAKE_ANDROID_STL_TYPE)
if(CMAKE_ANDROID_NDK)
if(CMAKE_ANDROID_NDK_TOOLCHAIN_UNIFIED)
if(CMAKE_ANDROID_STL_TYPE STREQUAL "system")
set(_ANDROID_STL_EXCEPTIONS 0)
set(_ANDROID_STL_RTTI 0)
macro(__android_stl lang)
string(APPEND CMAKE_${lang}_FLAGS_INIT " -stdlib=libstdc++")
endmacro()
elseif(CMAKE_ANDROID_STL_TYPE STREQUAL "c++_static")
set(_ANDROID_STL_EXCEPTIONS 1)
set(_ANDROID_STL_RTTI 1)
macro(__android_stl lang)
string(APPEND CMAKE_${lang}_FLAGS_INIT " -stdlib=libc++")
string(APPEND CMAKE_${lang}_STANDARD_LIBRARIES " -static-libstdc++")
endmacro()
elseif(CMAKE_ANDROID_STL_TYPE STREQUAL "c++_shared")
set(_ANDROID_STL_EXCEPTIONS 1)
set(_ANDROID_STL_RTTI 1)
macro(__android_stl lang)
string(APPEND CMAKE_${lang}_FLAGS_INIT " -stdlib=libc++")
endmacro()
elseif(CMAKE_ANDROID_STL_TYPE STREQUAL "none")
set(_ANDROID_STL_RTTI 0)
set(_ANDROID_STL_EXCEPTIONS 0)
macro(__android_stl lang)
# FIXME: Add a way to add project-wide language-specific compile-only flags.
set(CMAKE_CXX_COMPILE_OBJECT
"<CMAKE_CXX_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -o <OBJECT> -c <SOURCE> -nostdinc++")
string(APPEND CMAKE_${lang}_STANDARD_LIBRARIES " -nostdlib++")
endmacro()
else()
message(FATAL_ERROR
"Android: STL '${CMAKE_ANDROID_STL_TYPE}' not supported by this NDK."
)
endif()
elseif(CMAKE_ANDROID_NDK)
macro(__android_stl_inc lang dir req)
if(EXISTS "${dir}")
@@ -152,6 +186,10 @@ macro(__android_compiler_common lang)
__android_stl(CXX)
endif()
if(CMAKE_ANDROID_NDK_TOOLCHAIN_UNIFIED)
string(APPEND CMAKE_${lang}_STANDARD_LIBRARIES " -latomic -lm")
endif()
# <ndk>/build/core/definitions.mk appends the sysroot's include directory
# explicitly at the end of the command-line include path so that it
# precedes the toolchain's builtin include directories. This is
@@ -161,7 +199,7 @@ macro(__android_compiler_common lang)
#
# Do not do this for a standalone toolchain because it is already
# tied to a specific API version.
if(CMAKE_ANDROID_NDK)
if(CMAKE_ANDROID_NDK AND NOT CMAKE_ANDROID_NDK_TOOLCHAIN_UNIFIED)
if(CMAKE_SYSROOT_COMPILE)
set(_cmake_sysroot_compile "${CMAKE_SYSROOT_COMPILE}")
else()

View File

@@ -221,8 +221,15 @@ if(CMAKE_ANDROID_NDK)
else()
message(FATAL_ERROR "Android: Builds hosted on '${CMAKE_HOST_SYSTEM_NAME}' not supported.")
endif()
# Look for a unified toolchain/sysroot provided with the NDK.
set(CMAKE_ANDROID_NDK_TOOLCHAIN_UNIFIED "${CMAKE_ANDROID_NDK}/toolchains/llvm/prebuilt/${CMAKE_ANDROID_NDK_TOOLCHAIN_HOST_TAG}")
if(NOT IS_DIRECTORY "${CMAKE_ANDROID_NDK_TOOLCHAIN_UNIFIED}/sysroot")
set(CMAKE_ANDROID_NDK_TOOLCHAIN_UNIFIED "")
endif()
else()
set(CMAKE_ANDROID_NDK_TOOLCHAIN_HOST_TAG "")
set(CMAKE_ANDROID_NDK_TOOLCHAIN_UNIFIED "")
endif()
# https://developer.android.com/ndk/guides/abis.html
@@ -370,6 +377,7 @@ if(CMAKE_ANDROID_NDK)
"set(CMAKE_ANDROID_ARCH_TRIPLE \"${CMAKE_ANDROID_ARCH_TRIPLE}\")\n"
"set(CMAKE_ANDROID_NDK_DEPRECATED_HEADERS \"${CMAKE_ANDROID_NDK_DEPRECATED_HEADERS}\")\n"
"set(CMAKE_ANDROID_NDK_TOOLCHAIN_HOST_TAG \"${CMAKE_ANDROID_NDK_TOOLCHAIN_HOST_TAG}\")\n"
"set(CMAKE_ANDROID_NDK_TOOLCHAIN_UNIFIED \"${CMAKE_ANDROID_NDK_TOOLCHAIN_UNIFIED}\")\n"
)
endif()

View File

@@ -19,6 +19,11 @@ endif()
set(CMAKE_BUILD_TYPE_INIT Debug)
# Skip sysroot selection if the NDK has a unified toolchain.
if(CMAKE_ANDROID_NDK_TOOLCHAIN_UNIFIED)
return()
endif()
if(NOT CMAKE_SYSROOT)
if(CMAKE_ANDROID_NDK)
set(CMAKE_SYSROOT "${CMAKE_ANDROID_NDK}/platforms/android-${CMAKE_SYSTEM_VERSION}/arch-${CMAKE_ANDROID_ARCH}")

View File

@@ -1,6 +1,31 @@
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.
# In Android NDK r19 and above there is a single clang toolchain.
if(CMAKE_ANDROID_NDK_TOOLCHAIN_UNIFIED)
if(CMAKE_ANDROID_NDK_TOOLCHAIN_VERSION AND NOT CMAKE_ANDROID_NDK_TOOLCHAIN_VERSION STREQUAL "clang")
message(FATAL_ERROR
"Android: The CMAKE_ANDROID_NDK_TOOLCHAIN_VERSION value '${CMAKE_ANDROID_NDK_TOOLCHAIN_VERSION}' "
"is not supported by this NDK. It must be 'clang' or not set at all."
)
endif()
message(STATUS "Android: Selected unified Clang toolchain")
set(_ANDROID_TOOL_NDK_TOOLCHAIN_VERSION "clang")
set(_ANDROID_TOOL_C_COMPILER "${CMAKE_ANDROID_NDK_TOOLCHAIN_UNIFIED}/bin/clang${_ANDROID_HOST_EXT}")
set(_ANDROID_TOOL_C_TOOLCHAIN_MACHINE "${CMAKE_ANDROID_ARCH_TRIPLE}")
set(_ANDROID_TOOL_C_TOOLCHAIN_VERSION "")
set(_ANDROID_TOOL_C_COMPILER_EXTERNAL_TOOLCHAIN "")
set(_ANDROID_TOOL_C_TOOLCHAIN_PREFIX "${CMAKE_ANDROID_NDK_TOOLCHAIN_UNIFIED}/bin/${CMAKE_ANDROID_ARCH_TRIPLE}-")
set(_ANDROID_TOOL_C_TOOLCHAIN_SUFFIX "${_ANDROID_HOST_EXT}")
set(_ANDROID_TOOL_CXX_COMPILER "${CMAKE_ANDROID_NDK_TOOLCHAIN_UNIFIED}/bin/clang++${_ANDROID_HOST_EXT}")
set(_ANDROID_TOOL_CXX_TOOLCHAIN_MACHINE "${CMAKE_ANDROID_ARCH_TRIPLE}")
set(_ANDROID_TOOL_CXX_TOOLCHAIN_VERSION "")
set(_ANDROID_TOOL_CXX_COMPILER_EXTERNAL_TOOLCHAIN "")
set(_ANDROID_TOOL_CXX_TOOLCHAIN_PREFIX "${CMAKE_ANDROID_NDK_TOOLCHAIN_UNIFIED}/bin/${CMAKE_ANDROID_ARCH_TRIPLE}-")
set(_ANDROID_TOOL_CXX_TOOLCHAIN_SUFFIX "${_ANDROID_HOST_EXT}")
return()
endif()
# In Android NDK releases there is build system toolchain selection logic in
# these files:
#

View File

@@ -3,7 +3,7 @@ string(APPEND _ANDROID_ABI_INIT_CFLAGS
" -no-canonical-prefixes"
)
if(CMAKE_ANDROID_NDK AND NOT CMAKE_ANDROID_NDK_DEPRECATED_HEADERS)
if(CMAKE_ANDROID_NDK AND NOT CMAKE_ANDROID_NDK_TOOLCHAIN_UNIFIED AND NOT CMAKE_ANDROID_NDK_DEPRECATED_HEADERS)
string(APPEND _ANDROID_ABI_INIT_CFLAGS " -D__ANDROID_API__=${CMAKE_SYSTEM_VERSION}")
endif()