# Copyright (C) 2016 The Android Open Source Project # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Configurable variables. # Modeled after the ndk-build system. # For any variables defined in: # https://developer.android.com/ndk/guides/android_mk.html # https://developer.android.com/ndk/guides/application_mk.html # if it makes sense for CMake, then replace LOCAL, APP, or NDK with ANDROID, and # we have that variable below. # # ANDROID_TOOLCHAIN # ANDROID_ABI # ANDROID_PLATFORM # ANDROID_STL # ANDROID_PIE # ANDROID_CPP_FEATURES # ANDROID_ALLOW_UNDEFINED_SYMBOLS # ANDROID_ARM_MODE # ANDROID_DISABLE_FORMAT_STRING_CHECKS # ANDROID_CCACHE # Binocle stuff set(ANDROID_NDK $ENV{ANDROID_NDK_ROOT}) # End of Binocle stuff cmake_minimum_required(VERSION 3.6.0) # CMake invokes the toolchain file twice during the first build, but only once # during subsequent rebuilds. This was causing the various flags to be added # twice on the first build, and on a rebuild ninja would see only one set of the # flags and rebuild the world. # https://github.com/android-ndk/ndk/issues/323 if(ANDROID_NDK_TOOLCHAIN_INCLUDED) return() endif(ANDROID_NDK_TOOLCHAIN_INCLUDED) set(ANDROID_NDK_TOOLCHAIN_INCLUDED true) if(DEFINED ANDROID_USE_LEGACY_TOOLCHAIN_FILE) set(_USE_LEGACY_TOOLCHAIN_FILE ${ANDROID_USE_LEGACY_TOOLCHAIN_FILE}) else() # Default to the legacy toolchain file to avoid changing the behavior of # CMAKE_CXX_FLAGS. See https://github.com/android/ndk/issues/1693. set(_USE_LEGACY_TOOLCHAIN_FILE true) endif() if(_USE_LEGACY_TOOLCHAIN_FILE) include("${CMAKE_CURRENT_LIST_DIR}/android-legacy.toolchain.cmake") return() endif() # Android NDK path get_filename_component(ANDROID_NDK_EXPECTED_PATH "${CMAKE_CURRENT_LIST_DIR}/../.." ABSOLUTE) if(NOT ANDROID_NDK) set(CMAKE_ANDROID_NDK "${ANDROID_NDK_EXPECTED_PATH}") else() # Allow the user to specify their own NDK path, but emit a warning. This is an # uncommon use case, but helpful if users want to use a bleeding edge # toolchain file with a stable NDK. # https://github.com/android-ndk/ndk/issues/473 get_filename_component(ANDROID_NDK "${ANDROID_NDK}" ABSOLUTE) if(NOT "${ANDROID_NDK}" STREQUAL "${ANDROID_NDK_EXPECTED_PATH}") message(WARNING "Using custom NDK path (ANDROID_NDK is set): ${ANDROID_NDK}") endif() set(CMAKE_ANDROID_NDK ${ANDROID_NDK}) endif() unset(ANDROID_NDK_EXPECTED_PATH) file(TO_CMAKE_PATH "${CMAKE_ANDROID_NDK}" CMAKE_ANDROID_NDK) # Android NDK revision # Possible formats: # * r16, build 1234: 16.0.1234 # * r16b, build 1234: 16.1.1234 # * r16 beta 1, build 1234: 16.0.1234-beta1 # # Canary builds are not specially marked. file(READ "${CMAKE_ANDROID_NDK}/source.properties" ANDROID_NDK_SOURCE_PROPERTIES) set(ANDROID_NDK_REVISION_REGEX "^Pkg\\.Desc = Android NDK\nPkg\\.Revision = ([0-9]+)\\.([0-9]+)\\.([0-9]+)(-beta([0-9]+))?") if(NOT ANDROID_NDK_SOURCE_PROPERTIES MATCHES "${ANDROID_NDK_REVISION_REGEX}") message(SEND_ERROR "Failed to parse Android NDK revision: ${CMAKE_ANDROID_NDK}/source.properties.\n${ANDROID_NDK_SOURCE_PROPERTIES}") endif() set(ANDROID_NDK_MAJOR "${CMAKE_MATCH_1}") set(ANDROID_NDK_MINOR "${CMAKE_MATCH_2}") set(ANDROID_NDK_BUILD "${CMAKE_MATCH_3}") set(ANDROID_NDK_BETA "${CMAKE_MATCH_5}") if(ANDROID_NDK_BETA STREQUAL "") set(ANDROID_NDK_BETA "0") endif() set(ANDROID_NDK_REVISION "${ANDROID_NDK_MAJOR}.${ANDROID_NDK_MINOR}.${ANDROID_NDK_BUILD}${CMAKE_MATCH_4}") # Touch toolchain variable to suppress "unused variable" warning. # This happens if CMake is invoked with the same command line the second time. if(CMAKE_TOOLCHAIN_FILE) endif() # Determine the ABI. if(NOT CMAKE_ANDROID_ARCH_ABI) if(ANDROID_ABI STREQUAL "armeabi-v7a with NEON") set(CMAKE_ANDROID_ARCH_ABI armeabi-v7a) elseif(ANDROID_ABI) set(CMAKE_ANDROID_ARCH_ABI ${ANDROID_ABI}) elseif(ANDROID_TOOLCHAIN_NAME MATCHES "^arm-linux-androideabi-") set(CMAKE_ANDROID_ARCH_ABI armeabi-v7a) elseif(ANDROID_TOOLCHAIN_NAME MATCHES "^aarch64-linux-android-") set(CMAKE_ANDROID_ARCH_ABI arm64-v8a) elseif(ANDROID_TOOLCHAIN_NAME MATCHES "^x86-") set(CMAKE_ANDROID_ARCH_ABI x86) elseif(ANDROID_TOOLCHAIN_NAME MATCHES "^x86_64-") set(CMAKE_ANDROID_ARCH_ABI x86_64) else() set(CMAKE_ANDROID_ARCH_ABI armeabi-v7a) endif() endif() if(DEFINED ANDROID_ARM_NEON AND NOT ANDROID_ARM_NEON) message(FATAL_ERROR "Disabling Neon is no longer supported") endif() if(CMAKE_ANDROID_ARCH_ABI STREQUAL "armeabi-v7a") set(CMAKE_ANDROID_ARM_NEON TRUE) if(NOT DEFINED CMAKE_ANDROID_ARM_MODE) if(DEFINED ANDROID_FORCE_ARM_BUILD) set(CMAKE_ANDROID_ARM_MODE ${ANDROID_FORCE_ARM_BUILD}) elseif(DEFINED ANDROID_ARM_MODE) if(ANDROID_ARM_MODE STREQUAL "arm") set(CMAKE_ANDROID_ARM_MODE TRUE) elseif(ANDROID_ARM_MODE STREQUAL "thumb") set(CMAKE_ANDROID_ARM_MODE FALSE) else() message(FATAL_ERROR "Invalid Android ARM mode: ${ANDROID_ARM_MODE}.") endif() endif() endif() endif() # PIE is supported on all currently supported Android releases, but it is not # supported with static executables, so we still provide ANDROID_PIE as an # escape hatch for those. if(NOT DEFINED CMAKE_POSITION_INDEPENDENT_CODE) if(DEFINED ANDROID_PIE) set(CMAKE_POSITION_INDEPENDENT_CODE ${ANDROID_PIE}) elseif(DEFINED ANDROID_APP_PIE) set(CMAKE_POSITION_INDEPENDENT_CODE ${ANDROID_APP_PIE}) else() set(CMAKE_POSITION_INDEPENDENT_CODE TRUE) endif() endif() # Default values for configurable variables. if(NOT ANDROID_TOOLCHAIN) set(ANDROID_TOOLCHAIN clang) elseif(ANDROID_TOOLCHAIN STREQUAL gcc) message(FATAL_ERROR "GCC is no longer supported. See " "https://android.googlesource.com/platform/ndk/+/master/docs/ClangMigration.md.") endif() if(ANDROID_NATIVE_API_LEVEL AND NOT ANDROID_PLATFORM) if(ANDROID_NATIVE_API_LEVEL MATCHES "^android-[0-9]+$") set(ANDROID_PLATFORM ${ANDROID_NATIVE_API_LEVEL}) elseif(ANDROID_NATIVE_API_LEVEL MATCHES "^[0-9]+$") set(ANDROID_PLATFORM android-${ANDROID_NATIVE_API_LEVEL}) endif() endif() include(${CMAKE_ANDROID_NDK}/build/cmake/adjust_api_level.cmake) adjust_api_level("${ANDROID_PLATFORM}" CMAKE_SYSTEM_VERSION) if(NOT DEFINED CMAKE_ANDROID_STL_TYPE AND DEFINED ANDROID_STL) set(CMAKE_ANDROID_STL_TYPE ${ANDROID_STL}) endif() if("${CMAKE_ANDROID_STL_TYPE}" STREQUAL "gnustl_shared" OR "${CMAKE_ANDROID_STL_TYPE}" STREQUAL "gnustl_static" OR "${CMAKE_ANDROID_STL_TYPE}" STREQUAL "stlport_shared" OR "${CMAKE_ANDROID_STL_TYPE}" STREQUAL "stlport_static") message(FATAL_ERROR "\ ${CMAKE_ANDROID_STL_TYPE} is no longer supported. Please switch to either c++_shared \ or c++_static. See https://developer.android.com/ndk/guides/cpp-support.html \ for more information.") endif() # Standard cross-compiling stuff. set(CMAKE_SYSTEM_NAME Android) # STL. if(ANDROID_STL) set(CMAKE_ANDROID_STL_TYPE ${ANDROID_STL}) endif() if(NDK_CCACHE AND NOT ANDROID_CCACHE) set(ANDROID_CCACHE "${NDK_CCACHE}") endif() if(ANDROID_CCACHE) set(CMAKE_C_COMPILER_LAUNCHER "${ANDROID_CCACHE}") set(CMAKE_CXX_COMPILER_LAUNCHER "${ANDROID_CCACHE}") endif() # Configuration specific flags. if(ANDROID_STL_FORCE_FEATURES AND NOT DEFINED ANDROID_CPP_FEATURES) set(ANDROID_CPP_FEATURES "rtti exceptions") endif() if(ANDROID_CPP_FEATURES) separate_arguments(ANDROID_CPP_FEATURES) foreach(feature ${ANDROID_CPP_FEATURES}) if(NOT ${feature} MATCHES "^(rtti|exceptions|no-rtti|no-exceptions)$") message(FATAL_ERROR "Invalid Android C++ feature: ${feature}.") endif() if(${feature} STREQUAL "rtti") set(CMAKE_ANDROID_RTTI TRUE) endif() if(${feature} STREQUAL "no-rtti") set(CMAKE_ANDROID_RTTI FALSE) endif() if(${feature} STREQUAL "exceptions") set(CMAKE_ANDROID_EXCEPTIONS TRUE) endif() if(${feature} STREQUAL "no-exceptions") set(CMAKE_ANDROID_EXCEPTIONS FALSE) endif() endforeach() string(REPLACE ";" " " ANDROID_CPP_FEATURES "${ANDROID_CPP_FEATURES}") endif() # Export configurable variables for the try_compile() command. set(CMAKE_TRY_COMPILE_PLATFORM_VARIABLES ANDROID_ABI ANDROID_ALLOW_UNDEFINED_SYMBOLS ANDROID_ARM_MODE ANDROID_ARM_NEON ANDROID_CCACHE ANDROID_CPP_FEATURES ANDROID_DISABLE_FORMAT_STRING_CHECKS ANDROID_PIE ANDROID_PLATFORM ANDROID_STL ANDROID_TOOLCHAIN ANDROID_USE_LEGACY_TOOLCHAIN_FILE ) if(DEFINED ANDROID_NO_UNDEFINED AND NOT DEFINED ANDROID_ALLOW_UNDEFINED_SYMBOLS) if(ANDROID_NO_UNDEFINED) set(ANDROID_ALLOW_UNDEFINED_SYMBOLS FALSE) else() set(ANDROID_ALLOW_UNDEFINED_SYMBOLS TRUE) endif() endif() if(DEFINED ANDROID_SO_UNDEFINED AND NOT DEFINED ANDROID_ALLOW_UNDEFINED_SYMBOLS) set(ANDROID_ALLOW_UNDEFINED_SYMBOLS "${ANDROID_SO_UNDEFINED}") endif() # Exports compatible variables defined in exports.cmake. set(_ANDROID_EXPORT_COMPATIBILITY_VARIABLES TRUE) if(CMAKE_HOST_SYSTEM_NAME STREQUAL Linux) set(ANDROID_HOST_TAG linux-x86_64) elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL Darwin) set(ANDROID_HOST_TAG darwin-x86_64) elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL Windows) set(ANDROID_HOST_TAG windows-x86_64) endif() # Toolchain. set(ANDROID_TOOLCHAIN_ROOT "${CMAKE_ANDROID_NDK}/toolchains/llvm/prebuilt/${ANDROID_HOST_TAG}") # NB: This variable causes CMake to automatically pass --sysroot to the # toolchain. Studio currently relies on this to recognize Android builds. If # this variable is removed, ensure that flag is still passed. # TODO: Teach Studio to recognize Android builds based on --target. set(CMAKE_SYSROOT "${ANDROID_TOOLCHAIN_ROOT}/sysroot")