android.cmake 9.3 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
# Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserve.
# 
# 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.

# This is a toolchain file for cross-compiling for Android, and the
# configuration refers to the open-source resposity:
#     https://github.com/taka-no-me/android-cmake
# Most of the variables are compatible with that used in
#     https://developer.android.com/ndk/guides/cmake.html
L
Liu Yiqun 已提交
20
# The supported variables are listed belows:
21 22
# 
# ANDROID_STANDALONE_TOOLCHAIN
23
# ANDROID_TOOLCHAIN
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
# ANDROID_ABI
# ANDROID_NATIVE_API_LEVEL
# ANDROID_ARM_MODE
# ANDROID_ARM_NEON
#
# For CMake >= 3.7.0, all the settings will be delivered to CMake system
# variables to let CMake do the cross-compiling configurations itself.
# More detail of cross-compiling settings
#     https://cmake.org/cmake/help/v3.7/manual/cmake-toolchains.7.html

IF(NOT ANDROID)
    return()
ENDIF()

# check the exist of android standalone toolchain
IF(NOT DEFINED ANDROID_STANDALONE_TOOLCHAIN)
    SET(ANDROID_STANDALONE_TOOLCHAIN $ENV{ANDROID_STANDALONE_TOOLCHAIN}
        CACHE PATH "Folder holds the standalone toolchain of Android NDK")
ENDIF()
IF(NOT ANDROID_STANDALONE_TOOLCHAIN)
L
Liu Yiqun 已提交
44
    MESSAGE(WARNING "It is recommended to set ANDROID_STANDALONE_TOOLCHAIN to "
45
            "use a standalone toolchain.\n"
46 47 48 49
            "To cross-compile for Android, you need to:\n"
            "1. Download an Android NDK from"
            " https://developer.android.com/ndk/downloads/index.html\n"
            "2. Setup a standalone toolchain"
L
Liu Yiqun 已提交
50
            "https://developer.android.google.cn/ndk/guides/standalone_toolchain.html?hl=zh-cn\n")
51 52
ENDIF()

L
Liu Yiqun 已提交
53
IF(NOT DEFINED CMAKE_SYSTEM_VERSION AND ANDROID_NATIVE_API_LEVEL)
54 55 56 57 58 59 60
    IF(ANDROID_NATIVE_API_LEVEL MATCHES "^android-[0-9]+$")
        STRING(REPLACE "android-" "" CMAKE_SYSTEM_VERSION "${CMAKE_MATCH_0}")
    ELSEIF(ANDROID_NATIVE_API_LEVEL MATCHES "^[0-9]+$")
        SET(CMAKE_SYSTEM_VERSION ${ANDROID_NATIVE_API_LEVEL})
    ENDIF()
ENDIF()

61 62 63 64
IF(NOT DEFINED ANDROID_TOOLCHAIN)
    SET(ANDROID_TOOLCHAIN clang)
ENDIF()

65 66 67 68 69 70 71
IF(NOT DEFINED ANDROID_ABI)
    SET(ANDROID_ABI "armeabi-v7a")
ENDIF()

IF(NOT DEFINED ANDROID_ARM_MODE)
    SET(ANDROID_ARM_MODE ON)
ENDIF()
L
Liu Yiqun 已提交
72
IF(ANDROID_ARM_MODE)
73
    SET(ANDROID_ARM_MODE_NAME "arm")
L
Liu Yiqun 已提交
74 75 76
ELSE(ANDROID_ARM_MODE)
    SET(ANDROID_ARM_MODE_NAME "thumb")
ENDIF(ANDROID_ARM_MODE)
77

78 79 80 81
IF(NOT DEFINED ANDROID_ARM_NEON)
    SET(ANDROID_ARM_NEON ON)
ENDIF()

L
Liu Yiqun 已提交
82 83
IF("${CMAKE_VERSION}" VERSION_LESS "3.7.0")
    IF("${CMAKE_VERSION}" VERSION_LESS "3.1.0")
84 85 86 87 88
        SET(CMAKE_SYSTEM_NAME "Linux")
    ENDIF()
    MESSAGE(WARNING "It is recommended to use CMake >= 3.7.0 (current version: "
            "${CMAKE_VERSION}), when cross-compiling for Android.")

89
    IF(ANDROID_STANDALONE_TOOLCHAIN)
90
        # Use standalone toolchain
91 92 93 94 95 96 97 98 99 100 101
        SET(CMAKE_SYSROOT "${ANDROID_STANDALONE_TOOLCHAIN}/sysroot")

        IF(NOT CMAKE_SYSTEM_VERSION)
            SET(ANDROID_STANDALONE_TOOLCHAIN_API "")
            SET(ANDROID_API_LEVEL_H_REGEX "^[\t ]*#[\t ]*define[\t ]+__ANDROID_API__[\t ]+([0-9]+)")
            FILE(STRINGS "${ANDROID_STANDALONE_TOOLCHAIN}/sysroot/usr/include/android/api-level.h"
                ANDROID_API_LEVEL_H_CONTENT REGEX "${ANDROID_API_LEVEL_H_REGEX}")
            IF(ANDROID_API_LEVEL_H_CONTENT MATCHES "${ANDROID_API_LEVEL_H_REGEX}")
                SET(ANDROID_STANDALONE_TOOLCHAIN_API "${CMAKE_MATCH_1}")
            ENDIF()
            SET(CMAKE_SYSTEM_VERSION ${ANDROID_STANDALONE_TOOLCHAIN_API})
