[cmake-developers] [RFC] FindAndroidNDK and UseAndroidNDK

Xiaolei Yu dreifachstein at gmail.com
Sat Mar 12 04:05:58 EST 2016


Hello,
my team decided to ditch ndk-build and migrate to cmake. And I would 
like to upstream these two modules, which are currently used in my hobby 
projects.

They are intended to be used by custom toolchain files in place of 
android.cmake. The goal is to preserve as much information as possible 
as I am using a cmake super build to drive dozens of external projects, 
while android.cmake merges most info into linker and c/cxx flags.

I am aware of the code style problems and will fix them in the formal 
patch. In this mail I am seeking your feedbacks on several issues:

1. using CMAKE_LIBRARY_ARCHITECTURE to represent android 
TARGET_ARCH_ABI. The way android handles native libraries is similar to 
debian multiarch and I am reusing this property.
Android-GNU-{C, CXX}.cmake will setup compiler flags based on it. I can 
think of another use case when a super build decides where to pull 
prebuilt blobs.

2. clang support is lacking. I am not using clang for android but can 
add the support if deemed necessary.

3. the FindAndroidNDK module is saving many values and I am not sure if 
all of them are worth to keep.

Best Regards



-------------- next part --------------

macro ( android_use_cxx_gnustl variant version )
  set ( _gnustl ${ANDROID_NDK_ROOT}/sources/cxx-stl/gnu-libstdc++/${version} )

  if ( "${variant}" STREQUAL "SHARED" )
    set ( CMAKE_CXX_STANDARD_LIBRARIES_INIT
      ${_gnustl}/libs/${CMAKE_LIBRARY_ARCHITECTURE}/libgnustl_shared.so
    )
  elseif ( "${variant}" STREQUAL "STATIC" )
    set ( CMAKE_CXX_STANDARD_LIBRARIES_INIT
      ${_gnustl}/libs/${CMAKE_LIBRARY_ARCHITECTURE}/libgnustl_static.a
      ${_gnustl}/libs/${CMAKE_LIBRARY_ARCHITECTURE}/libsupc++.a
    )
  else ()
    message ( FATAL_ERROR "invalid gnustl variant: ${variant}")
  endif ()

  include_directories ( SYSTEM
    ${_gnustl}/libs/${CMAKE_LIBRARY_ARCHITECTURE}/include
    ${_gnustl}/include
  )
endmacro ()

macro ( android_use_toolchain version )
  set ( CMAKE_C_COMPILER    ${AndroidNDK_GNU_CROSSPREFIX_${version}}gcc )
  set ( CMAKE_CXX_COMPILER  ${AndroidNDK_GNU_CROSSPREFIX_${version}}g++ )
endmacro ()
-------------- next part --------------

cmake_minimum_required ( VERSION 3.4 )

set ( _target_arch_abi_list
  armeabi armeabi-v7a armeabi-v7a-hard arm64
  x86 x86_64 mips mips64
)

if ( NOT "${CMAKE_LIBRARY_ARCHITECTURE}" IN_LIST _target_arch_abi_list )
  message ( FATAL_ERROR "invalid value: CMAKE_LIBRARY_ARCHITECTURE=${CMAKE_LIBRARY_ARCHITECTURE}" )
endif ()

set ( _target_arch_list
  arm arm64
  x86 x86_64
  mips mips64
)

set ( _target_arch )
set ( _gnu_mach )
set ( _gnu_os )
set ( _gnu_toolchain_name )

if ( CMAKE_LIBRARY_ARCHITECTURE MATCHES "^armeabi" )
  set ( _target_arch        arm )
  set ( _gnu_mach           arm )
  set ( _gnu_os             linux-androideabi )
elseif ( CMAKE_LIBRARY_ARCHITECTURE STREQUAL "arm64-v8a" )
  set ( _target_arch        arm64 )
  set ( _gnu_mach           aarch64 )
elseif ( CMAKE_LIBRARY_ARCHITECTURE STREQUAL "mips" )
  set ( _gnu_mach           mipsel )
elseif ( CMAKE_LIBRARY_ARCHITECTURE STREQUAL "mips64" )
  set ( _gnu_mach           mips64el )
elseif ( CMAKE_LIBRARY_ARCHITECTURE STREQUAL "x86" )
  set ( _gnu_mach           i686 )
  set ( _gnu_toolchain_name x86 )
elseif ( CMAKE_LIBRARY_ARCHITECTURE STREQUAL "x86_64" )
  set ( _gnu_toolchain_name x86_64 )
endif ()

if ( NOT _target_arch )
  set ( _target_arch ${CMAKE_LIBRARY_ARCHITECTURE} )
endif ()

if ( NOT _gnu_mach )
  set ( _gnu_mach    ${CMAKE_LIBRARY_ARCHITECTURE} )
endif ()
if ( NOT _gnu_os )
  set ( _gnu_os      linux-android )
endif ()
set ( _gnu_triplet   ${_gnu_mach}-${_gnu_os} )

if ( NOT _gnu_toolchain_name )
  set ( _gnu_toolchain_name ${_gnu_triplet} )
endif ()

