diff --git a/AddQtAndroidApk.cmake b/AddQtAndroidApk.cmake index 22a7f24..f084304 100644 --- a/AddQtAndroidApk.cmake +++ b/AddQtAndroidApk.cmake @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.0) -cmake_policy(SET CMP0026 OLD) # allow use of the LOCATION target property +# cmake_policy(SET CMP0026 OLD) # allow use of the LOCATION target property # store the current source directory for future use set(QT_ANDROID_SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}) @@ -68,11 +68,7 @@ macro(add_qt_android_apk TARGET SOURCE_TARGET) cmake_parse_arguments(ARG "INSTALL" "NAME;VERSION_NAME;VERSION_CODE;PACKAGE_NAME;PACKAGE_SOURCES;KEYSTORE_PASSWORD;EXTRA_QML" "DEPENDS;KEYSTORE;ANDROID_MANIFEST_IN_PATH;VERBOSE" ${ARGN}) # extract the full path of the source target binary - if(CMAKE_BUILD_TYPE STREQUAL "Debug") - get_property(QT_ANDROID_APP_PATH TARGET ${SOURCE_TARGET} PROPERTY DEBUG_LOCATION) - else() - get_property(QT_ANDROID_APP_PATH TARGET ${SOURCE_TARGET} PROPERTY LOCATION) - endif() + set(QT_ANDROID_APP_PATH "$") # full file path to the app's main shared library # define the application name if(ARG_NAME) @@ -151,12 +147,30 @@ macro(add_qt_android_apk TARGET SOURCE_TARGET) configure_file(${QT_ANDROID_MANIFEST_IN_REAL_PATH} ${QT_ANDROID_APP_PACKAGE_SOURCE_ROOT}/AndroidManifest.xml @ONLY) endif() - if(ANDROID_STL) + # newer NDK toolchains don't define ANDROID_STL_PREFIX anymore, + # so this is a fallback to the only supported value in recent versions + if(NOT ANDROID_STL_PREFIX) + if(ANDROID_STL MATCHES "^c\\+\\+_") + set(ANDROID_STL_PREFIX llvm-libc++) + endif() + endif() + + if(NOT ANDROID_STL_PREFIX) + message("Failed to determine ANDROID_STL_PREFIX value for ANDROID_STL=${ANDROID_STL}.") + endif() + + # define the STL shared library path + # up until NDK r18, ANDROID_STL_SHARED_LIBRARIES is populated by the NDK's toolchain file + # since NDK r19, the only option for a shared STL library is libc++_shared + if(ANDROID_STL_SHARED_LIBRARIES) + list(GET ANDROID_STL_SHARED_LIBRARIES 0 STL_LIBRARY_NAME) # we can only give one to androiddeployqt if(ANDROID_STL_PATH) set(QT_ANDROID_STL_PATH "${ANDROID_STL_PATH}/libs/${ANDROID_ABI}/lib${ANDROID_STL}.so") else() set(QT_ANDROID_STL_PATH "${ANDROID_NDK}/sources/cxx-stl/${ANDROID_STL_PREFIX}/libs/${ANDROID_ABI}/lib${ANDROID_STL}.so") endif() + elseif(ANDROID_STL STREQUAL c++_shared) + set(QT_ANDROID_STL_PATH "${ANDROID_NDK}/sources/cxx-stl/${ANDROID_STL_PREFIX}/libs/${ANDROID_ABI}/libc++_shared.so") else() set(QT_ANDROID_STL_PATH) IF(ANDROID_STL_STATIC_LIBRARIES) @@ -170,39 +184,59 @@ macro(add_qt_android_apk TARGET SOURCE_TARGET) if(ARG_DEPENDS) foreach(LIB ${ARG_DEPENDS}) if(TARGET ${LIB}) - # item is a CMake target, extract the library path - if(CMAKE_BUILD_TYPE STREQUAL "Debug") - get_property(LIB_PATH TARGET ${LIB} PROPERTY DEBUG_LOCATION) - else() - get_property(LIB_PATH TARGET ${LIB} PROPERTY LOCATION) - endif() - set(LIB ${LIB_PATH}) + set(LIB "$") + endif() + + if(EXTRA_LIBS) + set(EXTRA_LIBS "${EXTRA_LIBS},${LIB}") + else() + set(EXTRA_LIBS "${LIB}") endif() - if(EXTRA_LIBS) - set(EXTRA_LIBS "${EXTRA_LIBS},${LIB}") - else() - set(EXTRA_LIBS "${LIB}") - endif() endforeach() set(QT_ANDROID_APP_EXTRA_LIBS "\"android-extra-libs\": \"${EXTRA_LIBS}\",") endif() - + + # determine whether to use the gcc- or llvm/clang-toolchain + # if ANDROID_USE_LLVM was explicitly set, use it its value directly + # otherwise, ANDROID_TOOLCHAIN value (set by the NDK's toolchain file) says whether llvm/clang or gcc is used + if(DEFINED ANDROID_USE_LLVM) + string(TOLOWER "${ANDROID_USE_LLVM}" QT_ANDROID_USE_LLVM) + elseif(ANDROID_TOOLCHAIN STREQUAL clang) + set(QT_ANDROID_USE_LLVM "true") + else() + set(QT_ANDROID_USE_LLVM "false") + endif() + # set some toolchain variables used by androiddeployqt; # unfortunately, Qt tries to build paths from these variables although these full paths - # are already available in the toochain file, so we have to parse them - string(REGEX MATCH "${ANDROID_NDK}/toolchains/(.*)-(.*)/prebuilt/.*" ANDROID_TOOLCHAIN_PARSED ${ANDROID_TOOLCHAIN_ROOT}) - if(ANDROID_TOOLCHAIN_PARSED) - set(QT_ANDROID_TOOLCHAIN_PREFIX ${CMAKE_MATCH_1}) - set(QT_ANDROID_TOOLCHAIN_VERSION ${CMAKE_MATCH_2}) + # are already available in the toochain file, so we have to parse them if using gcc + if(QT_ANDROID_USE_LLVM STREQUAL "true") + set(QT_ANDROID_TOOLCHAIN_PREFIX "llvm") + set(QT_ANDROID_TOOLCHAIN_VERSION) + set(QT_ANDROID_TOOL_PREFIX "llvm") else() - message(FATAL_ERROR "Failed to parse ANDROID_TOOLCHAIN_ROOT to get toolchain prefix and version") + string(REGEX MATCH "${ANDROID_NDK}/toolchains/(.*)-(.*)/prebuilt/.*/bin/(.*)-" ANDROID_TOOLCHAIN_PARSED ${ANDROID_TOOLCHAIN_PREFIX}) + if(ANDROID_TOOLCHAIN_PARSED) + set(QT_ANDROID_TOOLCHAIN_PREFIX ${CMAKE_MATCH_1}) + set(QT_ANDROID_TOOLCHAIN_VERSION ${CMAKE_MATCH_2}) + set(QT_ANDROID_TOOL_PREFIX ${CMAKE_MATCH_3}) + else() + message(FATAL_ERROR "Failed to parse ANDROID_TOOLCHAIN_PREFIX to get toolchain prefix and version and tool prefix") + endif() endif() # make sure that the output directory for the Android package exists file(MAKE_DIRECTORY ${QT_ANDROID_APP_BINARY_DIR}/libs/${ANDROID_ABI}) # create the configuration file that will feed androiddeployqt - configure_file(${QT_ANDROID_SOURCE_DIR}/qtdeploy.json.in ${CMAKE_CURRENT_BINARY_DIR}/qtdeploy.json @ONLY) + # 1. replace placeholder variables at generation time + configure_file(${QT_ANDROID_SOURCE_DIR}/qtdeploy.json.in ${CMAKE_CURRENT_BINARY_DIR}/qtdeploy.json.in @ONLY) + # 2. evaluate generator expressions at build time + file(GENERATE + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/qtdeploy.json + INPUT ${CMAKE_CURRENT_BINARY_DIR}/qtdeploy.json.in + ) + # 3. Configure build.gradle to properly work with Android Studio import SET(QT_ANDROID_NATIVE_API_LEVEL ${ANDROID_NATIVE_API_LEVEL}) configure_file(${QT_ANDROID_SOURCE_DIR}/build.gradle.in ${QT_ANDROID_APP_BINARY_DIR}/build.gradle @ONLY) diff --git a/qtdeploy.json.in b/qtdeploy.json.in index 8b5569e..8375e8b 100644 --- a/qtdeploy.json.in +++ b/qtdeploy.json.in @@ -5,7 +5,7 @@ "ndk": "@QT_ANDROID_NDK_ROOT@", "sdkBuildToolsRevision": "@QT_ANDROID_SDK_BUILDTOOLS_REVISION@", "toolchain-prefix": "@QT_ANDROID_TOOLCHAIN_PREFIX@", - "tool-prefix": "@QT_ANDROID_TOOLCHAIN_PREFIX@", + "tool-prefix": "@QT_ANDROID_TOOL_PREFIX@", "toolchain-version": "@QT_ANDROID_TOOLCHAIN_VERSION@", "ndk-host": "@ANDROID_NDK_HOST_SYSTEM_NAME@", "target-architecture": "@ANDROID_ABI@", @@ -14,6 +14,7 @@ "android-app-name": "@QT_ANDROID_APP_NAME@", "qml-root-path": "@QT_ANDROID_QML_IMPORT_PATH@", "stdcpp-path": "@QT_ANDROID_STL_PATH@", + "useLLVM": @QT_ANDROID_USE_LLVM@, @QT_ANDROID_APP_EXTRA_LIBS@ "android-package-source-directory": "@QT_ANDROID_APP_PACKAGE_SOURCE_ROOT@" }