android.toolchain.cmake 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719
  1. # Copyright (C) 2016 The Android Open Source Project
  2. #
  3. # Licensed under the Apache License, Version 2.0 (the "License");
  4. # you may not use this file except in compliance with the License.
  5. # You may obtain a copy of the License at
  6. #
  7. # http://www.apache.org/licenses/LICENSE-2.0
  8. #
  9. # Unless required by applicable law or agreed to in writing, software
  10. # distributed under the License is distributed on an "AS IS" BASIS,
  11. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. # See the License for the specific language governing permissions and
  13. # limitations under the License.
  14. # Configurable variables.
  15. # Modeled after the ndk-build system.
  16. # For any variables defined in:
  17. # https://developer.android.com/ndk/guides/android_mk.html
  18. # https://developer.android.com/ndk/guides/application_mk.html
  19. # if it makes sense for CMake, then replace LOCAL, APP, or NDK with ANDROID, and
  20. # we have that variable below.
  21. #
  22. # ANDROID_TOOLCHAIN
  23. # ANDROID_ABI
  24. # ANDROID_PLATFORM
  25. # ANDROID_STL
  26. # ANDROID_PIE
  27. # ANDROID_CPP_FEATURES
  28. # ANDROID_ALLOW_UNDEFINED_SYMBOLS
  29. # ANDROID_ARM_MODE
  30. # ANDROID_ARM_NEON
  31. # ANDROID_DISABLE_FORMAT_STRING_CHECKS
  32. # ANDROID_CCACHE
  33. cmake_minimum_required(VERSION 3.6.0)
  34. # Inhibit all of CMake's own NDK handling code.
  35. set(CMAKE_SYSTEM_VERSION 1)
  36. # CMake invokes the toolchain file twice during the first build, but only once
  37. # during subsequent rebuilds. This was causing the various flags to be added
  38. # twice on the first build, and on a rebuild ninja would see only one set of the
  39. # flags and rebuild the world.
  40. # https://github.com/android-ndk/ndk/issues/323
  41. if(ANDROID_NDK_TOOLCHAIN_INCLUDED)
  42. return()
  43. endif(ANDROID_NDK_TOOLCHAIN_INCLUDED)
  44. set(ANDROID_NDK_TOOLCHAIN_INCLUDED true)
  45. # Android NDK
  46. get_filename_component(ANDROID_NDK_EXPECTED_PATH
  47. "${CMAKE_CURRENT_LIST_DIR}/../.." ABSOLUTE)
  48. if(NOT ANDROID_NDK)
  49. set(ANDROID_NDK "${ANDROID_NDK_EXPECTED_PATH}")
  50. else()
  51. # Allow the user to specify their own NDK path, but emit a warning. This is an
  52. # uncommon use case, but helpful if users want to use a bleeding edge
  53. # toolchain file with a stable NDK.
  54. # https://github.com/android-ndk/ndk/issues/473
  55. get_filename_component(ANDROID_NDK "${ANDROID_NDK}" ABSOLUTE)
  56. if(NOT "${ANDROID_NDK}" STREQUAL "${ANDROID_NDK_EXPECTED_PATH}")
  57. message(WARNING "Using custom NDK path (ANDROID_NDK is set): ${ANDROID_NDK}")
  58. endif()
  59. endif()
  60. unset(ANDROID_NDK_EXPECTED_PATH)
  61. file(TO_CMAKE_PATH "${ANDROID_NDK}" ANDROID_NDK)
  62. # Android NDK revision
  63. # Possible formats:
  64. # * r16, build 1234: 16.0.1234
  65. # * r16b, build 1234: 16.1.1234
  66. # * r16 beta 1, build 1234: 16.0.1234-beta1
  67. #
  68. # Canary builds are not specially marked.
  69. file(READ "${ANDROID_NDK}/source.properties" ANDROID_NDK_SOURCE_PROPERTIES)
  70. set(ANDROID_NDK_REVISION_REGEX
  71. "^Pkg\\.Desc = Android NDK\nPkg\\.Revision = ([0-9]+)\\.([0-9]+)\\.([0-9]+)(-beta([0-9]+))?")
  72. if(NOT ANDROID_NDK_SOURCE_PROPERTIES MATCHES "${ANDROID_NDK_REVISION_REGEX}")
  73. message(SEND_ERROR "Failed to parse Android NDK revision: ${ANDROID_NDK}/source.properties.\n${ANDROID_NDK_SOURCE_PROPERTIES}")
  74. endif()
  75. set(ANDROID_NDK_MAJOR "${CMAKE_MATCH_1}")
  76. set(ANDROID_NDK_MINOR "${CMAKE_MATCH_2}")
  77. set(ANDROID_NDK_BUILD "${CMAKE_MATCH_3}")
  78. set(ANDROID_NDK_BETA "${CMAKE_MATCH_5}")
  79. if(ANDROID_NDK_BETA STREQUAL "")
  80. set(ANDROID_NDK_BETA "0")
  81. endif()
  82. set(ANDROID_NDK_REVISION
  83. "${ANDROID_NDK_MAJOR}.${ANDROID_NDK_MINOR}.${ANDROID_NDK_BUILD}${CMAKE_MATCH_4}")
  84. # Touch toolchain variable to suppress "unused variable" warning.
  85. # This happens if CMake is invoked with the same command line the second time.
  86. if(CMAKE_TOOLCHAIN_FILE)
  87. endif()
  88. # Compatibility for configurable variables.
  89. # Compatible with configurable variables from the other toolchain file:
  90. # https://github.com/taka-no-me/android-cmake
  91. # TODO: We should consider dropping compatibility to simplify things once most
  92. # of our users have migrated to our standard set of configurable variables.
  93. if(ANDROID_TOOLCHAIN_NAME AND NOT ANDROID_TOOLCHAIN)
  94. if(ANDROID_TOOLCHAIN_NAME MATCHES "-clang([0-9].[0-9])?$")
  95. set(ANDROID_TOOLCHAIN clang)
  96. elseif(ANDROID_TOOLCHAIN_NAME MATCHES "-[0-9].[0-9]$")
  97. set(ANDROID_TOOLCHAIN gcc)
  98. endif()
  99. endif()
  100. if(ANDROID_ABI STREQUAL "armeabi-v7a with NEON")
  101. set(ANDROID_ABI armeabi-v7a)
  102. set(ANDROID_ARM_NEON TRUE)
  103. elseif(ANDROID_TOOLCHAIN_NAME AND NOT ANDROID_ABI)
  104. if(ANDROID_TOOLCHAIN_NAME MATCHES "^arm-linux-androideabi-")
  105. set(ANDROID_ABI armeabi-v7a)
  106. elseif(ANDROID_TOOLCHAIN_NAME MATCHES "^aarch64-linux-android-")
  107. set(ANDROID_ABI arm64-v8a)
  108. elseif(ANDROID_TOOLCHAIN_NAME MATCHES "^x86-")
  109. set(ANDROID_ABI x86)
  110. elseif(ANDROID_TOOLCHAIN_NAME MATCHES "^x86_64-")
  111. set(ANDROID_ABI x86_64)
  112. elseif(ANDROID_TOOLCHAIN_NAME MATCHES "^mipsel-linux-android-")
  113. set(ANDROID_ABI mips)
  114. elseif(ANDROID_TOOLCHAIN_NAME MATCHES "^mips64el-linux-android-")
  115. set(ANDROID_ABI mips64)
  116. endif()
  117. endif()
  118. if(ANDROID_NATIVE_API_LEVEL AND NOT ANDROID_PLATFORM)
  119. if(ANDROID_NATIVE_API_LEVEL MATCHES "^android-[0-9]+$")
  120. set(ANDROID_PLATFORM ${ANDROID_NATIVE_API_LEVEL})
  121. elseif(ANDROID_NATIVE_API_LEVEL MATCHES "^[0-9]+$")
  122. set(ANDROID_PLATFORM android-${ANDROID_NATIVE_API_LEVEL})
  123. endif()
  124. endif()
  125. if(DEFINED ANDROID_APP_PIE AND NOT DEFINED ANDROID_PIE)
  126. set(ANDROID_PIE "${ANDROID_APP_PIE}")
  127. endif()
  128. if(ANDROID_STL_FORCE_FEATURES AND NOT DEFINED ANDROID_CPP_FEATURES)
  129. set(ANDROID_CPP_FEATURES "rtti exceptions")
  130. endif()
  131. if(DEFINED ANDROID_NO_UNDEFINED AND NOT DEFINED ANDROID_ALLOW_UNDEFINED_SYMBOLS)
  132. if(ANDROID_NO_UNDEFINED)
  133. set(ANDROID_ALLOW_UNDEFINED_SYMBOLS FALSE)
  134. else()
  135. set(ANDROID_ALLOW_UNDEFINED_SYMBOLS TRUE)
  136. endif()
  137. endif()
  138. if(DEFINED ANDROID_SO_UNDEFINED AND NOT DEFINED ANDROID_ALLOW_UNDEFINED_SYMBOLS)
  139. set(ANDROID_ALLOW_UNDEFINED_SYMBOLS "${ANDROID_SO_UNDEFINED}")
  140. endif()
  141. if(DEFINED ANDROID_FORCE_ARM_BUILD AND NOT ANDROID_ARM_MODE)
  142. if(ANDROID_FORCE_ARM_BUILD)
  143. set(ANDROID_ARM_MODE arm)
  144. else()
  145. set(ANDROID_ARM_MODE thumb)
  146. endif()
  147. endif()
  148. if(NDK_CCACHE AND NOT ANDROID_CCACHE)
  149. set(ANDROID_CCACHE "${NDK_CCACHE}")
  150. endif()
  151. # Default values for configurable variables.
  152. if(NOT ANDROID_TOOLCHAIN)
  153. set(ANDROID_TOOLCHAIN clang)
  154. elseif(ANDROID_TOOLCHAIN STREQUAL gcc)
  155. message(FATAL_ERROR "GCC is no longer supported. See "
  156. "https://android.googlesource.com/platform/ndk/+/master/docs/ClangMigration.md.")
  157. endif()
  158. if(NOT ANDROID_ABI)
  159. set(ANDROID_ABI armeabi-v7a)
  160. endif()
  161. if(ANDROID_ABI STREQUAL armeabi)
  162. message(FATAL_ERROR "armeabi is no longer supported. Use armeabi-v7a.")
  163. elseif(ANDROID_ABI MATCHES "^(mips|mips64)$")
  164. message(FATAL_ERROR "MIPS and MIPS64 are no longer supported.")
  165. endif()
  166. if(ANDROID_ABI STREQUAL armeabi-v7a AND NOT DEFINED ANDROID_ARM_NEON)
  167. set(ANDROID_ARM_NEON TRUE)
  168. endif()
  169. include(${ANDROID_NDK}/build/cmake/platforms.cmake)
  170. # If no platform version was chosen by the user, default to the minimum version
  171. # supported by this NDK.
  172. if(NOT ANDROID_PLATFORM)
  173. message(STATUS "\
  174. ANDROID_PLATFORM not set. Defaulting to minimum supported version
  175. ${NDK_MIN_PLATFORM_LEVEL}.")
  176. set(ANDROID_PLATFORM "android-${NDK_MIN_PLATFORM_LEVEL}")
  177. endif()
  178. if(ANDROID_PLATFORM STREQUAL "latest")
  179. message(STATUS
  180. "Using latest available ANDROID_PLATFORM: ${NDK_MAX_PLATFORM_LEVEL}.")
  181. set(ANDROID_PLATFORM "android-${NDK_MAX_PLATFORM_LEVEL}")
  182. string(REPLACE "android-" "" ANDROID_PLATFORM_LEVEL ${ANDROID_PLATFORM})
  183. endif()
  184. string(REPLACE "android-" "" ANDROID_PLATFORM_LEVEL ${ANDROID_PLATFORM})
  185. # Aliases defined by meta/platforms.json include codename aliases for platform
  186. # API levels as well as cover any gaps in platforms that may not have had NDK
  187. # APIs.
  188. if(NOT "${NDK_PLATFORM_ALIAS_${ANDROID_PLATFORM_LEVEL}}" STREQUAL "")
  189. message(STATUS "\
  190. ${ANDROID_PLATFORM} is an alias for \
  191. ${NDK_PLATFORM_ALIAS_${ANDROID_PLATFORM_LEVEL}}. Adjusting ANDROID_PLATFORM to \
  192. match.")
  193. set(ANDROID_PLATFORM "${NDK_PLATFORM_ALIAS_${ANDROID_PLATFORM_LEVEL}}")
  194. string(REPLACE "android-" "" ANDROID_PLATFORM_LEVEL ${ANDROID_PLATFORM})
  195. endif()
  196. # Pull up to the minimum supported version if an old API level was requested.
  197. if(ANDROID_PLATFORM_LEVEL LESS NDK_MIN_PLATFORM_LEVEL)
  198. message(STATUS "\
  199. ${ANDROID_PLATFORM} is unsupported. Using minimum supported version \
  200. ${NDK_MIN_PLATFORM_LEVEL}.")
  201. set(ANDROID_PLATFORM "android-${NDK_MIN_PLATFORM_LEVEL}")
  202. string(REPLACE "android-" "" ANDROID_PLATFORM_LEVEL ${ANDROID_PLATFORM})
  203. endif()
  204. # And for LP64 we need to pull up to 21. No diagnostic is provided here because
  205. # minSdkVersion < 21 is valid for the project even though it may not be for this
  206. # ABI.
  207. if(ANDROID_ABI MATCHES "64(-v8a)?$" AND ANDROID_PLATFORM_LEVEL LESS 21)
  208. set(ANDROID_PLATFORM android-21)
  209. set(ANDROID_PLATFORM_LEVEL 21)
  210. endif()
  211. # ANDROID_PLATFORM beyond the maximum is an error. The correct way to specify
  212. # the latest version is ANDROID_PLATFORM=latest.
  213. if(ANDROID_PLATFORM_LEVEL GREATER NDK_MAX_PLATFORM_LEVEL)
  214. message(SEND_ERROR "\
  215. ${ANDROID_PLATFORM} is above the maximum supported version \
  216. ${NDK_MAX_PLATFORM_LEVEL}. Choose a supported API level or set \
  217. ANDROID_PLATFORM to \"latest\".")
  218. endif()
  219. if(NOT ANDROID_STL)
  220. set(ANDROID_STL c++_static)
  221. endif()
  222. if("${ANDROID_STL}" STREQUAL "gnustl_shared" OR
  223. "${ANDROID_STL}" STREQUAL "gnustl_static" OR
  224. "${ANDROID_STL}" STREQUAL "stlport_shared" OR
  225. "${ANDROID_STL}" STREQUAL "stlport_static")
  226. message(FATAL_ERROR "\
  227. ${ANDROID_STL} is no longer supported. Please switch to either c++_shared or \
  228. c++_static. See https://developer.android.com/ndk/guides/cpp-support.html \
  229. for more information.")
  230. endif()
  231. set(ANDROID_PIE TRUE)
  232. if(NOT ANDROID_ARM_MODE)
  233. set(ANDROID_ARM_MODE thumb)
  234. endif()
  235. # Export configurable variables for the try_compile() command.
  236. set(CMAKE_TRY_COMPILE_PLATFORM_VARIABLES
  237. ANDROID_ABI
  238. ANDROID_ALLOW_UNDEFINED_SYMBOLS
  239. ANDROID_ARM_MODE
  240. ANDROID_ARM_NEON
  241. ANDROID_CCACHE
  242. ANDROID_CPP_FEATURES
  243. ANDROID_DISABLE_FORMAT_STRING_CHECKS
  244. ANDROID_LD
  245. ANDROID_PIE
  246. ANDROID_PLATFORM
  247. ANDROID_STL
  248. ANDROID_TOOLCHAIN
  249. )
  250. # Standard cross-compiling stuff.
  251. set(ANDROID TRUE)
  252. set(CMAKE_SYSTEM_NAME Android)
  253. # https://github.com/android-ndk/ndk/issues/890
  254. #
  255. # ONLY doesn't do anything when CMAKE_FIND_ROOT_PATH is empty. Without this,
  256. # CMake will wrongly search host sysroots for headers/libraries. The actual path
  257. # used here is fairly meaningless since CMake doesn't handle the NDK sysroot
  258. # layout (per-arch and per-verion subdirectories for libraries), so find_library
  259. # is handled separately by CMAKE_SYSTEM_LIBRARY_PATH.
  260. list(APPEND CMAKE_FIND_ROOT_PATH "${ANDROID_NDK}")
  261. # Allow users to override these values in case they want more strict behaviors.
  262. # For example, they may want to prevent the NDK's libz from being picked up so
  263. # they can use their own.
  264. # https://github.com/android-ndk/ndk/issues/517
  265. if(NOT CMAKE_FIND_ROOT_PATH_MODE_PROGRAM)
  266. set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
  267. endif()
  268. if(NOT CMAKE_FIND_ROOT_PATH_MODE_LIBRARY)
  269. set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
  270. endif()
  271. if(NOT CMAKE_FIND_ROOT_PATH_MODE_INCLUDE)
  272. set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
  273. endif()
  274. if(NOT CMAKE_FIND_ROOT_PATH_MODE_PACKAGE)
  275. set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
  276. endif()
  277. # ABI.
  278. set(CMAKE_ANDROID_ARCH_ABI ${ANDROID_ABI})
  279. if(ANDROID_ABI STREQUAL armeabi-v7a)
  280. set(ANDROID_SYSROOT_ABI arm)
  281. set(ANDROID_TOOLCHAIN_NAME arm-linux-androideabi)
  282. set(CMAKE_SYSTEM_PROCESSOR armv7-a)
  283. set(ANDROID_LLVM_TRIPLE armv7-none-linux-androideabi)
  284. elseif(ANDROID_ABI STREQUAL arm64-v8a)
  285. set(ANDROID_SYSROOT_ABI arm64)
  286. set(CMAKE_SYSTEM_PROCESSOR aarch64)
  287. set(ANDROID_TOOLCHAIN_NAME aarch64-linux-android)
  288. set(ANDROID_LLVM_TRIPLE aarch64-none-linux-android)
  289. elseif(ANDROID_ABI STREQUAL x86)
  290. set(ANDROID_SYSROOT_ABI x86)
  291. set(CMAKE_SYSTEM_PROCESSOR i686)
  292. set(ANDROID_TOOLCHAIN_NAME i686-linux-android)
  293. set(ANDROID_LLVM_TRIPLE i686-none-linux-android)
  294. elseif(ANDROID_ABI STREQUAL x86_64)
  295. set(ANDROID_SYSROOT_ABI x86_64)
  296. set(CMAKE_SYSTEM_PROCESSOR x86_64)
  297. set(ANDROID_TOOLCHAIN_NAME x86_64-linux-android)
  298. set(ANDROID_LLVM_TRIPLE x86_64-none-linux-android)
  299. else()
  300. message(FATAL_ERROR "Invalid Android ABI: ${ANDROID_ABI}.")
  301. endif()
  302. set(ANDROID_LLVM_TRIPLE "${ANDROID_LLVM_TRIPLE}${ANDROID_PLATFORM_LEVEL}")
  303. set(ANDROID_COMPILER_FLAGS)
  304. set(ANDROID_COMPILER_FLAGS_CXX)
  305. set(ANDROID_COMPILER_FLAGS_DEBUG)
  306. set(ANDROID_COMPILER_FLAGS_RELEASE)
  307. set(ANDROID_LINKER_FLAGS)
  308. set(ANDROID_LINKER_FLAGS_EXE)
  309. if(ANDROID_LD STREQUAL lld)
  310. list(APPEND ANDROID_LINKER_FLAGS -fuse-ld=lld)
  311. endif()
  312. # Don't re-export libgcc symbols in every binary.
  313. list(APPEND ANDROID_LINKER_FLAGS -Wl,--exclude-libs,libgcc_real.a)
  314. list(APPEND ANDROID_LINKER_FLAGS -Wl,--exclude-libs,libatomic.a)
  315. # STL.
  316. set(ANDROID_CXX_STANDARD_LIBRARIES)
  317. if(ANDROID_STL STREQUAL system)
  318. list(APPEND ANDROID_COMPILER_FLAGS_CXX "-stdlib=libstdc++")
  319. if(NOT "x${ANDROID_CPP_FEATURES}" STREQUAL "x")
  320. list(APPEND ANDROID_CXX_STANDARD_LIBRARIES "-lc++abi")
  321. if(ANDROID_PLATFORM_LEVEL LESS 21)
  322. list(APPEND ANDROID_CXX_STANDARD_LIBRARIES "-landroid_support")
  323. endif()
  324. endif()
  325. elseif(ANDROID_STL STREQUAL c++_static)
  326. list(APPEND ANDROID_LINKER_FLAGS "-static-libstdc++")
  327. elseif(ANDROID_STL STREQUAL c++_shared)
  328. elseif(ANDROID_STL STREQUAL none)
  329. list(APPEND ANDROID_COMPILER_FLAGS_CXX "-nostdinc++")
  330. list(APPEND ANDROID_LINKER_FLAGS "-nostdlib++")
  331. else()
  332. message(FATAL_ERROR "Invalid Android STL: ${ANDROID_STL}.")
  333. endif()
  334. if(CMAKE_HOST_SYSTEM_NAME STREQUAL Linux)
  335. set(ANDROID_HOST_TAG linux-x86_64)
  336. elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL Darwin)
  337. set(ANDROID_HOST_TAG darwin-x86_64)
  338. elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL Windows)
  339. set(ANDROID_HOST_TAG windows-x86_64)
  340. endif()
  341. if(CMAKE_HOST_SYSTEM_NAME STREQUAL Windows)
  342. set(ANDROID_TOOLCHAIN_SUFFIX .exe)
  343. endif()
  344. # Toolchain.
  345. set(ANDROID_TOOLCHAIN_ROOT
  346. "${ANDROID_NDK}/toolchains/llvm/prebuilt/${ANDROID_HOST_TAG}")
  347. set(ANDROID_TOOLCHAIN_PREFIX
  348. "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_NAME}-")
  349. list(APPEND CMAKE_PREFIX_PATH "${ANDROID_TOOLCHAIN_ROOT}")
  350. # find_library searches a handful of paths as described by
  351. # https://cmake.org/cmake/help/v3.6/command/find_library.html. CMake doesn't
  352. # understand the Android sysroot layout, so we need to give the direct path to
  353. # the libraries rather than just the sysroot. Set up CMAKE_SYSTEM_LIBRARY_PATH
  354. # (https://cmake.org/cmake/help/v3.6/variable/CMAKE_SYSTEM_LIBRARY_PATH.html)
  355. # instead.
  356. # NB: This variable causes CMake to automatically pass --sysroot to the
  357. # toolchain. Studio currently relies on this to recognize Android builds. If
  358. # this variable is removed, ensure that flag is still passed.
  359. # TODO: Teach Studio to recognize Android builds based on --target.
  360. set(CMAKE_SYSROOT "${ANDROID_TOOLCHAIN_ROOT}/sysroot")
  361. # Allows CMake to find headers in the architecture-specific include directories.
  362. set(CMAKE_LIBRARY_ARCHITECTURE "${ANDROID_TOOLCHAIN_NAME}")
  363. # Instructs CMake to search the correct API level for libraries.
  364. list(APPEND CMAKE_SYSTEM_LIBRARY_PATH
  365. "/usr/lib/${ANDROID_TOOLCHAIN_NAME}/${ANDROID_PLATFORM_LEVEL}")
  366. set(ANDROID_HOST_PREBUILTS "${ANDROID_NDK}/prebuilt/${ANDROID_HOST_TAG}")
  367. set(ANDROID_C_COMPILER
  368. "${ANDROID_TOOLCHAIN_ROOT}/bin/clang${ANDROID_TOOLCHAIN_SUFFIX}")
  369. set(ANDROID_CXX_COMPILER
  370. "${ANDROID_TOOLCHAIN_ROOT}/bin/clang++${ANDROID_TOOLCHAIN_SUFFIX}")
  371. set(ANDROID_ASM_COMPILER
  372. "${ANDROID_TOOLCHAIN_ROOT}/bin/clang${ANDROID_TOOLCHAIN_SUFFIX}")
  373. # Clang can fail to compile if CMake doesn't correctly supply the target and
  374. # external toolchain, but to do so, CMake needs to already know that the
  375. # compiler is clang. Tell CMake that the compiler is really clang, but don't
  376. # use CMakeForceCompiler, since we still want compile checks. We only want
  377. # to skip the compiler ID detection step.
  378. set(CMAKE_C_COMPILER_ID_RUN TRUE)
  379. set(CMAKE_CXX_COMPILER_ID_RUN TRUE)
  380. set(CMAKE_C_COMPILER_ID Clang)
  381. set(CMAKE_CXX_COMPILER_ID Clang)
  382. set(CMAKE_C_COMPILER_VERSION 9.0)
  383. set(CMAKE_CXX_COMPILER_VERSION 9.0)
  384. set(CMAKE_C_STANDARD_COMPUTED_DEFAULT 11)
  385. set(CMAKE_CXX_STANDARD_COMPUTED_DEFAULT 14)
  386. set(CMAKE_C_COMPILER_TARGET ${ANDROID_LLVM_TRIPLE})
  387. set(CMAKE_C_COMPILER_FRONTEND_VARIANT "GNU")
  388. set(CMAKE_CXX_COMPILER_FRONTEND_VARIANT "GNU")
  389. set(CMAKE_CXX_COMPILER_TARGET ${ANDROID_LLVM_TRIPLE})
  390. set(CMAKE_ASM_COMPILER_TARGET ${ANDROID_LLVM_TRIPLE})
  391. set(CMAKE_C_COMPILER_EXTERNAL_TOOLCHAIN "${ANDROID_TOOLCHAIN_ROOT}")
  392. set(CMAKE_CXX_COMPILER_EXTERNAL_TOOLCHAIN "${ANDROID_TOOLCHAIN_ROOT}")
  393. set(CMAKE_ASM_COMPILER_EXTERNAL_TOOLCHAIN "${ANDROID_TOOLCHAIN_ROOT}")
  394. set(ANDROID_AR "${ANDROID_TOOLCHAIN_PREFIX}ar${ANDROID_TOOLCHAIN_SUFFIX}")
  395. set(ANDROID_RANLIB
  396. "${ANDROID_TOOLCHAIN_PREFIX}ranlib${ANDROID_TOOLCHAIN_SUFFIX}")
  397. # Generic flags.
  398. list(APPEND ANDROID_COMPILER_FLAGS
  399. -g
  400. -DANDROID
  401. -fdata-sections
  402. -ffunction-sections
  403. -funwind-tables
  404. -fstack-protector-strong
  405. -no-canonical-prefixes)
  406. # https://github.com/android/ndk/issues/885
  407. # If we're using LLD we need to use a slower build-id algorithm to work around
  408. # the old version of LLDB in Android Studio, which doesn't understand LLD's
  409. # default hash ("fast").
  410. #
  411. # Note that because we cannot see the user's flags, we can't detect this very
  412. # accurately. Users that explicitly use -fuse-ld=lld instead of ANDROID_LD will
  413. # not be able to debug.
  414. if(ANDROID_LD STREQUAL lld)
  415. list(APPEND ANDROID_LINKER_FLAGS -Wl,--build-id=sha1)
  416. else()
  417. list(APPEND ANDROID_LINKER_FLAGS -Wl,--build-id)
  418. endif()
  419. list(APPEND ANDROID_LINKER_FLAGS -Wl,--fatal-warnings)
  420. list(APPEND ANDROID_LINKER_FLAGS_EXE -Wl,--gc-sections)
  421. # Debug and release flags.
  422. list(APPEND ANDROID_COMPILER_FLAGS_DEBUG -O0)
  423. if(ANDROID_ABI MATCHES "^armeabi" AND ANDROID_ARM_MODE STREQUAL thumb)
  424. list(APPEND ANDROID_COMPILER_FLAGS_RELEASE -Oz)
  425. else()
  426. list(APPEND ANDROID_COMPILER_FLAGS_RELEASE -O2)
  427. endif()
  428. list(APPEND ANDROID_COMPILER_FLAGS_RELEASE -DNDEBUG)
  429. if(ANDROID_TOOLCHAIN STREQUAL clang)
  430. list(APPEND ANDROID_COMPILER_FLAGS_DEBUG -fno-limit-debug-info)
  431. endif()
  432. # Toolchain and ABI specific flags.
  433. if(ANDROID_ABI STREQUAL x86 AND ANDROID_PLATFORM_LEVEL LESS 24)
  434. # http://b.android.com/222239
  435. # http://b.android.com/220159 (internal http://b/31809417)
  436. # x86 devices have stack alignment issues.
  437. list(APPEND ANDROID_COMPILER_FLAGS -mstackrealign)
  438. endif()
  439. list(APPEND ANDROID_COMPILER_FLAGS -D_FORTIFY_SOURCE=2)
  440. # STL specific flags.
  441. if(ANDROID_STL MATCHES "^c\\+\\+_")
  442. if(ANDROID_ABI MATCHES "^armeabi")
  443. list(APPEND ANDROID_LINKER_FLAGS "-Wl,--exclude-libs,libunwind.a")
  444. endif()
  445. endif()
  446. set(CMAKE_C_STANDARD_LIBRARIES_INIT "-latomic -lm")
  447. set(CMAKE_CXX_STANDARD_LIBRARIES_INIT "${CMAKE_C_STANDARD_LIBRARIES_INIT}")
  448. if(ANDROID_CXX_STANDARD_LIBRARIES)
  449. string(REPLACE ";" "\" \"" ANDROID_CXX_STANDARD_LIBRARIES "\"${ANDROID_CXX_STANDARD_LIBRARIES}\"")
  450. set(CMAKE_CXX_STANDARD_LIBRARIES_INIT "${CMAKE_CXX_STANDARD_LIBRARIES_INIT} ${ANDROID_CXX_STANDARD_LIBRARIES}")
  451. endif()
  452. # Configuration specific flags.
  453. # PIE is supported on all currently supported Android releases, but it is not
  454. # supported with static executables, so we still provide ANDROID_PIE as an
  455. # escape hatch for those.
  456. if(ANDROID_PIE)
  457. set(CMAKE_POSITION_INDEPENDENT_CODE TRUE)
  458. endif()
  459. if(ANDROID_CPP_FEATURES)
  460. separate_arguments(ANDROID_CPP_FEATURES)
  461. foreach(feature ${ANDROID_CPP_FEATURES})
  462. if(NOT ${feature} MATCHES "^(rtti|exceptions|no-rtti|no-exceptions)$")
  463. message(FATAL_ERROR "Invalid Android C++ feature: ${feature}.")
  464. endif()
  465. list(APPEND ANDROID_COMPILER_FLAGS_CXX
  466. -f${feature})
  467. endforeach()
  468. string(REPLACE ";" " " ANDROID_CPP_FEATURES "${ANDROID_CPP_FEATURES}")
  469. endif()
  470. if(NOT ANDROID_ALLOW_UNDEFINED_SYMBOLS)
  471. list(APPEND ANDROID_LINKER_FLAGS
  472. -Wl,--no-undefined)
  473. endif()
  474. if(ANDROID_ABI MATCHES "armeabi")
  475. # Clang does not set this up properly when using -fno-integrated-as.
  476. # https://github.com/android-ndk/ndk/issues/906
  477. list(APPEND ANDROID_COMPILER_FLAGS "-march=armv7-a")
  478. if(ANDROID_ARM_MODE STREQUAL thumb)
  479. list(APPEND ANDROID_COMPILER_FLAGS -mthumb)
  480. elseif(ANDROID_ARM_MODE STREQUAL arm)
  481. # Default behavior.
  482. else()
  483. message(FATAL_ERROR "Invalid Android ARM mode: ${ANDROID_ARM_MODE}.")
  484. endif()
  485. if(ANDROID_ABI STREQUAL armeabi-v7a AND NOT ANDROID_ARM_NEON)
  486. list(APPEND ANDROID_COMPILER_FLAGS
  487. -mfpu=vfpv3-d16)
  488. endif()
  489. endif()
  490. # CMake automatically forwards all compiler flags to the linker, and clang
  491. # doesn't like having -Wa flags being used for linking. To prevent CMake from
  492. # doing this would require meddling with the CMAKE_<LANG>_COMPILE_OBJECT rules,
  493. # which would get quite messy.
  494. list(APPEND ANDROID_LINKER_FLAGS -Qunused-arguments)
  495. if(ANDROID_DISABLE_FORMAT_STRING_CHECKS)
  496. list(APPEND ANDROID_COMPILER_FLAGS
  497. -Wno-error=format-security)
  498. else()
  499. list(APPEND ANDROID_COMPILER_FLAGS
  500. -Wformat -Werror=format-security)
  501. endif()
  502. # Convert these lists into strings.
  503. string(REPLACE ";" " " ANDROID_COMPILER_FLAGS "${ANDROID_COMPILER_FLAGS}")
  504. string(REPLACE ";" " " ANDROID_COMPILER_FLAGS_CXX "${ANDROID_COMPILER_FLAGS_CXX}")
  505. string(REPLACE ";" " " ANDROID_COMPILER_FLAGS_DEBUG "${ANDROID_COMPILER_FLAGS_DEBUG}")
  506. string(REPLACE ";" " " ANDROID_COMPILER_FLAGS_RELEASE "${ANDROID_COMPILER_FLAGS_RELEASE}")
  507. string(REPLACE ";" " " ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS}")
  508. string(REPLACE ";" " " ANDROID_LINKER_FLAGS_EXE "${ANDROID_LINKER_FLAGS_EXE}")
  509. if(ANDROID_CCACHE)
  510. set(CMAKE_C_COMPILER_LAUNCHER "${ANDROID_CCACHE}")
  511. set(CMAKE_CXX_COMPILER_LAUNCHER "${ANDROID_CCACHE}")
  512. endif()
  513. set(CMAKE_C_COMPILER "${ANDROID_C_COMPILER}")
  514. set(CMAKE_CXX_COMPILER "${ANDROID_CXX_COMPILER}")
  515. set(CMAKE_AR "${ANDROID_AR}" CACHE FILEPATH "Archiver")
  516. set(CMAKE_RANLIB "${ANDROID_RANLIB}" CACHE FILEPATH "Ranlib")
  517. set(_CMAKE_TOOLCHAIN_PREFIX "${ANDROID_TOOLCHAIN_PREFIX}")
  518. if(ANDROID_ABI STREQUAL "x86" OR ANDROID_ABI STREQUAL "x86_64")
  519. set(CMAKE_ASM_NASM_COMPILER
  520. "${ANDROID_TOOLCHAIN_ROOT}/bin/yasm${ANDROID_TOOLCHAIN_SUFFIX}")
  521. set(CMAKE_ASM_NASM_COMPILER_ARG1 "-DELF")
  522. endif()
  523. # Set or retrieve the cached flags.
  524. # This is necessary in case the user sets/changes flags in subsequent
  525. # configures. If we included the Android flags in here, they would get
  526. # overwritten.
  527. set(CMAKE_C_FLAGS ""
  528. CACHE STRING "Flags used by the compiler during all build types.")
  529. set(CMAKE_CXX_FLAGS ""
  530. CACHE STRING "Flags used by the compiler during all build types.")
  531. set(CMAKE_ASM_FLAGS ""
  532. CACHE STRING "Flags used by the compiler during all build types.")
  533. set(CMAKE_C_FLAGS_DEBUG ""
  534. CACHE STRING "Flags used by the compiler during debug builds.")
  535. set(CMAKE_CXX_FLAGS_DEBUG ""
  536. CACHE STRING "Flags used by the compiler during debug builds.")
  537. set(CMAKE_ASM_FLAGS_DEBUG ""
  538. CACHE STRING "Flags used by the compiler during debug builds.")
  539. set(CMAKE_C_FLAGS_RELEASE ""
  540. CACHE STRING "Flags used by the compiler during release builds.")
  541. set(CMAKE_CXX_FLAGS_RELEASE ""
  542. CACHE STRING "Flags used by the compiler during release builds.")
  543. set(CMAKE_ASM_FLAGS_RELEASE ""
  544. CACHE STRING "Flags used by the compiler during release builds.")
  545. set(CMAKE_MODULE_LINKER_FLAGS ""
  546. CACHE STRING "Flags used by the linker during the creation of modules.")
  547. set(CMAKE_SHARED_LINKER_FLAGS ""
  548. CACHE STRING "Flags used by the linker during the creation of dll's.")
  549. set(CMAKE_EXE_LINKER_FLAGS ""
  550. CACHE STRING "Flags used by the linker.")
  551. set(CMAKE_C_FLAGS "${ANDROID_COMPILER_FLAGS} ${CMAKE_C_FLAGS}")
  552. set(CMAKE_CXX_FLAGS "${ANDROID_COMPILER_FLAGS} ${ANDROID_COMPILER_FLAGS_CXX} ${CMAKE_CXX_FLAGS}")
  553. set(CMAKE_ASM_FLAGS "${ANDROID_COMPILER_FLAGS} ${CMAKE_ASM_FLAGS}")
  554. set(CMAKE_C_FLAGS_DEBUG "${ANDROID_COMPILER_FLAGS_DEBUG} ${CMAKE_C_FLAGS_DEBUG}")
  555. set(CMAKE_CXX_FLAGS_DEBUG "${ANDROID_COMPILER_FLAGS_DEBUG} ${CMAKE_CXX_FLAGS_DEBUG}")
  556. set(CMAKE_ASM_FLAGS_DEBUG "${ANDROID_COMPILER_FLAGS_DEBUG} ${CMAKE_ASM_FLAGS_DEBUG}")
  557. set(CMAKE_C_FLAGS_RELEASE "${ANDROID_COMPILER_FLAGS_RELEASE} ${CMAKE_C_FLAGS_RELEASE}")
  558. set(CMAKE_CXX_FLAGS_RELEASE "${ANDROID_COMPILER_FLAGS_RELEASE} ${CMAKE_CXX_FLAGS_RELEASE}")
  559. set(CMAKE_ASM_FLAGS_RELEASE "${ANDROID_COMPILER_FLAGS_RELEASE} ${CMAKE_ASM_FLAGS_RELEASE}")
  560. set(CMAKE_SHARED_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} ${CMAKE_SHARED_LINKER_FLAGS}")
  561. set(CMAKE_MODULE_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} ${CMAKE_MODULE_LINKER_FLAGS}")
  562. set(CMAKE_EXE_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} ${ANDROID_LINKER_FLAGS_EXE} ${CMAKE_EXE_LINKER_FLAGS}")
  563. # Compatibility for read-only variables.
  564. # Read-only variables for compatibility with the other toolchain file.
  565. # We'll keep these around for the existing projects that still use them.
  566. # TODO: All of the variables here have equivalents in our standard set of
  567. # configurable variables, so we can remove these once most of our users migrate
  568. # to those variables.
  569. set(ANDROID_NATIVE_API_LEVEL ${ANDROID_PLATFORM_LEVEL})
  570. if(ANDROID_ALLOW_UNDEFINED_SYMBOLS)
  571. set(ANDROID_SO_UNDEFINED TRUE)
  572. else()
  573. set(ANDROID_NO_UNDEFINED TRUE)
  574. endif()
  575. set(ANDROID_FUNCTION_LEVEL_LINKING TRUE)
  576. set(ANDROID_GOLD_LINKER TRUE)
  577. set(ANDROID_NOEXECSTACK TRUE)
  578. set(ANDROID_RELRO TRUE)
  579. if(ANDROID_ARM_MODE STREQUAL arm)
  580. set(ANDROID_FORCE_ARM_BUILD TRUE)
  581. endif()
  582. if(ANDROID_CPP_FEATURES MATCHES "rtti"
  583. AND ANDROID_CPP_FEATURES MATCHES "exceptions")
  584. set(ANDROID_STL_FORCE_FEATURES TRUE)
  585. endif()
  586. if(ANDROID_CCACHE)
  587. set(NDK_CCACHE "${ANDROID_CCACHE}")
  588. endif()
  589. if(ANDROID_TOOLCHAIN STREQUAL clang)
  590. set(ANDROID_TOOLCHAIN_NAME ${ANDROID_TOOLCHAIN_NAME}-clang)
  591. else()
  592. set(ANDROID_TOOLCHAIN_NAME ${ANDROID_TOOLCHAIN_NAME}-4.9)
  593. endif()
  594. set(ANDROID_NDK_HOST_X64 TRUE)
  595. set(ANDROID_NDK_LAYOUT RELEASE)
  596. if(ANDROID_ABI STREQUAL armeabi-v7a)
  597. set(ARMEABI_V7A TRUE)
  598. if(ANDROID_ARM_NEON)
  599. set(NEON TRUE)
  600. endif()
  601. elseif(ANDROID_ABI STREQUAL arm64-v8a)
  602. set(ARM64_V8A TRUE)
  603. elseif(ANDROID_ABI STREQUAL x86)
  604. set(X86 TRUE)
  605. elseif(ANDROID_ABI STREQUAL x86_64)
  606. set(X86_64 TRUE)
  607. endif()
  608. set(ANDROID_NDK_HOST_SYSTEM_NAME ${ANDROID_HOST_TAG})
  609. set(ANDROID_NDK_ABI_NAME ${ANDROID_ABI})
  610. set(ANDROID_NDK_RELEASE r${ANDROID_NDK_REVISION})
  611. set(ANDROID_ARCH_NAME ${ANDROID_SYSROOT_ABI})
  612. set(TOOL_OS_SUFFIX ${ANDROID_TOOLCHAIN_SUFFIX})
  613. if(ANDROID_TOOLCHAIN STREQUAL clang)
  614. set(ANDROID_COMPILER_IS_CLANG TRUE)
  615. endif()
  616. # CMake 3.7+ compatibility.
  617. if (CMAKE_VERSION VERSION_GREATER 3.7.0)
  618. set(CMAKE_ANDROID_NDK ${ANDROID_NDK})
  619. set(CMAKE_ANDROID_NDK_TOOLCHAIN_VERSION clang)
  620. set(CMAKE_ANDROID_STL_TYPE ${ANDROID_STL})
  621. if(ANDROID_ABI MATCHES "^armeabi(-v7a)?$")
  622. set(CMAKE_ANDROID_ARM_NEON ${ANDROID_ARM_NEON})
  623. set(CMAKE_ANDROID_ARM_MODE ${ANDROID_ARM_MODE})
  624. endif()
  625. # https://github.com/android/ndk/issues/861
  626. if(ANDROID_ABI STREQUAL armeabi-v7a)
  627. set(CMAKE_ANDROID_ARCH arm)
  628. elseif(ANDROID_ABI STREQUAL arm64-v8a)
  629. set(CMAKE_ANDROID_ARCH arm64)
  630. elseif(ANDROID_ABI STREQUAL x86)
  631. set(CMAKE_ANDROID_ARCH x86)
  632. elseif(ANDROID_ABI STREQUAL x86_64)
  633. set(CMAKE_ANDROID_ARCH x86_64)
  634. endif()
  635. # https://github.com/android/ndk/issues/1012
  636. set(CMAKE_ASM_ANDROID_TOOLCHAIN_MACHINE "${ANDROID_TOOLCHAIN_NAME}")
  637. set(CMAKE_C_ANDROID_TOOLCHAIN_MACHINE "${ANDROID_TOOLCHAIN_NAME}")
  638. set(CMAKE_CXX_ANDROID_TOOLCHAIN_MACHINE "${ANDROID_TOOLCHAIN_NAME}")
  639. set(CMAKE_ASM_ANDROID_TOOLCHAIN_PREFIX "${ANDROID_TOOLCHAIN_PREFIX}")
  640. set(CMAKE_C_ANDROID_TOOLCHAIN_PREFIX "${ANDROID_TOOLCHAIN_PREFIX}")
  641. set(CMAKE_CXX_ANDROID_TOOLCHAIN_PREFIX "${ANDROID_TOOLCHAIN_PREFIX}")
  642. set(CMAKE_ASM_ANDROID_TOOLCHAIN_SUFFIX "${ANDROID_TOOLCHAIN_SUFFIX}")
  643. set(CMAKE_C_ANDROID_TOOLCHAIN_SUFFIX "${ANDROID_TOOLCHAIN_SUFFIX}")
  644. set(CMAKE_CXX_ANDROID_TOOLCHAIN_SUFFIX "${ANDROID_TOOLCHAIN_SUFFIX}")
  645. endif()