Android.cmake 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611
  1. #
  2. # Copyright (c) 2016-2017 Yao Wei Tjong. All rights reserved.
  3. #
  4. # Permission is hereby granted, free of charge, to any person obtaining a copy
  5. # of this software and associated documentation files (the "Software"), to deal
  6. # in the Software without restriction, including without limitation the rights
  7. # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. # copies of the Software, and to permit persons to whom the Software is
  9. # furnished to do so, subject to the following conditions:
  10. #
  11. # The above copyright notice and this permission notice shall be included in
  12. # all copies or substantial portions of the Software.
  13. #
  14. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  20. # THE SOFTWARE.
  21. #
  22. # Modified by Yao Wei Tjong for Urho3D
  23. #
  24. # This CMake toolchain file is designed to work with both cmake-gui and cmake CLI.
  25. # It is inspired from https://github.com/taka-no-me/android-cmake/android.toolchain.cmake,
  26. # most of its options are kept for compatibility, however, the possible values for each option are not identical.
  27. #
  28. # Options:
  29. # ANDROID_NDK - path to the NDK root.
  30. # Can be set as environment variable.
  31. # NOTE: This option cannot be changed after the initial configuration/generation.
  32. #
  33. # ANDROID_TOOLCHAIN_NAME=arm-linux-androideabi-clang - the name of compiler toolchain to be used.
  34. # The possible values are derived from the prebuilt compiler toolchains in the Android NDK.
  35. # NOTE: This option cannot be changed after the initial configuration/generation.
  36. #
  37. # ANDROID_ABI=armeabi-v7a - specifies the target Application Binary Interface (ABI).
  38. # This option nearly matches to the APP_ABI variable used by ndk-build tool from Android NDK.
  39. #
  40. # Possible targets are:
  41. # 1) For arm arch:
  42. # armeabi-v7a - ARMv7 based devices with hardware FPU instructions but software floating-point calling convention (softfp).
  43. # armeabi-v6 - ARMv6 based devices with hardware FPU instructions but software floating-point calling convention (softfp).
  44. # armeabi - ARMv5TE based CPU with software floating point operations (soft).
  45. #
  46. # These ABI options can be combined with one of the below modifiers to specify which hardware FPU to use:
  47. # "with neon-vfpv4" - Use NEON SIMD and VFPv4.
  48. # "with neon" - Use NEON SIMD and VFPv3.
  49. # "with vfpv4" - Use VFPv4.
  50. # "with vfpv3" - Use VFPv3 (32 registers).
  51. # "with vfpv3-d16" - Use VFPv3 (16 registers). This is the default for ARMv7.
  52. # "with vfp" - Use VFPv2. This is the default and the only possible combination for ARMv6.
  53. #
  54. # 2) For aarch64 arch:
  55. # arm64-v8a - ARMv8 AArch64 instruction set.
  56. #
  57. # 3) For i686 arch:
  58. # x86 - IA-32 instruction set.
  59. #
  60. # 4) For x86_64 arch:
  61. # x86_64 - Intel64 instruction set.
  62. #
  63. # 5) For mipsel arch:
  64. # mips - MIPS32 instruction set.
  65. #
  66. # 6) For mips64el arch:
  67. # mips64 - MIPS64 instruction set.
  68. #
  69. # ANDROID_NATIVE_API_LEVEL=android-9 - level of Android API compile for.
  70. # The default level is android-21 when targeting any of the 64-bit ABIs.
  71. # NOTE: The level must not be larger than android:minSdkVersion in AndroidManifest.xml.
  72. #
  73. # ANDROID_FORCE_ARM_BUILD=OFF - set ON to generate 32-bit ARM instructions instead of Thumb.
  74. # This option is only available for arm arch.
  75. #
  76. # ANDROID_STACK_PROTECTION=OFF - set ON to force the addition of a stack canary that checks for stack smashing.
  77. # When it is ON the generated binary may be larger in size and slower in performance.
  78. # Unlike ndk-build, it is defaulted to OFF.
  79. #
  80. # ANDROID_NO_UNDEFINED=ON - set ON to show all undefined symbols as linker errors even if they are not used.
  81. #
  82. # ANDROID_NOEXECSTACK=ON - set ON to enforce the NX (no execute) security feature in the generated machine code.
  83. #
  84. # ANDROID_RELRO=ON - set ON to mark certain regions of the resulting executable or shared library as being read-only.
  85. #
  86. # ANDROID_FATAL_WARNINGS=ON - set ON to treat all linker warnings as errors.
  87. #
  88. # ANDROID_FORMAT_SECURITY=ON - set ON to provide compiler protection against format string vulnerabilities.
  89. #
  90. # ANDROID_FUNCTION_LEVEL_LINKING=ON - set ON to split data/function sections and garbage collect unused sections at link time.
  91. # This option may be turned off to avoid potential debugging problems in Debug build configuration.
  92. #
  93. # ANDROID_STL=system - specify the C++ STL runtime to use.
  94. # When ANDROID_STL_FORCE_FEATURES is ON then it auto-configures the RTTI and exceptions settings to ON for any runtime chosen,
  95. # except for default system runtime.
  96. # NOTE: Use shared runtime when your project contains multiple shared libraries or executables.
  97. # Otherwise, the build system does not define certain global uniquely, which can result in unpredictable runtime behavior.
  98. # This behavior may include crashes and failure to properly catch exceptions.
  99. #
  100. # Possible values are:
  101. # system -> Use the minimal system C++ runtime library. Implies -fno-rtti -fno-exceptions.
  102. # gabi++_static -> Use the GAbi++ runtime as a static library.
  103. # gabi++_shared -> Use the GAbi++ runtime as a shared library.
  104. # stlport_static -> Use the STLport runtime as a static library. STLport is licensed under BSD-like license.
  105. # stlport_shared -> Use the STLport runtime as a shared library.
  106. # gnustl_static -> Use the GNU libstdc++ as a static library. GNU libstdc++ is licensed under GPLv3 + linking exception.
  107. # gnustl_shared -> Use the GNU libstdc++ as a shared library.
  108. # c++_static -> Use the LLVM libc++ runtime as a static library. LLVM libc++ is licensed under BSD-Like and MIT license.
  109. # c++_shared -> Use the LLVM libc++ runtime as a shared library.
  110. #
  111. # ANDROID_STL_FORCE_FEATURES=ON - automatically configure rtti and exceptions settings based on the chosen C++ STL runtime.
  112. # If disabled, then the user is responsible for setting ANDROID_RTTI and ANDROID_EXCEPTIONS options manually.
  113. #
  114. # ANDROID_RTTI=ON - set ON to enable RTTI.
  115. # This option is only available when ANDROID_STL_FORCE_FEATURES is disabled.
  116. #
  117. # ANDROID_EXCEPTIONS=ON - set ON to enable C++ exceptions.
  118. # This option is only available when ANDROID_STL_FORCE_FEATURES is disabled.
  119. #
  120. cmake_minimum_required (VERSION 3.2.3)
  121. mark_as_advanced (CMAKE_TOOLCHAIN_FILE)
  122. set (CMAKE_SYSTEM_NAME Android)
  123. set (CMAKE_SYSTEM_VERSION 1)
  124. set (CMAKE_POSITION_INDEPENDENT_CODE 1)
  125. set (ANDROID 1)
  126. # Prevent critical variables from changing after the initial configuration
  127. if (CMAKE_CROSSCOMPILING)
  128. set (SAVED_ANDROID_NDK ${ANDROID_NDK} CACHE INTERNAL "Initial value for ANDROID_NDK")
  129. set (SAVED_ANDROID_TOOLCHAIN_NAME ${ANDROID_TOOLCHAIN_NAME} CACHE INTERNAL "Initial value for ANDROID_TOOLCHAIN_NAME")
  130. # Urho3D - save the initial values of CC and CXX environment variables
  131. set (SAVED_CC $ENV{CC} CACHE INTERNAL "Initial value for CC")
  132. set (SAVED_CXX $ENV{CXX} CACHE INTERNAL "Initial value for CXX")
  133. return ()
  134. elseif ((SAVED_ANDROID_NDK AND NOT SAVED_ANDROID_NDK STREQUAL ANDROID_NDK) OR (SAVED_ANDROID_TOOLCHAIN_NAME AND NOT SAVED_ANDROID_TOOLCHAIN_NAME STREQUAL ANDROID_TOOLCHAIN_NAME))
  135. set (ANDROID_NDK ${SAVED_ANDROID_NDK} CACHE PATH "Path to Android NDK (Android platform only)" FORCE)
  136. set (ANDROID_TOOLCHAIN_NAME ${SAVED_ANDROID_TOOLCHAIN_NAME} CACHE STRING "Specify the name of compiler toolchain (Android platform only), possible values depends on installed Android NDK, default to Clang compiler toolchain" FORCE)
  137. message (FATAL_ERROR "ANDROID_NDK and ANDROID_TOOLCHAIN_NAME cannot be changed after the initial configuration/generation. "
  138. "Auto reverting to its initial value. If you wish to change it then the build tree would have to be regenerated from scratch.")
  139. endif ()
  140. # Workaround try_compile() limitation where it cannot see cache variables and it is a waste of time to reinit everything all over
  141. get_property (IN_TRY_COMPILE GLOBAL PROPERTY IN_TRY_COMPILE)
  142. if (NOT IN_TRY_COMPILE)
  143. # Android NDK paths
  144. if (NOT SAVED_ANDROID_NDK)
  145. if (NOT ANDROID_NDK AND DEFINED ENV{ANDROID_NDK})
  146. file (TO_CMAKE_PATH $ENV{ANDROID_NDK} ANDROID_NDK)
  147. endif ()
  148. set (ANDROID_NDK ${ANDROID_NDK} CACHE PATH "Path to Android NDK (Android platform only)")
  149. if (NOT EXISTS ${ANDROID_NDK})
  150. message (FATAL_ERROR "Could not find Android NDK. "
  151. "Use ANDROID_NDK environment variable or build option to specify the location of Android NDK.")
  152. endif ()
  153. endif ()
  154. if (NOT ANDROID_NDK_VERSION)
  155. if (EXISTS ${ANDROID_NDK}/source.properties)
  156. file (STRINGS ${ANDROID_NDK}/source.properties LINE LIMIT_COUNT 1 REGEX [0-9]+\\.[0-9]+\\.[0-9]+)
  157. endif ()
  158. if (LINE MATCHES "([0-9]+\\.[0-9]+\\.[0-9]+)")
  159. set (ANDROID_NDK_VERSION ${CMAKE_MATCH_1} CACHE INTERNAL "Android NDK version")
  160. endif ()
  161. if (ANDROID_NDK_VERSION LESS 12)
  162. unset (ANDROID_NDK_VERSION CACHE)
  163. message (FATAL_ERROR "Unsupported Android NDK version. This toolchain file only supports Android NDK r12 onward.")
  164. endif ()
  165. endif ()
  166. set (ANDROID_NDK_TOOLCHAINS_CONFIG_PATH ${ANDROID_NDK}/build/core/toolchains)
  167. set (ANDROID_NDK_TOOLCHAINS_PATH ${ANDROID_NDK}/toolchains)
  168. if (NOT ANDROID_NDK_HOST_SYSTEM_NAME)
  169. file (GLOB ANDROID_NDK_HOST_SYSTEM_NAME RELATIVE ${ANDROID_NDK_TOOLCHAINS_PATH}/llvm/prebuilt ${ANDROID_NDK_TOOLCHAINS_PATH}/llvm/prebuilt/*)
  170. set (ANDROID_NDK_HOST_SYSTEM_NAME ${ANDROID_NDK_HOST_SYSTEM_NAME} CACHE INTERNAL "Android NDK host system name")
  171. endif ()
  172. set (ANDROID_NDK_TOOLCHAINS_SUBPATH /prebuilt/${ANDROID_NDK_HOST_SYSTEM_NAME})
  173. # Android compiler toolchains
  174. if (NOT SAVED_ANDROID_TOOLCHAIN_NAME)
  175. set (ANDROID_DEFAULT_TOOLCHAIN_NAME arm-linux-androideabi-clang)
  176. set (ANDROID_TOOLCHAIN_NAME ${ANDROID_DEFAULT_TOOLCHAIN_NAME} CACHE STRING "Specify the name of compiler toolchain (Android platform only), default to ${ANDROID_DEFAULT_TOOLCHAIN_NAME}")
  177. file (GLOB ANDROID_SUPPORTED_TOOLCHAINS RELATIVE ${ANDROID_NDK_TOOLCHAINS_CONFIG_PATH} ${ANDROID_NDK_TOOLCHAINS_CONFIG_PATH}/*)
  178. list (SORT ANDROID_SUPPORTED_TOOLCHAINS)
  179. set_property (CACHE ANDROID_TOOLCHAIN_NAME PROPERTY STRINGS ${ANDROID_SUPPORTED_TOOLCHAINS})
  180. list (FIND ANDROID_SUPPORTED_TOOLCHAINS "${ANDROID_TOOLCHAIN_NAME}" FOUND_INDEX) # Stringify as the actual variable may be empty
  181. if (FOUND_INDEX EQUAL -1)
  182. string (REPLACE ";" "\", \"" PRINTABLE_ANDROID_SUPPORTED_TOOLCHAINS "\"${ANDROID_SUPPORTED_TOOLCHAINS}\"")
  183. message (FATAL_ERROR "Unrecognized '${ANDROID_TOOLCHAIN_NAME}' specified in the ANDROID_TOOLCHAIN_NAME option, "
  184. "supported values are: ${PRINTABLE_ANDROID_SUPPORTED_TOOLCHAINS}.")
  185. endif ()
  186. set (ANDROID_TOOLCHAIN_ROOT ${ANDROID_NDK_TOOLCHAINS_PATH}/${ANDROID_TOOLCHAIN_NAME}${ANDROID_NDK_TOOLCHAINS_SUBPATH})
  187. if (ANDROID_TOOLCHAIN_NAME MATCHES "-clang.*$")
  188. set (ANDROID_CLANG_TOOLCHAIN_ROOT ${ANDROID_NDK_TOOLCHAINS_PATH}/llvm${ANDROID_NDK_TOOLCHAINS_SUBPATH} CACHE INTERNAL "Clang toolchain root if using Clang")
  189. set (CLANG CLANG_ CACHE INTERNAL "Non empty if using Clang")
  190. # Check if it still depends on GCC toolchain for assembler and linker support (assume 4.9 is the last deprecated GCC version supported by Android NDK)
  191. file (STRINGS ${ANDROID_NDK_TOOLCHAINS_CONFIG_PATH}/${ANDROID_TOOLCHAIN_NAME}/setup.mk ANDROID_ROOT_${ANDROID_TOOLCHAIN_NAME} REGEX ^TOOLCHAIN_ROOT.*-4.9)
  192. if (ANDROID_ROOT_${ANDROID_TOOLCHAIN_NAME})
  193. string (REGEX REPLACE -clang.*$ -4.9 GCC_TOOLCHAIN_NAME "${ANDROID_TOOLCHAIN_NAME}")
  194. set (ANDROID_TOOLCHAIN_ROOT ${ANDROID_NDK_TOOLCHAINS_PATH}/${GCC_TOOLCHAIN_NAME}${ANDROID_NDK_TOOLCHAINS_SUBPATH})
  195. endif ()
  196. endif ()
  197. set (ANDROID_TOOLCHAIN_ROOT ${ANDROID_TOOLCHAIN_ROOT} CACHE INTERNAL "GCC toolchain root")
  198. endif ()
  199. string (REGEX REPLACE -[^-]+$ "" ANDROID_TOOLCHAIN_MACHINE_NAME "${ANDROID_TOOLCHAIN_NAME}")
  200. string (REGEX REPLACE -.*$|el "" MACHINE_ARCH "${ANDROID_TOOLCHAIN_MACHINE_NAME}")
  201. if (ANDROID_TOOLCHAIN_MACHINE_NAME MATCHES x86)
  202. string (REGEX REPLACE ^x86- i686- ANDROID_TOOLCHAIN_MACHINE_NAME "${ANDROID_TOOLCHAIN_MACHINE_NAME}-linux-android")
  203. endif ()
  204. # Android ABIs
  205. if (NOT ANDROID_ABI OR NOT ANDROID_ABI_SAVED STREQUAL ANDROID_ABI)
  206. set (ANDROID_SUPPORTED_ABIS_arm armeabi-v7a armeabi-v6 armeabi)
  207. set (ANDROID_SUPPORTED_ABIS_aarch64 arm64-v8a)
  208. set (ANDROID_SUPPORTED_ABIS_x86 x86)
  209. set (ANDROID_SUPPORTED_ABIS_x86_64 x86_64)
  210. set (ANDROID_SUPPORTED_ABIS_mips mips)
  211. set (ANDROID_SUPPORTED_ABIS_mips64 mips64)
  212. set (ANDROID_SUPPORTED_ABIS ${ANDROID_SUPPORTED_ABIS_${MACHINE_ARCH}})
  213. list (GET ANDROID_SUPPORTED_ABIS 0 DEFAULT_ANDROID_ABI)
  214. set (ANDROID_ABI ${DEFAULT_ANDROID_ABI} CACHE STRING "Specify target ABI (Android platform only), possible values depends on the target arch of the chosen Android compiler toolchain, default to first ABI of each target arch")
  215. set_property (CACHE ANDROID_ABI PROPERTY STRINGS ${ANDROID_SUPPORTED_ABIS})
  216. if (ANDROID_ABI MATCHES with)
  217. string (REGEX REPLACE ".+with (.+)" \\1 ANDROID_ABI_MODIFIER "${ANDROID_ABI}")
  218. if (MACHINE_ARCH STREQUAL arm)
  219. set (ANDROID_SUPPORTED_ARM_ABI_MODIFIERS neon-vfpv4 neon vfpv4 vfpv3 vfpv3-d16 vfp)
  220. list (FIND ANDROID_SUPPORTED_ARM_ABI_MODIFIERS "${ANDROID_ABI_MODIFIER}" FOUND_INDEX) # Stringify as the variable may be empty
  221. if (FOUND_INDEX EQUAL -1)
  222. string (REPLACE ";" "\", \"" PRINTABLE_ANDROID_SUPPORTED_ARM_ABI_MODIFIERS "\"${ANDROID_SUPPORTED_ARM_ABI_MODIFIERS}\"")
  223. message (FATAL_ERROR "Unrecognized '${ANDROID_ABI_MODIFIER}' specified in the ANDROID_ABI option, "
  224. "supported values are: ${PRINTABLE_ANDROID_SUPPORTED_ARM_ABI_MODIFIERS}.")
  225. endif ()
  226. else ()
  227. message (FATAL_ERROR "Unrecognized '${ANDROID_ABI_MODIFIER}' specified in the ANDROID_ABI option, "
  228. "the chosen Android ABI does not support any modifiers.")
  229. endif ()
  230. endif ()
  231. string (REGEX REPLACE with.+ "" ANDROID_ABI_BASE "${ANDROID_ABI}")
  232. list (FIND ANDROID_SUPPORTED_ABIS "${ANDROID_ABI_BASE}" FOUND_INDEX) # Stringify as the variable may be empty
  233. if (FOUND_INDEX EQUAL -1)
  234. string (REPLACE ";" "\", \"" PRINTABLE_ANDROID_SUPPORTED_ABIS "\"${ANDROID_SUPPORTED_ABIS}\"")
  235. message (FATAL_ERROR "Unrecognized '${ANDROID_ABI}' specified in the ANDROID_ABI option, "
  236. "supported values are: ${PRINTABLE_ANDROID_SUPPORTED_ABIS}.")
  237. endif ()
  238. set (ANDROID_ABI_SAVED ${ANDROID_ABI} CACHE INTERNAL "Last saved value for ANDROID_ABI")
  239. # Invalidate internal caches that depend on ANDROID_ABI, if any
  240. unset (ANDROID_STL_SAVED CACHE) # This should cause ANDROID_STL option to be revalidated
  241. if (CLANG)
  242. set (INVALIDATE_CCT 1)
  243. endif ()
  244. endif ()
  245. # First, derive variable values based on chosen compiler toolchain
  246. set (ANDROID_NDK_ABI_NAME ${MACHINE_ARCH})
  247. set (ANDROID_ARCH_NAME ${MACHINE_ARCH})
  248. set (CMAKE_SYSTEM_PROCESSOR ${MACHINE_ARCH})
  249. string (REGEX REPLACE "^([^-]+).*$" \\1-none-linux-android ANDROID_LLVM_TRIPLE "${ANDROID_TOOLCHAIN_MACHINE_NAME}")
  250. # Then, handle exceptional cases based on chosen ABI
  251. if (ANDROID_ABI MATCHES armeabi-v7a)
  252. if (NOT ANDROID_ABI MATCHES with)
  253. set (ANDROID_ABI "armeabi-v7a with vfpv3-d16") # This is the default case for armeabi-v7a
  254. endif ()
  255. set (ANDROID_NDK_ABI_NAME armeabi-v7a)
  256. set (CMAKE_SYSTEM_PROCESSOR armv7-a)
  257. set (ANDROID_LLVM_TRIPLE armv7-none-linux-androideabi)
  258. elseif (ANDROID_ABI MATCHES armeabi)
  259. set (ANDROID_NDK_ABI_NAME armeabi)
  260. if (ANDROID_ABI MATCHES -v6)
  261. set (ANDROID_ABI "armeabi-v6 with vfp") # This is the default case for armeabi-v6
  262. set (CMAKE_SYSTEM_PROCESSOR armv6)
  263. else ()
  264. set (CMAKE_SYSTEM_PROCESSOR armv5te)
  265. endif ()
  266. set (ANDROID_LLVM_TRIPLE armv5te-none-linux-androideabi)
  267. elseif (ANDROID_ABI STREQUAL arm64-v8a)
  268. set (ANDROID_NDK_ABI_NAME arm64-v8a)
  269. set (ANDROID_ARCH_NAME arm64)
  270. elseif (ANDROID_ABI STREQUAL x86)
  271. set (CMAKE_SYSTEM_PROCESSOR i686)
  272. endif ()
  273. include (CMakeDependentOption)
  274. cmake_dependent_option (ANDROID_FORCE_ARM_BUILD "Use 32-bit ARM instructions instead of Thumb" FALSE "ANDROID_ARCH_NAME STREQUAL arm" FALSE)
  275. # Urho3D - comment out as Urho manages the runtime and library output directories in its own module
  276. #set (CMAKE_RUNTIME_OUTPUT_DIRECTORY {CMAKE_BINARY_DIR}/bin)
  277. #set (CMAKE_LIBRARY_OUTPUT_DIRECTORY {CMAKE_BINARY_DIR}/libs/${ANDROID_NDK_ABI_NAME})
  278. # Android API levels
  279. if (NOT ANDROID_NATIVE_API_LEVEL OR NOT ANDROID_NATIVE_API_LEVEL_SAVED STREQUAL ANDROID_NATIVE_API_LEVEL)
  280. set (ANDROID_DEFAULT_NDK_API_LEVEL_arm 9)
  281. set (ANDROID_DEFAULT_NDK_API_LEVEL_arm64 21)
  282. set (ANDROID_DEFAULT_NDK_API_LEVEL_x86 9)
  283. set (ANDROID_DEFAULT_NDK_API_LEVEL_x86_64 21)
  284. set (ANDROID_DEFAULT_NDK_API_LEVEL_mips 9)
  285. set (ANDROID_DEFAULT_NDK_API_LEVEL_mips64 21)
  286. set (ANDROID_DEFAULT_NDK_API_LEVEL ${ANDROID_DEFAULT_NDK_API_LEVEL_${ANDROID_ARCH_NAME}})
  287. set (ANDROID_NATIVE_API_LEVEL android-${ANDROID_DEFAULT_NDK_API_LEVEL} CACHE STRING "Specify target API level (Android platform only), default to 'android-9' on 32-bit ABIs, default to 'android-21' on 64-bit ABIs")
  288. if (NOT SUPPORTED_NATIVE_API_LEVELS_${ANDROID_ARCH_NAME})
  289. if (NOT SUPPORTED_NATIVE_API_LEVELS)
  290. file (GLOB SUPPORTED_NATIVE_API_LEVELS RELATIVE ${ANDROID_NDK}/platforms ${ANDROID_NDK}/platforms/android-*)
  291. string (REPLACE android- "" SUPPORTED_NATIVE_API_LEVELS "${SUPPORTED_NATIVE_API_LEVELS}")
  292. set (SUPPORTED_NATIVE_API_LEVELS ${SUPPORTED_NATIVE_API_LEVELS} CACHE INTERNAL "Supported Android native API levels")
  293. endif ()
  294. set (SUPPORTED_NATIVE_API_LEVELS_${ANDROID_ARCH_NAME} ${SUPPORTED_NATIVE_API_LEVELS})
  295. foreach (API_LEVEL ${SUPPORTED_NATIVE_API_LEVELS})
  296. if (API_LEVEL LESS ANDROID_DEFAULT_NDK_API_LEVEL OR API_LEVEL LESS 10)
  297. list (REMOVE_ITEM SUPPORTED_NATIVE_API_LEVELS_${ANDROID_ARCH_NAME} ${API_LEVEL})
  298. endif ()
  299. if (NOT API_LEVEL LESS ANDROID_DEFAULT_NDK_API_LEVEL AND API_LEVEL LESS 10)
  300. list (APPEND SUPPORTED_NATIVE_API_LEVELS_${ANDROID_ARCH_NAME} 0${API_LEVEL}) # Add 0 padding for sorting
  301. endif ()
  302. endforeach ()
  303. list (SORT SUPPORTED_NATIVE_API_LEVELS_${ANDROID_ARCH_NAME})
  304. string (REGEX REPLACE ";0*" ";android-" SUPPORTED_NATIVE_API_LEVELS_${ANDROID_ARCH_NAME} ";${SUPPORTED_NATIVE_API_LEVELS_${ANDROID_ARCH_NAME}}")
  305. string (REGEX REPLACE "^;" "" SUPPORTED_NATIVE_API_LEVELS_${ANDROID_ARCH_NAME} "${SUPPORTED_NATIVE_API_LEVELS_${ANDROID_ARCH_NAME}}")
  306. set (SUPPORTED_NATIVE_API_LEVELS_${ANDROID_ARCH_NAME} ${SUPPORTED_NATIVE_API_LEVELS_${ANDROID_ARCH_NAME}} CACHE INTERNAL "Supported Android native API levels for arch ${ANDROID_ARCH_NAME}")
  307. endif ()
  308. set_property (CACHE ANDROID_NATIVE_API_LEVEL PROPERTY STRINGS ${SUPPORTED_NATIVE_API_LEVELS_${ANDROID_ARCH_NAME}})
  309. list (FIND SUPPORTED_NATIVE_API_LEVELS_${ANDROID_ARCH_NAME} "${ANDROID_NATIVE_API_LEVEL}" FOUND_INDEX) # Stringify as the actual variable may be empty
  310. if (FOUND_INDEX EQUAL -1)
  311. string (REPLACE ";" "\", \"" PRINTABLE_ANDROID_SUPPORTED_NATIVE_API_LEVELS "\"${SUPPORTED_NATIVE_API_LEVELS_${ANDROID_ARCH_NAME}}\"")
  312. message (FATAL_ERROR "Unsupported '${ANDROID_NATIVE_API_LEVEL}' specified in the ANDROID_NATIVE_API_LEVEL option, "
  313. "supported values are: ${PRINTABLE_ANDROID_SUPPORTED_NATIVE_API_LEVELS}.")
  314. endif ()
  315. set (ANDROID_NATIVE_API_LEVEL_SAVED ${ANDROID_NATIVE_API_LEVEL} CACHE INTERNAL "Last saved value for ANDROID_NATIVE_API_LEVEL")
  316. endif ()
  317. # Warn if the chosen level is larger than android:minSdkVersion, this check can only done in CMake rerun (after the build tree has been generated)
  318. string (REPLACE android- "" APP_PLATFORM_LEVEL "${ANDROID_NATIVE_API_LEVEL}")
  319. if (EXISTS ${CMAKE_BINARY_DIR}/AndroidManifest.xml)
  320. file (STRINGS ${CMAKE_BINARY_DIR}/AndroidManifest.xml LINE LIMIT_COUNT 1 REGEX android:minSdkVersion=)
  321. if (LINE MATCHES "android:minSdkVersion=\"([^\"]+)\"")
  322. set (APP_MIN_PLATFORM_LEVEL ${CMAKE_MATCH_1})
  323. if (APP_PLATFORM_LEVEL GREATER APP_MIN_PLATFORM_LEVEL)
  324. message (WARNING "ANDROID_NATIVE_API_LEVEL (${ANDROID_NATIVE_API_LEVEL}) is larger than android:minSdkVersion (${APP_MIN_PLATFORM_LEVEL}) in AndroidManifest.xml.")
  325. endif ()
  326. endif ()
  327. endif ()
  328. # System root
  329. set (CMAKE_SYSROOT ${ANDROID_NDK}/platforms/${ANDROID_NATIVE_API_LEVEL}/arch-${ANDROID_ARCH_NAME})
  330. # C++ STL runtimes
  331. option (ANDROID_STL_FORCE_FEATURES "Automatically configure rtti and exceptions support based on the chosen C++ STL runtime" TRUE)
  332. # Urho3D - always use RTTI due to dynamic cast usage in the codebase
  333. #cmake_dependent_option (ANDROID_RTTI "Set ON to enable RTTI" TRUE "NOT ANDROID_STL_FORCE_FEATURES" TRUE)
  334. set (ANDROID_RTTI 1)
  335. cmake_dependent_option (ANDROID_EXCEPTIONS "Set ON to enable C++ exceptions" TRUE "NOT ANDROID_STL_FORCE_FEATURES" TRUE)
  336. if (NOT FEATURE_SIGNATURE STREQUAL "${ANDROID_STL_FORCE_FEATURES}-${ANDROID_RTTI}-${ANDROID_EXCEPTIONS}")
  337. set (INVALIDATE_CCT 1)
  338. set (FEATURE_SIGNATURE "${ANDROID_STL_FORCE_FEATURES}-${ANDROID_RTTI}-${ANDROID_EXCEPTIONS}" CACHE INTERNAL "Signature when the C++ features are last cached")
  339. endif ()
  340. # Urho3D - warn if static runtime is chosen when using SHARED Urho3D library type
  341. if (URHO3D_LIB_TYPE STREQUAL SHARED AND ANDROID_STL MATCHES static)
  342. message (WARNING "Using static C++ STL runtime (${ANDROID_STL}) with SHARED Urho3D library type may result in unpredictable runtime behavior.")
  343. endif ()
  344. if (NOT ANDROID_STL OR NOT ANDROID_STL_SAVED STREQUAL ANDROID_STL)
  345. # Urho3D - default to use LLVM libc++ runtime
  346. #set (ANDROID_DEFAULT_STL system)
  347. if (URHO3D_LIB_TYPE STREQUAL SHARED)
  348. set (ANDROID_DEFAULT_STL c++_shared)
  349. else ()
  350. set (ANDROID_DEFAULT_STL c++_static)
  351. endif ()
  352. set (ANDROID_STL ${ANDROID_DEFAULT_STL} CACHE STRING "Specify the C++ STL runtime (Android platform only), default to ${ANDROID_DEFAULT_STL}; STLport may only be used when URHO3D_NETWORK is disabled")
  353. # Urho3D - proper C++ STL runtime is required to build Urho3D, exclude those that do not cut it
  354. #set (ANDROID_SUPPORTED_RUNTIMES system gabi++_static gabi++_shared stlport_static stlport_shared gnustl_static gnustl_shared c++_static c++_shared)
  355. set (ANDROID_SUPPORTED_RUNTIMES stlport_static stlport_shared gnustl_static gnustl_shared c++_static c++_shared)
  356. set_property (CACHE ANDROID_STL PROPERTY STRINGS ${ANDROID_SUPPORTED_RUNTIMES})
  357. list (FIND ANDROID_SUPPORTED_RUNTIMES "${ANDROID_STL}" FOUND_INDEX) # Stringify as the actual variable may be empty
  358. if (FOUND_INDEX EQUAL -1)
  359. string (REPLACE ";" "\", \"" PRINTABLE_ANDROID_SUPPORTED_RUNTIMES "\"${ANDROID_SUPPORTED_RUNTIMES}\"")
  360. message (FATAL_ERROR "Unrecognized '${ANDROID_STL}' specified in the ANDROID_STL option, "
  361. "supported values are: ${PRINTABLE_ANDROID_SUPPORTED_RUNTIMES}.")
  362. endif ()
  363. if (ANDROID_STL STREQUAL system)
  364. if (ANDROID_STL_FORCE_FEATURES)
  365. set (ANDROID_RTTI 0)
  366. set (ANDROID_EXCEPTIONS 0)
  367. endif ()
  368. set (STL_LIBS stdc++)
  369. # If the 'system' runtime is used in combination with RTTI or C++ exceptions then automatically link against the GNU libsupc++ for now
  370. if (ANDROID_RTTI OR ANDROID_EXCEPTIONS)
  371. set (STL_LIBS ${STL_LIBS} supc++)
  372. endif ()
  373. set (STL_INCLUDE_DIRS ${ANDROID_NDK}/sources/cxx-stl/system/include)
  374. elseif (ANDROID_STL MATCHES gabi\\+\\+)
  375. set (STL_INCLUDE_DIRS ${ANDROID_NDK}/sources/cxx-stl/gabi++/include)
  376. elseif (ANDROID_STL MATCHES stlport)
  377. set (STL_LIBS ${ANDROID_STL})
  378. set (STL_LIBRARY_DIR ${ANDROID_NDK}/sources/cxx-stl/stlport/libs/${ANDROID_NDK_ABI_NAME})
  379. set (STL_INCLUDE_DIRS ${ANDROID_NDK}/sources/cxx-stl/stlport/stlport) # This is not a typo!
  380. elseif (ANDROID_STL MATCHES gnustl)
  381. set (STL_LIBS ${ANDROID_STL} supc++)
  382. set (STL_LIBRARY_DIR ${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/4.9/libs/${ANDROID_NDK_ABI_NAME})
  383. set (STL_INCLUDE_DIRS ${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/4.9/include ${STL_LIBRARY_DIR}/include)
  384. elseif (ANDROID_STL MATCHES c\\+\\+)
  385. set (STL_LIBS c++)
  386. # TODO: Remove this once libgcc.a is not being used
  387. set (GCC_FIX "-Wl,-z,muldefs")
  388. set (STL_LIBRARY_DIR ${ANDROID_NDK}/sources/cxx-stl/llvm-libc++/libs/${ANDROID_NDK_ABI_NAME})
  389. if (EXISTS ${ANDROID_NDK}/sources/cxx-stl/llvm-libc++/libcxx)
  390. set (LIBCXX libcxx/)
  391. set (LIBCXXABI libcxxabi/)
  392. endif ()
  393. set (STL_INCLUDE_DIRS ${ANDROID_NDK}/sources/cxx-stl/llvm-libc++/${LIBCXX}include ${ANDROID_NDK}/sources/cxx-stl/llvm-libc++abi/${LIBCXXABI}include ${ANDROID_NDK}/sources/android/support/include)
  394. endif ()
  395. file (GLOB SHARED_LIBS ${CMAKE_BINARY_DIR}/libs/${ANDROID_NDK_ABI_NAME}/lib*_shared.so)
  396. if (SHARED_LIBS)
  397. execute_process (COMMAND ${CMAKE_COMMAND} -E remove ${SHARED_LIBS})
  398. endif ()
  399. if (ANDROID_STL MATCHES shared)
  400. execute_process (COMMAND ${CMAKE_COMMAND} -E copy_if_different ${STL_LIBRARY_DIR}/lib${ANDROID_STL}.so ${CMAKE_BINARY_DIR}/libs/${ANDROID_NDK_ABI_NAME}/lib${ANDROID_STL}.so)
  401. endif ()
  402. if (STL_LIBS)
  403. string (REPLACE ";" " -l" STL_LINKER_FLAGS ";${STL_LIBS}")
  404. if (ANDROID_STL MATCHES system|static)
  405. set (STL_LINKER_FLAGS "-Wl,-Bstatic ${STL_LINKER_FLAGS} -Wl,-Bdynamic")
  406. endif ()
  407. set (STL_LINKER_FLAGS "-L${STL_LIBRARY_DIR} ${STL_LINKER_FLAGS} ${GCC_FIX}")
  408. else ()
  409. set (STL_LINKER_FLAGS)
  410. endif ()
  411. foreach (VAR ANDROID_RTTI ANDROID_EXCEPTIONS STL_INCLUDE_DIRS STL_LIBRARY_DIR STL_LINKER_FLAGS)
  412. set (${VAR} ${${VAR}} CACHE INTERNAL "C++ STL runtimes")
  413. endforeach ()
  414. set (ANDROID_STL_SAVED ${ANDROID_STL} CACHE INTERNAL "Last saved value for ANDROID_STL")
  415. endif ()
  416. # Cross compiler tools
  417. if (CMAKE_HOST_WIN32)
  418. set (TOOL_EXT .exe)
  419. endif ()
  420. if (CLANG)
  421. set (C_COMPILER clang)
  422. set (CXX_COMPILER clang++)
  423. else ()
  424. set (COMPILER_PREFIX ${ANDROID_TOOLCHAIN_MACHINE_NAME}-)
  425. set (C_COMPILER gcc)
  426. set (CXX_COMPILER g++)
  427. endif ()
  428. if (NOT CMAKE_C_COMPILER)
  429. set (COMPILER_PATH ${ANDROID_${CLANG}TOOLCHAIN_ROOT}/bin) # CLANG is empty when the compiler is not Clang
  430. if ("$ENV{USE_CCACHE}" AND NOT CMAKE_HOST_WIN32)
  431. execute_process (COMMAND whereis -b ccache COMMAND grep -o \\S*lib\\S* OUTPUT_VARIABLE CCACHE_SYMLINK ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
  432. if (CCACHE_SYMLINK AND EXISTS ${CCACHE_SYMLINK}/${COMPILER_PREFIX}${C_COMPILER} AND EXISTS ${CCACHE_SYMLINK}/${COMPILER_PREFIX}${CXX_COMPILER})
  433. set (COMPILER_PATH ${CCACHE_SYMLINK})
  434. else ()
  435. # Fallback to create the ccache symlink in the build tree itself
  436. execute_process (COMMAND which ccache RESULT_VARIABLE EXIT_CODE OUTPUT_VARIABLE CCACHE ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
  437. if (EXIT_CODE EQUAL 0 AND CCACHE)
  438. foreach (TOOL ${C_COMPILER} ${CXX_COMPILER})
  439. execute_process (COMMAND ${CMAKE_COMMAND} -E create_symlink ${CCACHE} ${CMAKE_BINARY_DIR}/${COMPILER_PREFIX}${TOOL})
  440. endforeach ()
  441. set (COMPILER_PATH ${CMAKE_BINARY_DIR})
  442. else ()
  443. message (WARNING "ccache may not have been installed on this host system. "
  444. "This is required to enable ccache support for Android NDK compiler toolchain. "
  445. "CMake has been configured to use the actual compiler toolchain instead of ccache. "
  446. "In order to rectify this, the build tree must be regenerated after installing ccache.")
  447. endif ()
  448. endif ()
  449. if (NOT COMPILER_PATH STREQUAL ${ANDROID_${CLANG}TOOLCHAIN_ROOT}/bin AND NOT $ENV{PATH} MATCHES ${ANDROID_${CLANG}TOOLCHAIN_ROOT}/bin)
  450. message (FATAL_ERROR "The bin directory containing the compiler toolchain (${ANDROID_${CLANG}TOOLCHAIN_ROOT}/bin) has not been added in the PATH environment variable. "
  451. "This is required to enable ccache support for Android NDK compiler toolchain.")
  452. endif ()
  453. endif ()
  454. set (CMAKE_C_COMPILER ${COMPILER_PATH}/${COMPILER_PREFIX}${C_COMPILER}${TOOL_EXT} CACHE PATH "C compiler")
  455. set (CMAKE_CXX_COMPILER ${COMPILER_PATH}/${COMPILER_PREFIX}${CXX_COMPILER}${TOOL_EXT} CACHE PATH "C++ compiler")
  456. set (CMAKE_ASM_COMPILER ${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-gcc${TOOL_EXT} CACHE PATH "assembler")
  457. set (CMAKE_STRIP ${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-strip${TOOL_EXT} CACHE PATH "strip")
  458. set (CMAKE_AR ${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-gcc-ar${TOOL_EXT} CACHE PATH "archive")
  459. set (CMAKE_LINKER ${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-ld${TOOL_EXT} CACHE PATH "linker")
  460. set (CMAKE_NM ${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-nm${TOOL_EXT} CACHE PATH "nm")
  461. set (CMAKE_OBJCOPY ${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-objcopy${TOOL_EXT} CACHE PATH "objcopy")
  462. set (CMAKE_OBJDUMP ${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-objdump${TOOL_EXT} CACHE PATH "objdump")
  463. set (CMAKE_RANLIB ${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-ranlib${TOOL_EXT} CACHE PATH "ranlib")
  464. endif ()
  465. # Compiler and linker flags
  466. if (NOT CMAKE_C_FLAGS OR NOT FLAGS_SIGNATURE STREQUAL "${ANDROID_ABI}-${APP_PLATFORM_LEVEL}-${ANDROID_FORCE_ARM_BUILD}-${ANDROID_STACK_PROTECTION}-${ANDROID_NO_UNDEFINED}-${ANDROID_NOEXECSTACK}-${ANDROID_RELRO}-${ANDROID_FATAL_WARNINGS}-${ANDROID_FORMAT_SECURITY}-${ANDROID_FUNCTION_LEVEL_LINKING}-${ANDROID_STL}-${ANDROID_STL_FORCE_FEATURES}-${ANDROID_RTTI}-${ANDROID_EXCEPTIONS}")
  467. set (CMAKE_C_FLAGS "-fsigned-char -funwind-tables -no-canonical-prefixes")
  468. set (CMAKE_C_FLAGS_RELEASE "-O3 -DNDEBUG")
  469. set (CMAKE_C_FLAGS_DEBUG "-O0 -g -DDEBUG -D_DEBUG")
  470. set (CMAKE_SHARED_LINKER_FLAGS "-Wl,--build-id -Wl,--warn-shared-textrel")
  471. if (CLANG)
  472. set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -gcc-toolchain ${ANDROID_TOOLCHAIN_ROOT} -target ${ANDROID_LLVM_TRIPLE} -Wno-invalid-command-line-argument -Wno-unused-command-line-argument")
  473. set (CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -fno-limit-debug-info")
  474. endif ()
  475. if (ANDROID_ABI MATCHES armeabi)
  476. if (CLANG)
  477. set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-integrated-as")
  478. endif ()
  479. if (ANDROID_ABI MATCHES -v7a)
  480. set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=armv7-a")
  481. set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--fix-cortex-a8")
  482. elseif (ANDROID_ABI MATCHES -v6)
  483. set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=armv6")
  484. else ()
  485. set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=armv5te -mtune=xscale")
  486. endif ()
  487. if (ANDROID_ABI MATCHES -v7a|-v6)
  488. set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mfloat-abi=softfp")
  489. else ()
  490. set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -msoft-float")
  491. endif ()
  492. foreach (FPU neon-vfpv4 neon vfpv4 vfpv3 vfpv3-d16 vfp)
  493. if (ANDROID_ABI MATCHES " ${FPU}$")
  494. set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mfpu=${FPU}")
  495. endif ()
  496. endforeach ()
  497. if (ANDROID_FORCE_ARM_BUILD)
  498. set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -marm")
  499. else ()
  500. set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mthumb")
  501. endif ()
  502. elseif (ANDROID_ABI MATCHES mips)
  503. set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -finline-functions -fmessage-length=0")
  504. if (NOT CLANG)
  505. set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-inline-functions-called-once -fgcse-after-reload -frerun-cse-after-loop -frename-registers")
  506. endif ()
  507. # Clang outputs mips32r2 by default, switch to mips32r1
  508. # TODO: Remove this once mipsel-linux-android target is changed in clang
  509. if (ANDROID_ABI STREQUAL mips)
  510. set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mips32")
  511. endif ()
  512. endif ()
  513. # The ld.bfd needs help to find the location of the rooted shared libraries while ld.gold doesn't
  514. # TODO: Remove this once gold linker is the default for all the archs or when it is not possible to switch to use ld.bfd
  515. set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-rpath-link,\"${CMAKE_SYSROOT}/usr/lib\":\"${CMAKE_SYSROOT}/lib\":\"${STL_LIBRARY_DIR}\"")
  516. option (ANDROID_STACK_PROTECTION "Force the addition of a stack canary that checks for stack smashing")
  517. if (ANDROID_STACK_PROTECTION)
  518. set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fstack-protector-strong")
  519. endif ()
  520. option (ANDROID_NO_UNDEFINED "Ensure that a binary doesn't reference undefined symbols" TRUE)
  521. if (ANDROID_NO_UNDEFINED)
  522. set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--no-undefined")
  523. endif ()
  524. option (ANDROID_NOEXECSTACK "Enforce the NX (no execute) security feature in the generated machine code" TRUE)
  525. if (ANDROID_NOEXECSTACK)
  526. set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wa,--noexecstack")
  527. set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-z,noexecstack")
  528. endif ()
  529. option (ANDROID_RELRO "Mark certain regions of the resulting executable or shared library as being read-only" TRUE)
  530. if (ANDROID_RELRO)
  531. set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-z,relro -Wl,-z,now")
  532. endif ()
  533. option (ANDROID_FATAL_WARNINGS "Treat all linker warnings as errors" TRUE)
  534. if (ANDROID_FATAL_WARNINGS)
  535. set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--fatal-warnings")
  536. endif ()
  537. option (ANDROID_FORMAT_SECURITY "Provide compiler protection against format string vulnerabilities" TRUE)
  538. if (ANDROID_FORMAT_SECURITY)
  539. set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wformat -Werror=format-security")
  540. endif ()
  541. option (ANDROID_FUNCTION_LEVEL_LINKING "Split data/function sections and garbage collect unused sections at link time" TRUE)
  542. if (ANDROID_FUNCTION_LEVEL_LINKING)
  543. set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fdata-sections -ffunction-sections")
  544. set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--gc-sections")
  545. endif ()
  546. # RelWithDebInfo and MinSizeRel build configurations are just derivative of Release build configuration
  547. string (REPLACE -O3 "-O2 -g" CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELEASE}")
  548. string (REPLACE -O3 -Os CMAKE_C_FLAGS_MINSIZEREL "${CMAKE_C_FLAGS_RELEASE}")
  549. foreach (VAR _FLAGS _FLAGS_RELEASE _FLAGS_DEBUG _FLAGS_RELWITHDEBINFO _FLAGS_MINSIZEREL)
  550. set (CMAKE_C${VAR} ${CMAKE_C${VAR}} CACHE INTERNAL "C Compiler flags")
  551. set (CMAKE_CXX${VAR} ${CMAKE_C${VAR}} CACHE INTERNAL "CXX Compiler flags")
  552. endforeach ()
  553. # Only CXX compiler can accept these flags
  554. if (ANDROID_RTTI)
  555. set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -frtti" CACHE INTERNAL "CXX Compiler flags")
  556. else ()
  557. set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti" CACHE INTERNAL "CXX Compiler flags")
  558. endif ()
  559. if (ANDROID_EXCEPTIONS)
  560. set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fexceptions" CACHE INTERNAL "CXX Compiler flags")
  561. else ()
  562. set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-exceptions" CACHE INTERNAL "CXX Compiler flags")
  563. endif ()
  564. set (CMAKE_EXE_LINKER_FLAGS -Wl,-z,nocopyreloc)
  565. if (NOT APP_PLATFORM_LEVEL LESS 16)
  566. set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pie")
  567. endif ()
  568. set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${CMAKE_SHARED_LINKER_FLAGS}" CACHE INTERNAL "EXE linker flags")
  569. set (CMAKE_SHARED_LINKER_FLAGS ${CMAKE_SHARED_LINKER_FLAGS} CACHE INTERNAL "SHARED linker flags")
  570. set (CMAKE_MODULE_LINKER_FLAGS ${CMAKE_SHARED_LINKER_FLAGS} CACHE INTERNAL "MODULE linker flags")
  571. set (FLAGS_SIGNATURE "${ANDROID_ABI}-${APP_PLATFORM_LEVEL}-${ANDROID_FORCE_ARM_BUILD}-${ANDROID_STACK_PROTECTION}-${ANDROID_NO_UNDEFINED}-${ANDROID_NOEXECSTACK}-${ANDROID_RELRO}-${ANDROID_FATAL_WARNINGS}-${ANDROID_FORMAT_SECURITY}-${ANDROID_FUNCTION_LEVEL_LINKING}-${ANDROID_STL}-${ANDROID_STL_FORCE_FEATURES}-${ANDROID_RTTI}-${ANDROID_EXCEPTIONS}" CACHE INTERNAL "Signature when the compiler/linker flags are last cached")
  572. endif ()
  573. # Workaround try_compile() limitation
  574. set (ENV{CMAKE_SYSROOT} ${CMAKE_SYSROOT})
  575. set (ENV{STL_INCLUDE_DIRS} "${STL_INCLUDE_DIRS}") # Stringify to keep the list together
  576. set (ENV{STL_LINKER_FLAGS} "${STL_LINKER_FLAGS}")
  577. else ()
  578. set (CMAKE_SYSROOT $ENV{CMAKE_SYSROOT})
  579. set (STL_INCLUDE_DIRS $ENV{STL_INCLUDE_DIRS})
  580. set (STL_LINKER_FLAGS $ENV{STL_LINKER_FLAGS})
  581. endif ()
  582. include_directories (SYSTEM ${STL_INCLUDE_DIRS})
  583. # Cannot use link_directories() and link_libraries() commands here because CMake will emit the linker flags in an undesirable order
  584. # Workaround the problem by injecting the linker flags the last explicitly in the CMake build rules
  585. # This is a hack as it relies on internal implementation, i.e. the hard-coded rules must be kept in sync manually with CMake's Modules/CMakeCXXInformation.cmake file
  586. set (CMAKE_CXX_CREATE_SHARED_LIBRARY "<CMAKE_CXX_COMPILER> <CMAKE_SHARED_LIBRARY_CXX_FLAGS> <LANGUAGE_COMPILE_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS> <SONAME_FLAG><TARGET_SONAME> -o <TARGET> <OBJECTS> <LINK_LIBRARIES> ${STL_LINKER_FLAGS}")
  587. set (CMAKE_CXX_CREATE_SHARED_MODULE "<CMAKE_CXX_COMPILER> <CMAKE_SHARED_LIBRARY_CXX_FLAGS> <LANGUAGE_COMPILE_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS> <SONAME_FLAG><TARGET_SONAME> -o <TARGET> <OBJECTS> <LINK_LIBRARIES> ${STL_LINKER_FLAGS}")
  588. set (CMAKE_CXX_LINK_EXECUTABLE "<CMAKE_CXX_COMPILER> <FLAGS> <CMAKE_CXX_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES> ${STL_LINKER_FLAGS}")
  589. # Only search libraries and headers in sysroot
  590. set (CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
  591. set (CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
  592. set (CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
  593. # Use response files on Windows host to avoid failure in the linking phase with too long command line
  594. if (CMAKE_HOST_WIN32)
  595. set (CMAKE_C_USE_RESPONSE_FILE_FOR_OBJECTS 1)
  596. set (CMAKE_CXX_USE_RESPONSE_FILE_FOR_OBJECTS 1)
  597. endif ()