macro ( _do_find_info )
  file ( READ ${ANDROID_NDK_ROOT}/RELEASE.TXT _release_txt_str )

  string ( REGEX MATCH "^r[^ ]+" AndroidNDK_VERSION_STRING ${_release_txt_str} )

  if ( ${_release_txt_str} MATCHES "64\\-bit" )
    set ( AndroidNDK_64BIT TRUE )
  else ()
    set ( AndroidNDK_64BIT FALSE )
  endif ()

  set ( AndroidNDK_64BIT ${AndroidNDK_64BIT} CACHE BOOL "64-bit" )
  
  find_path ( AndroidNDK_HOST_PREBUILT_DIR  bin
    PATHS ${ANDROID_NDK_ROOT}/prebuilt/*
    NO_DEFAULT_PATH
  )

  get_filename_component ( AndroidNDK_HOST
    ${AndroidNDK_HOST_PREBUILT_DIR} NAME CACHE 
  )
endmacro ()

macro ( _do_find_sysroot )

  file ( GLOB _sysroot_list RELATIVE "${ANDROID_NDK_ROOT}/"
    "${ANDROID_NDK_ROOT}/platforms/android-*/arch-${_target_arch}"
  )

  foreach ( _sysroot ${_sysroot_list} )
    string ( REGEX REPLACE ".*/android-(.*)/.*" "\\1" _sysroot_version "${_sysroot}" )
    set ( AndroidNDK_SYSROOT_${_sysroot_version}
      ${ANDROID_NDK_ROOT}/${_sysroot} CACHE PATH
      "SYSROOT ${_sysroot_version}"
    )
    mark_as_advanced ( AndroidNDK_SYSROOT_${_sysroot_version} )
  endforeach ()
endmacro ()

macro ( _do_find_gnu_toolchain )

  file ( GLOB _gnu_toolchain_list RELATIVE "${ANDROID_NDK_ROOT}/"
    "${ANDROID_NDK_ROOT}/toolchains/${_gnu_toolchain_name}-[0-9].[0-9]/prebuilt/${AndroidNDK_HOST}"
  )

  set ( AndroidNDK_GNU_TRIPLET ${_gnu_triplet} CACHE PATH "target triplet" )
  mark_as_advanced ( AndroidNDK_GNU_TRIPLET )

  foreach ( toolchain ${_gnu_toolchain_list} )
    string ( REGEX REPLACE ".*-([0-9]\.[0-9])/prebuilt/.*" "\\1"
      _toolchain_version "${toolchain}"
    )

    set ( AndroidNDK_GNU_TOOLCHAIN_${_toolchain_version} 
      ${ANDROID_NDK_ROOT}/${toolchain} CACHE PATH
      "GNU TOOLCHAIN ${_toolchain_version}"
    )
    mark_as_advanced ( AndroidNDK_GNU_TOOLCHAIN_${_toolchain_version} )

    set ( AndroidNDK_GNU_CROSSPREFIX_${_toolchain_version}
      ${AndroidNDK_GNU_TOOLCHAIN_${_toolchain_version}}/bin/${_gnu_triplet}- CACHE STRING
      "GNU CROSSPREFIX ${_toolchain_version}"
    )
    mark_as_advanced ( AndroidNDK_GNU_TOOLCHAIN_${_toolchain_version} )
  endforeach ()
endmacro ()

find_file ( AndroidNDK_NDK_BUILD ndk-build 
  PATHS ${ANDROID_NDK_ROOT} $ENV{ANDROID_NDK_ROOT}
)
mark_as_advanced ( AndroidNDK_NDK_BUILD )

if ( AndroidNDK_NDK_BUILD )
  get_filename_component ( ANDROID_NDK_ROOT ${AndroidNDK_NDK_BUILD} DIRECTORY )

  set ( ANDROID_NDK_ROOT "${ANDROID_NDK_ROOT}" CACHE STRING "Android NDK" )

  _do_find_info ()
  _do_find_sysroot ()
  _do_find_gnu_toolchain ()
endif ()

include ( FindPackageHandleStandardArgs )

find_package_handle_standard_args ( AndroidNDK
  FOUND_VAR         AndroidNDK_FOUND
  REQUIRED_VARS     ANDROID_NDK_ROOT AndroidNDK_HOST
  VERSION_VAR       AndroidNDK_VERSION_STRING
  HANDLE_COMPONENTS
)
-------------- next part --------------

set ( lang CXX )

include ( Platform/Android-GNU )

-------------- next part --------------

set ( lang C )

include ( Platform/Android-GNU )
-------------- next part --------------


if ( CMAKE_LIBRARY_ARCHITECTURE STREQUAL armeabi-v7a )
  set ( compiler_flags  "-march=armv7-a -mfpu=vfpv3-d16 -mfloat-abi=softfp" )
  set ( linker_flags    "-lm" )
elseif ( CMAKE_LIBRARY_ARCHITECTURE STREQUAL armeabi-v7a-hard )
  set ( compiler_flags  "-march=armv7-a -mfpu=vfpv3-d16 -mfloat-abi=hard -D_NDK_MATH_NO_SOFTFP=1" )
  set ( linker_flags    "-lm_hard -Wl,--no-warn-mismatch" )
else ()
  set ( compiler_flags )
  set ( linker_flags )
endif ()

set ( compiler_flags "${compiler_flags} -DANDROID" )

foreach ( build_type DEBUG MINSIZEREL RELEASE RELWITHDEBINFO )
  set ( CMAKE_${lang}_FLAGS_${build_type}_INIT  "${CMAKE_${lang}_FLAGS_${build_type}_INIT} ${compiler_flags}" )
endforeach ()

if ( linker_flags )
  set ( CMAKE_${lang}_STANDARD_LIBRARIES_INIT   "${CMAKE_${lang}_STANDARD_LIBRARIES_INIT} ${linker_flags}" )
endif ()



More information about the cmake-developers mailing list