102 103
        ENDIF()

104 105
        # Toolchain
        SET(ANDROID_TOOLCHAIN_ROOT ${ANDROID_STANDALONE_TOOLCHAIN})
106 107 108 109 110 111 112 113 114 115 116 117
    ELSE(ANDROID_NDK)
        # TODO: use android ndk
    ENDIF()

    IF(ANDROID_ABI MATCHES "^armeabi(-v7a)?$")
        SET(ANDROID_TOOLCHAIN_NAME arm-linux-androideabi)
        IF(ANDROID_ABI STREQUAL "armeabi")
            SET(CMAKE_SYSTEM_PROCESSOR armv5te)
            SET(ANDROID_CLANG_TRIPLE armv5te-none-linux-androideabi)
        ELSEIF(ANDROID_ABI STREQUAL "armeabi-v7a")
            SET(CMAKE_SYSTEM_PROCESSOR armv7-a)
            SET(ANDROID_CLANG_TRIPLE armv7-none-linux-androideabi)
H
hedaoyuan 已提交
118
        ENDIF()
119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
    ELSEIF(ANDROID_ABI STREQUAL "arm64-v8a")
        SET(ANDROID_TOOLCHAIN_NAME aarch64-linux-android)
        SET(CMAKE_SYSTEM_PROCESSOR aarch64)
        SET(ANDROID_CLANG_TRIPLE aarch64-none-linux-android)
    ELSE()
        MESSAGE(FATAL_ERROR "Invalid Android ABI: ${ANDROID_ABI}.")
    ENDIF()
    SET(ANDROID_TOOLCHAIN_PREFIX "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_NAME}-")

    IF(ANDROID_TOOLCHAIN STREQUAL clang)
        SET(ANDROID_C_COMPILER_NAME clang)
        SET(ANDROID_CXX_COMPILER_NAME clang++)
        SET(CMAKE_C_COMPILER_TARGET   ${ANDROID_CLANG_TRIPLE})
        SET(CMAKE_CXX_COMPILER_TARGET ${ANDROID_CLANG_TRIPLE})
    ELSEIF(ANDROID_TOOLCHAIN STREQUAL gcc)
        SET(ANDROID_C_COMPILER_NAME gcc)
        SET(ANDROID_CXX_COMPILER_NAME g++)
    ELSE()
        MESSAGE(FATAL_ERROR "Invalid Android toolchain: ${ANDROID_TOOLCHAIN}")
138
    ENDIF()
139

140 141
    # C compiler
    IF(NOT CMAKE_C_COMPILER)
142
        SET(ANDROID_C_COMPILER "${ANDROID_TOOLCHAIN_PREFIX}${ANDROID_C_COMPILER_NAME}")
143
    ELSE()
L
Liu Yiqun 已提交
144
        GET_FILENAME_COMPONENT(ANDROID_C_COMPILER ${CMAKE_C_COMPILER} PROGRAM)
145 146
    ENDIF()
    IF(NOT EXISTS ${ANDROID_C_COMPILER})
L
Liu Yiqun 已提交
147
        MESSAGE(FATAL_ERROR "Cannot find C compiler: ${ANDROID_C_COMPILER}")
148 149
    ENDIF()

150 151
    # CXX compiler
    IF(NOT CMAKE_CXX_COMPILER)
152
        SET(ANDROID_CXX_COMPILER "${ANDROID_TOOLCHAIN_PREFIX}${ANDROID_CXX_COMPILER_NAME}")
153
    ELSE()
L
Liu Yiqun 已提交
154
        GET_FILENAME_COMPONENT(ANDROID_CXX_COMPILER ${CMAKE_CXX_COMPILER} PROGRAM)
155 156
    ENDIF()
    IF(NOT EXISTS ${ANDROID_CXX_COMPILER})
L
Liu Yiqun 已提交
157
        MESSAGE(FATAL_ERROR "Cannot find CXX compiler: ${ANDROID_CXX_COMPILER}")
158 159
    ENDIF()

160 161
    SET(CMAKE_C_COMPILER ${ANDROID_C_COMPILER} CACHE PATH "C compiler" FORCE)
    SET(CMAKE_CXX_COMPILER ${ANDROID_CXX_COMPILER} CACHE PATH "CXX compiler" FORCE)
162 163

    # Toolchain and ABI specific flags.
164
    SET(ANDROID_COMPILER_FLAGS "-ffunction-sections -fdata-sections")
