1# Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
2# file Copyright.txt or https://cmake.org/licensing for details.
3
4# This module is shared by multiple languages; use include blocker.
5if(__ANDROID_COMPILER_COMMON)
6  return()
7endif()
8set(__ANDROID_COMPILER_COMMON 1)
9
10if(CMAKE_ANDROID_NDK)
11  # <ndk>/build/core/definitions.mk
12
13  set(_ANDROID_STL_TYPES
14    none
15    system
16    c++_static
17    c++_shared
18    gabi++_static
19    gabi++_shared
20    gnustl_static
21    gnustl_shared
22    stlport_static
23    stlport_shared
24    )
25
26  if(CMAKE_ANDROID_STL_TYPE)
27    list(FIND _ANDROID_STL_TYPES "${CMAKE_ANDROID_STL_TYPE}" _ANDROID_STL_TYPE_FOUND)
28    if(_ANDROID_STL_TYPE_FOUND EQUAL -1)
29      string(REPLACE ";" "\n  " _msg ";${_ANDROID_STL_TYPES}")
30      message(FATAL_ERROR
31        "The CMAKE_ANDROID_STL_TYPE '${CMAKE_ANDROID_STL_TYPE}' is not one of the allowed values:${_msg}\n"
32        )
33    endif()
34    unset(_ANDROID_STL_TYPE_FOUND)
35  elseif(IS_DIRECTORY ${CMAKE_ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++)
36    set(CMAKE_ANDROID_STL_TYPE "gnustl_static")
37  else()
38    set(CMAKE_ANDROID_STL_TYPE "c++_static")
39  endif()
40
41  unset(_ANDROID_STL_TYPES)
42
43  # Forward Android-specific platform variables to try_compile projects.
44  list(APPEND CMAKE_TRY_COMPILE_PLATFORM_VARIABLES
45    CMAKE_ANDROID_STL_TYPE
46    )
47endif()
48
49if(CMAKE_ANDROID_STL_TYPE)
50  if(CMAKE_ANDROID_NDK_TOOLCHAIN_UNIFIED)
51    if(CMAKE_ANDROID_STL_TYPE STREQUAL "system")
52      set(_ANDROID_STL_EXCEPTIONS 0)
53      set(_ANDROID_STL_RTTI 0)
54      macro(__android_stl lang)
55        string(APPEND CMAKE_${lang}_FLAGS_INIT " -stdlib=libstdc++")
56        if(_ANDROID_STL_EXCEPTIONS OR _ANDROID_STL_RTTI)
57          string(APPEND CMAKE_${lang}_STANDARD_LIBRARIES " -lc++abi")
58          if(CMAKE_SYSTEM_VERSION LESS 21)
59            string(APPEND CMAKE_${lang}_STANDARD_LIBRARIES " -landroid_support")
60          endif()
61        endif()
62      endmacro()
63    elseif(CMAKE_ANDROID_STL_TYPE STREQUAL "c++_static")
64      set(_ANDROID_STL_EXCEPTIONS 1)
65      set(_ANDROID_STL_RTTI 1)
66      macro(__android_stl lang)
67        string(APPEND CMAKE_${lang}_FLAGS_INIT " -stdlib=libc++")
68        string(APPEND CMAKE_${lang}_STANDARD_LIBRARIES " -static-libstdc++")
69      endmacro()
70    elseif(CMAKE_ANDROID_STL_TYPE STREQUAL "c++_shared")
71      set(_ANDROID_STL_EXCEPTIONS 1)
72      set(_ANDROID_STL_RTTI 1)
73      macro(__android_stl lang)
74        string(APPEND CMAKE_${lang}_FLAGS_INIT " -stdlib=libc++")
75      endmacro()
76    elseif(CMAKE_ANDROID_STL_TYPE STREQUAL "none")
77      set(_ANDROID_STL_RTTI 0)
78      set(_ANDROID_STL_EXCEPTIONS 0)
79      macro(__android_stl lang)
80        # FIXME: Add a way to add project-wide language-specific compile-only flags.
81        set(CMAKE_CXX_COMPILE_OBJECT
82          "<CMAKE_CXX_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -o <OBJECT> -c <SOURCE> -nostdinc++")
83        string(APPEND CMAKE_${lang}_STANDARD_LIBRARIES " -nostdlib++")
84      endmacro()
85    else()
86      message(FATAL_ERROR
87        "Android: STL '${CMAKE_ANDROID_STL_TYPE}' not supported by this NDK."
88        )
89    endif()
90    if(DEFINED CMAKE_ANDROID_RTTI)
91      set(_ANDROID_STL_RTTI ${CMAKE_ANDROID_RTTI})
92    endif()
93    if(DEFINED CMAKE_ANDROID_EXCEPTIONS)
94      set(_ANDROID_STL_EXCEPTIONS ${CMAKE_ANDROID_EXCEPTIONS})
95    endif()
96  elseif(CMAKE_ANDROID_NDK)
97
98    macro(__android_stl_inc lang dir req)
99      if(EXISTS "${dir}")
100        list(APPEND CMAKE_${lang}_STANDARD_INCLUDE_DIRECTORIES "${dir}")
101      elseif(${req})
102        message(FATAL_ERROR
103          "Android: STL '${CMAKE_ANDROID_STL_TYPE}' include directory not found:\n"
104          "  ${dir}"
105          )
106      endif()
107    endmacro()
108
109    macro(__android_stl_lib lang lib req)
110      if(CMAKE_ANDROID_ARCH_ABI MATCHES "^armeabi" AND NOT CMAKE_ANDROID_ARM_MODE)
111        get_filename_component(_ANDROID_STL_LIBDIR "${lib}" DIRECTORY)
112        get_filename_component(_ANDROID_STL_LIBNAME "${lib}" NAME)
113        set(_ANDROID_STL_LIBTHUMB "${_ANDROID_STL_LIBDIR}/thumb/${_ANDROID_STL_LIBNAME}")
114        unset(_ANDROID_STL_LIBDIR)
115        unset(_ANDROID_STL_LIBNAME)
116      else()
117        set(_ANDROID_STL_LIBTHUMB "")
118      endif()
119
120      if(_ANDROID_STL_LIBTHUMB AND EXISTS "${_ANDROID_STL_LIBTHUMB}")
121        string(APPEND CMAKE_${lang}_STANDARD_LIBRARIES " \"${_ANDROID_STL_LIBTHUMB}\"")
122      elseif(EXISTS "${lib}")
123        string(APPEND CMAKE_${lang}_STANDARD_LIBRARIES " \"${lib}\"")
124      elseif(${req})
125        message(FATAL_ERROR
126          "Android: STL '${CMAKE_ANDROID_STL_TYPE}' library file not found:\n"
127          "  ${lib}"
128          )
129      endif()
130
131      unset(_ANDROID_STL_LIBTHUMB)
132    endmacro()
133
134    include(Platform/Android/ndk-stl-${CMAKE_ANDROID_STL_TYPE})
135  else()
136    macro(__android_stl lang)
137    endmacro()
138  endif()
139else()
140  macro(__android_stl lang)
141  endmacro()
142endif()
143
144# The NDK toolchain configuration files at:
145#
146#   <ndk>/[build/core/]toolchains/*/setup.mk
147#
148# contain logic to set TARGET_CFLAGS and TARGET_LDFLAGS (and debug/release
149# variants) to tell their build system what flags to pass for each ABI.
150# We need to produce the same flags here to produce compatible binaries.
151# We initialize these variables here and set them in the compiler-specific
152# modules that include this one.  Then we use them in the macro below when
153# it is called.
154set(_ANDROID_ABI_INIT_CFLAGS "")
155set(_ANDROID_ABI_INIT_CFLAGS_DEBUG "")
156set(_ANDROID_ABI_INIT_CFLAGS_RELEASE "")
157set(_ANDROID_ABI_INIT_LDFLAGS "")
158set(_ANDROID_ABI_INIT_EXE_LDFLAGS "")
159
160macro(__android_compiler_common lang)
161  if(_ANDROID_ABI_INIT_CFLAGS)
162    string(APPEND CMAKE_${lang}_FLAGS_INIT " ${_ANDROID_ABI_INIT_CFLAGS}")
163  endif()
164  if(_ANDROID_ABI_INIT_CFLAGS_DEBUG)
165    string(APPEND CMAKE_${lang}_FLAGS_DEBUG_INIT " ${_ANDROID_ABI_INIT_CFLAGS_DEBUG}")
166  endif()
167  if(_ANDROID_ABI_INIT_CFLAGS_RELEASE)
168    string(APPEND CMAKE_${lang}_FLAGS_RELEASE_INIT " ${_ANDROID_ABI_INIT_CFLAGS_RELEASE}")
169    string(APPEND CMAKE_${lang}_FLAGS_MINSIZEREL_INIT " ${_ANDROID_ABI_INIT_CFLAGS_RELEASE}")
170    string(APPEND CMAKE_${lang}_FLAGS_RELWITHDEBINFO_INIT " ${_ANDROID_ABI_INIT_CFLAGS_RELEASE}")
171  endif()
172  if(_ANDROID_ABI_INIT_LDFLAGS)
173    foreach(t EXE SHARED MODULE)
174      string(APPEND CMAKE_${t}_LINKER_FLAGS_INIT " ${_ANDROID_ABI_INIT_LDFLAGS}")
175    endforeach()
176  endif()
177  if(_ANDROID_ABI_INIT_EXE_LDFLAGS)
178    string(APPEND CMAKE_EXE_LINKER_FLAGS_INIT " ${_ANDROID_ABI_INIT_EXE_LDFLAGS}")
179  endif()
180
181  if(DEFINED _ANDROID_STL_EXCEPTIONS)
182    if(_ANDROID_STL_EXCEPTIONS)
183      string(APPEND CMAKE_${lang}_FLAGS_INIT " -fexceptions")
184    else()
185      string(APPEND CMAKE_${lang}_FLAGS_INIT " -fno-exceptions")
186    endif()
187  endif()
188
189  if("x${lang}" STREQUAL "xCXX" AND DEFINED _ANDROID_STL_RTTI)
190    if(_ANDROID_STL_RTTI)
191      string(APPEND CMAKE_${lang}_FLAGS_INIT " -frtti")
192    else()
193      string(APPEND CMAKE_${lang}_FLAGS_INIT " -fno-rtti")
194    endif()
195  endif()
196
197  if("x${lang}" STREQUAL "xCXX")
198    __android_stl(CXX)
199  endif()
200
201  if(CMAKE_ANDROID_NDK_TOOLCHAIN_UNIFIED)
202    string(APPEND CMAKE_${lang}_STANDARD_LIBRARIES " -latomic -lm")
203  endif()
204
205  # <ndk>/build/core/definitions.mk appends the sysroot's include directory
206  # explicitly at the end of the command-line include path so that it
207  # precedes the toolchain's builtin include directories.  This is
208  # necessary so that Android API-version-specific headers are preferred
209  # over those in the toolchain's `include-fixed` directory (which cannot
210  # possibly match all versions).
211  #
212  # Do not do this for a standalone toolchain because it is already
213  # tied to a specific API version.
214  if(CMAKE_ANDROID_NDK AND NOT CMAKE_ANDROID_NDK_TOOLCHAIN_UNIFIED)
215    if(CMAKE_SYSROOT_COMPILE)
216      set(_cmake_sysroot_compile "${CMAKE_SYSROOT_COMPILE}")
217    else()
218      set(_cmake_sysroot_compile "${CMAKE_SYSROOT}")
219    endif()
220    if(NOT CMAKE_ANDROID_NDK_DEPRECATED_HEADERS)
221      list(APPEND CMAKE_${lang}_STANDARD_INCLUDE_DIRECTORIES
222        "${_cmake_sysroot_compile}/usr/include"
223        "${_cmake_sysroot_compile}/usr/include/${CMAKE_ANDROID_ARCH_TRIPLE}"
224        )
225    else()
226      list(APPEND CMAKE_${lang}_STANDARD_INCLUDE_DIRECTORIES "${_cmake_sysroot_compile}/usr/include")
227    endif()
228    unset(_cmake_sysroot_compile)
229  endif()
230endmacro()
231