summaryrefslogtreecommitdiffstats
path: root/cmake
diff options
context:
space:
mode:
authorLeander Beernaert <leander.beernaert@qt.io>2019-06-06 14:29:31 +0200
committerLeander Beernaert <leander.beernaert@qt.io>2019-06-12 07:21:01 +0000
commit152b22a7b00c8365808dd58d2afb42ff86ed75ec (patch)
treeaaeaf7e272f744a7a8e24533df9dad9ab9bd224b /cmake
parent118e04013ab35fd5b6607ca239a44ab80fb064ed (diff)
Android: Generate deployment-settings.json
Generate the android deployment settings json for android apk targets. QtPlatformAndroid is now also deployed as a public build dependency of QtCore. Some minor refactoring has been performed to the naming of variables and functions to better match the public facing apis. Extra settings for the file can be configured using the following target properties: set_target_properties(Core PROPERTIES QT_ANDROID_DEPLOYMENT_DEPENDENCIES "foo;bar" QT_ANDROID_EXTRA_LIBS "foo;bar" QT_ANDROID_EXTRA_PLUGINS "foo;bar" QT_ANDROID_PACKAGE_SOURCE_DIR "/foo/bar/" ) The file is generated using the function qt_android_generate_depoyment_settings(). We need to install the android template files and jar files during the android build as the androiddeployqt tool wont work if parts of it are split between the host install and the android install. Added QT_BUILD_QT variable to check whether we are building Qt from source. Finally, we also force the stdlib to shared via cmake configuration with -DANDROID_STL="c++_shared" Change-Id: I063c47e11749d56ba4c6f02101dbcc09e1b9fe87 Reviewed-by: Qt CMake Build Bot Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Diffstat (limited to 'cmake')
-rw-r--r--cmake/QtBaseGlobalTargets.cmake9
-rw-r--r--cmake/QtBuild.cmake2
-rw-r--r--cmake/QtPlatformAndroid.cmake264
-rw-r--r--cmake/QtProperties.cmake1
-rw-r--r--cmake/QtSetup.cmake6
-rw-r--r--cmake/README.md5
6 files changed, 272 insertions, 15 deletions
diff --git a/cmake/QtBaseGlobalTargets.cmake b/cmake/QtBaseGlobalTargets.cmake
index 0b4bfa093c..f89bb405b5 100644
--- a/cmake/QtBaseGlobalTargets.cmake
+++ b/cmake/QtBaseGlobalTargets.cmake
@@ -10,7 +10,6 @@ target_include_directories(Platform
)
target_compile_definitions(Platform INTERFACE ${QT_PLATFORM_DEFINITIONS})
-
# When building on android we need to link against the logging library
# in order to satisfy linker dependencies. Both of these libraries are part of
# the NDK.
@@ -22,6 +21,14 @@ set(__GlobalConfig_path_suffix "${INSTALL_CMAKE_NAMESPACE}")
qt_path_join(__GlobalConfig_build_dir ${QT_CONFIG_BUILD_DIR} ${__GlobalConfig_path_suffix})
qt_path_join(__GlobalConfig_install_dir ${QT_CONFIG_INSTALL_DIR} ${__GlobalConfig_path_suffix})
+
+if (ANDROID)
+ qt_install(FILES
+ "${QT_CMAKE_DIR}/QtPlatformAndroid.cmake"
+ DESTINATION "${__GlobalConfig_install_dir}"
+ )
+endif()
+
# Generate and install Qt5 config file.
configure_package_config_file(
"${PROJECT_SOURCE_DIR}/cmake/QtConfig.cmake.in"
diff --git a/cmake/QtBuild.cmake b/cmake/QtBuild.cmake
index 30986c14fb..17bd41915a 100644
--- a/cmake/QtBuild.cmake
+++ b/cmake/QtBuild.cmake
@@ -1269,8 +1269,8 @@ set(QT_CMAKE_EXPORT_NAMESPACE ${QT_CMAKE_EXPORT_NAMESPACE})")
DESTINATION "${config_install_dir}"
COMPONENT Devel
)
- file(COPY ${extra_cmake_files} DESTINATION "${config_build_dir}")
+ file(COPY ${extra_cmake_files} DESTINATION "${config_build_dir}")
set(exported_targets ${target} ${target_private})
set(export_name "${INSTALL_CMAKE_NAMESPACE}${target}Targets")
qt_install(TARGETS ${exported_targets}
diff --git a/cmake/QtPlatformAndroid.cmake b/cmake/QtPlatformAndroid.cmake
index 46a8fe06a4..8d0d8b67da 100644
--- a/cmake/QtPlatformAndroid.cmake
+++ b/cmake/QtPlatformAndroid.cmake
@@ -1,9 +1,28 @@
#
-# Platform Settings for Android
+# Self contained Platform Settings for Android
+#
+# Note: This file is used both by the internal and public builds.
+#
+
+#
+# Public variables:
+# QT_ANDROID_JAR
+# Location of the adroid sdk jar for java code
+# QT_ANDROID_APIVERSION
+# Android API version
+# QT_ANDROID_SDK_BUILD_TOOLS_VERSION
+# Detected Android sdk build tools version
+# QT_ANDROID_NDK_STDLIB_PATH
+# Detected path to the c++ stl lib shared library
+#
+# Public functions:
+#
+# qt_android_generate_depolyment_settings()
+# Generate the depolyment settings json file for a cmake target.
#
if (NOT DEFINED ANDROID_SDK_ROOT)
- message(FATAL_ERROR "ANDROID_SDK_ROOT is not defined")
+ message(FATAL_ERROR "Please provide the location of the Android SDK directory via -DANDROID_SDK_ROOT=<path to Adndroid SDK>")
endif()
if (NOT IS_DIRECTORY "${ANDROID_SDK_ROOT}")
@@ -11,11 +30,11 @@ if (NOT IS_DIRECTORY "${ANDROID_SDK_ROOT}")
endif()
# Minimum recommend android SDK api version
-set(qt_android_api_version "android-21")
+set(QT_ANDROID_API_VERSION "android-21")
# Locate android.jar
-set(android_jar "${ANDROID_SDK_ROOT}/platforms/${qt_android_api_version}/android.jar")
-if(NOT EXISTS "${android_jar}")
+set(QT_ANDROID_JAR "${ANDROID_SDK_ROOT}/platforms/${QT_ANDROID_API_VERSION}/android.jar")
+if(NOT EXISTS "${QT_ANDROID_JAR}")
# Locate the highest available platform
file(GLOB android_platforms
LIST_DIRECTORIES true
@@ -26,19 +45,244 @@ if(NOT EXISTS "${android_jar}")
list(SORT android_platforms)
list(REVERSE android_platforms)
list(GET android_platforms 0 android_platform_latest)
- set(qt_android_api_version ${android_platform_latest})
- set(android_jar "${ANDROID_SDK_ROOT}/platforms/${qt_android_api_version}/android.jar")
+ set(QT_ANDROID_API_VERSION ${android_platform_latest})
+ set(QT_ANDROID_JAR "${ANDROID_SDK_ROOT}/platforms/${QT_ANDROID_API_VERSION}/android.jar")
endif()
endif()
-if(NOT EXISTS "${android_jar}")
- message(FATAL_ERROR "No suitable Android SDK platform found. Minimum version is ${qt_android_api_version}")
+if(NOT EXISTS "${QT_ANDROID_JAR}")
+ message(FATAL_ERROR "No suitable Android SDK platform found. Minimum version is ${QT_ANDROID_API_VERSION}")
endif()
-message(STATUS "Using Android SDK API ${qt_android_api_version} from ${ANDROID_SDK_ROOT}/platforms")
+message(STATUS "Using Android SDK API ${QT_ANDROID_API_VERSION} from ${ANDROID_SDK_ROOT}/platforms")
# Locate Java
include(UseJava)
# Find JDK 8.0
find_package(Java 1.8 COMPONENTS Development REQUIRED)
+
+# Locate newest android sdk build tools
+if (NOT QT_ANDROID_SDK_BUILD_TOOLS_VERSION)
+ file(GLOB android_build_tools
+ LIST_DIRECTORIES true
+ RELATIVE "${ANDROID_SDK_ROOT}/build-tools"
+ "${ANDROID_SDK_ROOT}/build-tools/*")
+ if (NOT android_build_tools)
+ message(FATAL_ERROR "Could not locate Android SDK build tools under \"${ANDROID_SDK}/build-tools\"")
+ endif()
+ list(SORT android_build_tools)
+ list(REVERSE android_build_tools)
+ list(GET android_build_tools 0 android_build_tools_latest)
+ set(qt_QT_ANDROID_SDK_BUILD_TOOLS_VERSION ${android_build_tools_latest})
+endif()
+
+# Ensure we are using the shared version of libc++
+if(NOT ANDROID_STL STREQUAL c++_shared)
+ message(FATAL_ERROR "The Qt libraries on Android only supports the shared library configuration of stl. Please use -DANDROID_STL=\"c++_shared\" as configuration argument.")
+endif()
+
+
+# Location of stdlibc++
+set(QT_ANDROID_NDK_STDLIB_PATH "${ANDROID_NDK}/sources/cxx-stl/llvm-libc++/libs/${ANDROID_ABI}/libc++_shared.so")
+
+# Target properties required for android deploy tool
+define_property(TARGET
+ PROPERTY
+ QT_ANDROID_DEPLOYMENT_DEPENDENCIES
+ BRIEF_DOCS
+ "Specify additional plugins that need to be deployed with the current android application"
+ FULL_DOCS
+ "By default, androiddeployqt will detect the dependencies of your application. But since run-time usage of plugins cannot be detected, there could be false positives, as your application will depend on any plugins that are potential dependencies. If you want to minimize the size of your APK, it's possible to override the automatic detection using the ANDROID_DEPLOYMENT_DEPENDENCIES variable. This should contain a list of all Qt files which need to be included, with paths relative to the Qt install root. Note that only the Qt files specified here will be included. Failing to include the correct files can result in crashes. It's also important to make sure the files are listed in the correct loading order. This variable provides a way to override the automatic detection entirely, so if a library is listed before its dependencies, it will fail to load on some devices."
+)
+
+define_property(TARGET
+ PROPERTY
+ QT_ANDROID_EXTRA_LIBS
+ BRIEF_DOCS
+ "A list of external libraries that will be copied into your application's library folder and loaded on start-up."
+ FULL_DOCS
+ "A list of external libraries that will be copied into your application's library folder and loaded on start-up. This can be used, for instance, to enable OpenSSL in your application. Simply set the paths to the required libssl.so and libcrypto.so libraries here and OpenSSL should be enabled automatically."
+)
+
+define_property(TARGET
+ PROPERTY
+ QT_ANDROID_EXTRA_PLUGINS
+ BRIEF_DOCS
+ "This variable can be used to specify different resources that your project has to bundle but cannot be delivered through the assets system, such as qml plugins."
+ FULL_DOCS
+ "This variable can be used to specify different resources that your project has to bundle but cannot be delivered through the assets system, such as qml plugins. When using this variable, androiddeployqt will make sure everything is packaged and deployed properly."
+)
+
+define_property(TARGET
+ PROPERTY
+ QT_ANDROID_PACKAGE_SOURCE_DIR
+ BRIEF_DOCS
+ "This variable can be used to specify a directory where additions and modifications can be made to the default Android package template."
+ FULL_DOCS
+ "This variable can be used to specify a directory where additions and modifications can be made to the default Android package template. The androiddeployqt tool will copy the application template from Qt into the build directory, and then it will copy the contents of the ANDROID_PACKAGE_SOURCE_DIR on top of this, overwriting any existing files. The update step where parts of the source files are modified automatically to reflect your other settings is then run on the resulting merged package. If you, for instance, want to make a custom AndroidManifest.xml for your application, then place this directly into the folder specified in this variable. You can also add custom Java files in ANDROID_PACKAGE_SOURCE_DIR/src."
+)
+
+define_property(TARGET
+ PROPERTY
+ QT_ANDROID_DEPLOYMENT_SETTINGS_FILE
+ BRIEF_DOCS
+ " "
+ FULL_DOCS
+ " "
+)
+
+# Generate deployment tool json
+function(qt_android_generate_depolyment_settings target)
+ # Information extracted from mkspecs/features/android/android_deployment_settings.prf
+ if (NOT TARGET ${target})
+ message(SEND_ERROR "${target} is not a cmake target")
+ return()
+ endif()
+
+ get_target_property(target_type ${target} TYPE)
+
+ if (NOT "${target_type}" STREQUAL "MODULE_LIBRARY")
+ message(SEND_ERROR "QT_ANDROID_GENERATE_DEPOLYMENT_SETTINGS only works on Module targets")
+ return()
+ endif()
+
+ get_target_property(target_source_dir ${target} SOURCE_DIR)
+ get_target_property(target_binary_dir ${target} BINARY_DIR)
+ get_target_property(target_output_name ${target} OUTPUT_NAME)
+ if (NOT target_output_name)
+ set(target_output_name ${target})
+ endif()
+ set(deploy_file "${target_binary_dir}/android-lib${target_output_name}.so-deployment-settings.json")
+
+ file(WRITE ${deploy_file} "{\n")
+ # content begin
+ file(APPEND ${deploy_file}
+ " \"description\": \"This file is generated by cmake to be read by androiddeployqt and should not be modified by hand.\",\n")
+
+ # Host Qt Android install path
+ if (NOT QT_BUILD_QT)
+ set(file_check "${Qt5_DIR}/plugins/platforms/android/libqtforandroid.so")
+ if (NOT EXISTS ${file_check})
+ message(SEND_ERROR "Detected Qt installation does not containt libqtforandroid.so. This is most likely due to the installation not being a build of Qt for Android. Please update your settings.")
+ return()
+ endif()
+ set(qt_android_install_dir ${Qt5_Dir})
+ else()
+ # Building from source, use the same install prefix
+ set(qt_android_install_dir ${CMAKE_INSTALL_PREFIX})
+ endif()
+
+ file(TO_NATIVE_PATH "${qt_android_install_dir}" qt_android_install_dir_native)
+ file(APPEND ${deploy_file}
+ " \"qt\": \"${qt_android_install_dir_native}\",\n")
+
+ # Android SDK path
+ file(TO_NATIVE_PATH "${ANDROID_SDK_ROOT}" android_sdk_root_native)
+ file(APPEND ${deploy_file}
+ " \"sdk\": \"${android_sdk_root_native}\",\n")
+
+ # Android SDK Build Tools Revision
+ file(APPEND ${deploy_file}
+ " \"sdkBuildToolsRevision\": \"${QT_ANDROID_SDK_BUILD_TOOLS_VERSION}\",\n")
+
+ # Android NDK
+ file(TO_NATIVE_PATH "${ANDROID_NDK}" android_ndk_root_native)
+ file(APPEND ${deploy_file}
+ " \"ndk\": \"${android_ndk_root_native}\",\n")
+
+ # Setup LLVM toolchain
+ file(APPEND ${deploy_file}
+ " \"toolchain-prefix\": \"llvm\",\n")
+ file(APPEND ${deploy_file}
+ " \"tool-prefix\": \"llvm\",\n")
+ file(APPEND ${deploy_file}
+ " \"useLLVM\": true,\n")
+
+ # NDK Toolchain Version
+ file(APPEND ${deploy_file}
+ " \"toolchain-version\": \"${CMAKE_ANDROID_NDK_TOOLCHAIN_VERSION}\",\n")
+
+ # NDK Host
+ file(APPEND ${deploy_file}
+ " \"ndk-host\": \"${ANDROID_NDK_HOST_SYSTEM_NAME}\",\n")
+
+ # Architecture
+ file(APPEND ${deploy_file}
+ " \"target-architecture\": \"${CMAKE_ANDROID_ARCH_ABI}\",\n")
+
+ # deployment dependencies
+ get_target_property(android_deployment_dependencies
+ ${target} QT_ANDROID_DEPLOYMENT_DEPENDENCIES)
+ if (android_deployment_dependencies)
+ list(JOIN android_deployment_dependencies "," android_deployment_dependencies)
+ file(APPEND ${deploy_file}
+ " \"deployment-dependencies\": \"${android_deployment_dependencies}\",\n")
+ endif()
+
+ # Extra plugins
+ get_target_property(android_extra_plugins
+ ${target} QT_ANDROID_EXTRA_PLUGINS)
+ if (android_extra_plugins)
+ list(JOIN android_extra_plugins "," android_extra_plugins)
+ file(APPEND ${deploy_file}
+ " \"android-extra-plugins\": \"${android_extra_plugins}\",\n")
+ endif()
+
+ # Extra libs
+ get_target_property(android_extra_libs
+ ${target} QT_ANDROID_EXTRA_LIBS)
+ if (android_extra_libs)
+ list(JOIN android_extra_libs "," android_extra_libs)
+ file(APPEND ${deploy_file}
+ " \"android-extra-libs\": \"${android_extra_libs}\",\n")
+ endif()
+
+ # package source dir
+ get_target_property(android_package_source_dir
+ ${target} QT_ANDROID_PACKAGE_SOURCE_DIR)
+ if (android_package_source_dir)
+ file(TO_NATIVE_PATH "${android_package_source_dir}" android_package_source_dir_native)
+ file(APPEND ${deploy_file}
+ " \"android-package-source-directory\": \"${android_package_source_dir_native}\",\n")
+endif()
+
+ #TODO: ANDROID_VERSION_NAME, doesn't seem to be used?
+
+ #TODO: ANDROID_VERSION_CODE, doesn't seem to be used?
+
+ #TODO: QML import path, could be a property? Example below:
+ #get_target_property(qml_import_path ${target} QT_QML_IMPORT_PATH)
+ #if (qml_import_path)
+ # file(TO_NATIVE_PATH "${qml_import_path}" qml_import_path_native)
+ # file(APPEND ${deploy_file}
+ # " \"qml-import-path\": \"${qml_import_path_native}\",\n")
+ #endif()
+
+ #TODO: QML root path, could be a property? Example below:
+ #get_target_property(qml_root_path ${target} QT_QML_ROOT_PATH)
+ #if(NOT qml_root_path)
+ # set(qml_root_path "${target_source_dir}")
+ #endif()
+ #file(TO_NATIVE_PATH "${qml_root_path}" qml_root_path_native)
+ #file(APPEND ${deploy_file}
+ # " \"qml-root-path\": \"${qml_root_path_native}\",\n")
+
+ # App binary
+ file(TO_NATIVE_PATH "${target_binary_dir}/lib${target_output_name}.so" target_binary_dir_native)
+ file(APPEND ${deploy_file}
+ " \"application-binary\": \"${target_binary_dir_native}\",\n")
+
+ # Lats item in json file
+
+ file(APPEND ${deploy_file}
+ " \"stdcpp-path\": \"${QT_ANDROID_NDK_STDLIB_PATH}\"\n")
+
+ # content end
+ file(APPEND ${deploy_file} "}\n")
+
+ set_target_properties(${target}
+ PROPERTIES
+ QT_ANDROID_DEPLOYMENT_SETTINGS_FILE ${deploy_file}
+ )
+endfunction()
diff --git a/cmake/QtProperties.cmake b/cmake/QtProperties.cmake
index b0621e7b46..e8b1fbf4f0 100644
--- a/cmake/QtProperties.cmake
+++ b/cmake/QtProperties.cmake
@@ -46,3 +46,4 @@ define_property(GLOBAL
FULL_DOCS
""
)
+
diff --git a/cmake/QtSetup.cmake b/cmake/QtSetup.cmake
index 62d4b0dece..3277a1af35 100644
--- a/cmake/QtSetup.cmake
+++ b/cmake/QtSetup.cmake
@@ -1,4 +1,10 @@
## Set a default build type if none was specified
+
+# Set the QT_IS_BUILDING_QT variable so we can verify whether we are building
+# Qt from source
+set(QT_BUILDING_QT TRUE CACHE
+ TYPE STRING "When this is present and set to true, it signals that we are building Qt from source.")
+
set(_default_build_type "Release")
if(EXISTS "${CMAKE_SOURCE_DIR}/.git")
set(_default_build_type "Debug")
diff --git a/cmake/README.md b/cmake/README.md
index 88d4b0aa31..bf878800d6 100644
--- a/cmake/README.md
+++ b/cmake/README.md
@@ -123,7 +123,7 @@ The specified path needs to point to a directory that contains an installed host
### Cross Compiling for Android
-In order to cross-compile Qt to Android, the above instructions apply. In addition, it is necessary to install the Android NDK as well as vcpkg. Vcpkg is needed to supply third-party libraries that Qt requires but that are not part of the Android NDK.
+In order to cross-compile Qt to Android, you need a host build (see instructions above) and an Android build. In addition, it is necessary to install the Android NDK as well as vcpkg. Vcpkg is needed to supply third-party libraries that Qt requires but that are not part of the Android NDK.
Vcpkg for Android can be set up using the following steps:
@@ -134,8 +134,7 @@ Vcpkg for Android can be set up using the following steps:
* Set the ``ANDROID_SDK_HOME`` environment variable to the path where you have installed the Android SDK.
* Build Qt dependencies: ``vcpkg install zlib pcre2 harfbuzz freetype openssl zstd``
-When running cmake in qtbase, pass ``-DCMAKE_TOOLCHAIN_FILE=/path/to/your/vcpkg/scripts/buildsystems/vcpkg.cmake -DVCPKG_CHAINLOAD_TOOLCHAIN_FILE=$ANDROID_NDK_HOME/build/cmake/android.toolchain.cmake -DVCPKG_TARGET_TRIPLET=$VCPKG_DEFAULT_TRIPLET -DQT_HOST_PATH=/path/to/your/host/build -DANDROID_NATIVE_API_LEVEL=21 -DANDROID_SDK_ROOT=$ANDROID_SDK_HOME``
-
+When running cmake in qtbase, pass ``-DCMAKE_TOOLCHAIN_FILE=/path/to/your/vcpkg/scripts/buildsystems/vcpkg.cmake -DVCPKG_CHAINLOAD_TOOLCHAIN_FILE=$ANDROID_NDK_HOME/build/cmake/android.toolchain.cmake -DVCPKG_TARGET_TRIPLET=$VCPKG_DEFAULT_TRIPLET -DQT_HOST_PATH=/path/to/your/host/build -DANDROID_NATIVE_API_LEVEL=21 -DANDROID_SDK_ROOT=$ANDROID_SDK_HOME -DANDROID_STL=c++_shared -DCMAKE_INSTALL_PREFIX=$INSTALL_PATH``
# Debugging CMake files