165 166 167 168 169 170 171
    SET(ANDROID_LINKER_FLAGS "-Wl,--gc-sections")

    IF(ANDROID_ABI STREQUAL "armeabi")
        LIST(APPEND ANDROID_COMPILER_FLAGS
             -march=armv5te
             -mtune=xscale
             -msoft-float)
172
    ELSEIF(ANDROID_ABI STREQUAL "armeabi-v7a")
173 174 175 176 177 178 179 180 181
        LIST(APPEND ANDROID_COMPILER_FLAGS
             -march=armv7-a
             -mfloat-abi=softfp)
        IF(ANDROID_ARM_NEON)
            LIST(APPEND ANDROID_COMPILER_FLAGS -mfpu=neon)
        ELSE()
            LIST(APPEND ANDROID_COMPILER_FLAGS -mfpu=vfpv3-d16)
        ENDIF()
        LIST(APPEND ANDROID_LINKER_FLAGS -Wl,--fix-cortex-a8)
182 183
    ELSEIF(ANDROID_ABI STREQUAL "arm64-v8a")
        LIST(APPEND ANDROID_COMPILER_FLAGS -march=armv8-a)
184 185 186 187 188 189 190 191
    ENDIF()

    IF(ANDROID_ABI MATCHES "^armeabi(-v7a)?$")
        IF(ANDROID_ARM_MODE)
            LIST(APPEND ANDROID_COMPILER_FLAGS -marm)
        ELSE()
            LIST(APPEND ANDROID_COMPILER_FLAGS -mthumb)
        ENDIF()
192 193 194 195
        IF(ANDROID_TOOLCHAIN STREQUAL clang)
            # Disable integrated-as for better compatibility.
            LIST(APPEND ANDROID_COMPILER_FLAGS -fno-integrated-as)
        ENDIF()
196 197
    ENDIF()

198 199 200 201 202 203
    IF(ANDROID_TOOLCHAIN STREQUAL clang)
        # CMake automatically forwards all compiler flags to the linker,
        # and clang doesn't like having -Wa flags being used for linking.
        # To prevent CMake from doing this would require meddling with
        # the CMAKE_<LANG>_COMPILE_OBJECT rules, which would get quite messy.
        LIST(APPEND ANDROID_LINKER_FLAGS -Qunused-arguments)
H
hedaoyuan 已提交
204 205
    ENDIF()

206 207 208 209
    STRING(REPLACE ";" " " ANDROID_COMPILER_FLAGS "${ANDROID_COMPILER_FLAGS}")
    STRING(REPLACE ";" " " ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS}")

    SET(CMAKE_C_FLAGS "${ANDROID_COMPILER_FLAGS} ${CMAKE_C_FLAGS}"
L
Liu Yiqun 已提交
210
        CACHE STRING "C flags")
211
    SET(CMAKE_CXX_FLAGS "${ANDROID_COMPILER_FLAGS} ${CMAKE_CXX_FLAGS}"
L
Liu Yiqun 已提交
212
        CACHE STRING "CXX flags")
213 214 215 216 217 218 219 220 221 222 223 224 225
    SET(CMAKE_SHARED_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} ${CMAKE_SHARED_LINKER_FLAGS}"
        CACHE STRING "shared linker flags")

    SET(CMAKE_POSITION_INDEPENDENT_CODE TRUE)
    SET(CMAKE_EXE_LINKER_FLAGS "-pie -fPIE ${ANDROID_LINKER_FLAGS} ${CMAKE_EXE_LINKER_FLAGS}"
        CACHE STRING "executable linker flags")

    MESSAGE(STATUS "Android: Targeting API '${CMAKE_SYSTEM_VERSION}' "
            "with architecture '${ANDROID_ARM_MODE_NAME}', "
            "ABI '${ANDROID_ABI}', and processor '${CMAKE_SYSTEM_PROCESSOR}'")
    MESSAGE(STATUS "System CMAKE_C_FLAGS: " ${CMAKE_C_FLAGS})
    MESSAGE(STATUS "System CMAKE_CXX_FLAGS: " ${CMAKE_CXX_FLAGS})
ELSE()
L
Liu Yiqun 已提交
226 227 228
    IF(ANDROID_STANDALONE_TOOLCHAIN)
        SET(CMAKE_ANDROID_STANDALONE_TOOLCHAIN ${ANDROID_STANDALONE_TOOLCHAIN})
    ENDIF()
229
    SET(CMAKE_ANDROID_ARCH_ABI ${ANDROID_ABI})
230 231 232 233 234 235
    IF(ANDROID_ABI MATCHES "^armeabi(-v7a)?$")
        SET(CMAKE_ANDROID_ARM_MODE ${ANDROID_ARM_MODE})
        IF(ANDROID_ABI STREQUAL "armeabi-v7a")
            SET(CMAKE_ANDROID_ARM_NEON ${ANDROID_ARM_NEON})
        ENDIF()
    ENDIF()
236
ENDIF()