Advance Wayland and KDE package bring-up
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
@@ -0,0 +1,322 @@
|
||||
# SPDX-FileCopyrightText: 2014 Aleix Pol i Gonzalez <aleixpol@kde.org>
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
#[=======================================================================[.rst:
|
||||
AndroidToolchain
|
||||
----------------
|
||||
|
||||
Enable easy compilation of cmake projects on Android.
|
||||
|
||||
By using this android toolchain, the projects will be set up to compile the
|
||||
specified project targeting an Android platform, depending on its input.
|
||||
Furthermore, if desired, an APK can be directly generated by using the
|
||||
`androiddeployqt <https://doc.qt.io/qt-5/deployment-android.html>`_ tool.
|
||||
|
||||
CMake upstream has Android support now. This module will still give us some
|
||||
useful features offering androiddeployqt integration and adequate executables
|
||||
format for our Android applications.
|
||||
|
||||
Since we are using CMake Android support, any information from CMake documentation
|
||||
still applies:
|
||||
https://cmake.org/cmake/help/v3.7/manual/cmake-toolchains.7.html#cross-compiling-for-android
|
||||
|
||||
.. note::
|
||||
|
||||
This module requires CMake 3.18.
|
||||
|
||||
Since 1.7.0.
|
||||
|
||||
Usage
|
||||
=====
|
||||
|
||||
To use this file, you need to set the ``CMAKE_TOOLCHAIN_FILE`` to point to
|
||||
``Android.cmake`` on the command line::
|
||||
|
||||
cmake -DCMAKE_TOOLCHAIN_FILE=/usr/share/ECM/toolchain/Android.cmake
|
||||
|
||||
You will also need to provide the locations of the Android NDK and SDK. This
|
||||
can be done on the commandline or with environment variables; in either case
|
||||
the variable names are:
|
||||
|
||||
``CMAKE_ANDROID_NDK``
|
||||
The NDK root path.
|
||||
``ANDROID_SDK_ROOT``
|
||||
The SDK root path.
|
||||
|
||||
Additional options are specified as cache variables (eg: on the command line):
|
||||
|
||||
``ANDROID_ABI``
|
||||
The ABI to use. See the ``sources/cxx-stl/gnu-libstdc++/*/libs``
|
||||
directories in the NDK. Default: ``armeabi-v7a``.
|
||||
``ANDROID_SDK_COMPILE_API``
|
||||
The platform API level to compile against. May be different from the NDK
|
||||
target. Default: newest installed version (e.g. android-30).
|
||||
``ANDROID_SDK_BUILD_TOOLS_REVISION``
|
||||
The build tools version to use.
|
||||
Default: newest installed version (e.g. ``30.0.2``).
|
||||
``ANDROID_EXTRA_LIBS``
|
||||
The ";"-separated list of full paths to libs to include in resulting APK (Qt 5 only).
|
||||
|
||||
For integrating other libraries which are not part of the Android toolchain,
|
||||
like Qt5, and installed to a separate prefix on the host system, the install
|
||||
prefixes of those libraries would be passed as alternative roots as list via
|
||||
``ECM_ADDITIONAL_FIND_ROOT_PATH``. Since 5.30.0.
|
||||
|
||||
For example, for integrating a Qt5 for Android present at
|
||||
``~/Qt/5.14.2/android/`` and some other libraries installed to
|
||||
the prefix ``/opt/android/foo``, you would use::
|
||||
|
||||
cmake \
|
||||
-DCMAKE_TOOLCHAIN_FILE=/usr/share/ECM/toolchain/Android.cmake \
|
||||
-DECM_ADDITIONAL_FIND_ROOT_PATH="~/Qt/5.14.2/android/;/opt/android/foo"
|
||||
|
||||
If your project uses ``find_package()`` to locate build tools on the host
|
||||
system, make sure to pass ``CMAKE_FIND_ROOT_PATH_BOTH`` or
|
||||
``NO_CMAKE_FIND_ROOT_PATH`` as argument in the call. See the
|
||||
``find_package()`` documentation for more details.
|
||||
|
||||
Deploying Qt 5 Applications
|
||||
===========================
|
||||
|
||||
After building the application, you will need to generate an APK that can be
|
||||
deployed to an Android device. This module integrates androiddeployqt support
|
||||
to help with this for Qt-based projects. To enable this, set the
|
||||
``QTANDROID_EXPORTED_TARGET`` variable to the targets you wish to export as an
|
||||
APK (in a ;-separed list), as well as ``ANDROID_APK_DIR`` to a directory
|
||||
containing some basic information. This will create a ``create-apk-<target>``
|
||||
target that will generate the APK file. See the `Qt on Android deployment
|
||||
documentation <https://doc.qt.io/qt-5/deployment-android.html>`_ for more
|
||||
information.
|
||||
|
||||
For example, you could do::
|
||||
|
||||
cmake \
|
||||
-DCMAKE_TOOLCHAIN_FILE=/usr/share/ECM/toolchain/Android.cmake \
|
||||
-DQTANDROID_EXPORTED_TARGET=myapp \
|
||||
-DANDROID_APK_DIR=myapp-apk
|
||||
make
|
||||
make create-apk-myapp
|
||||
|
||||
You can specify the APK output directory by setting ``ANDROID_APK_OUTPUT_DIR``.
|
||||
Otherwise the APK can be found in ``myapp_build_apk/`` in the build directory.
|
||||
|
||||
The create-apk-myapp target will be able to take an ARGS parameter with further
|
||||
arguments for androiddeployqt. For example, one can use::
|
||||
|
||||
make create-apk-myapp ARGS="--install"
|
||||
|
||||
To install the apk to test. To generate a signed apk, one can do it with the
|
||||
following syntax::
|
||||
|
||||
make create-apk-myapp ARGS="--sign ~/my.keystore alias_name"
|
||||
|
||||
In case it's needed for your application to set the APK directory from cmake
|
||||
scripting you can also set the directory as the ANDROID_APK_DIR property of
|
||||
the create-apk-myapp target.
|
||||
|
||||
See Android documentation on how to create a keystore to use
|
||||
|
||||
Advanced Options
|
||||
================
|
||||
|
||||
The following packaging options are mainly interesting for automation or integration
|
||||
with CI/CD pipelines:
|
||||
|
||||
``ANDROID_APK_OUTPUT_DIR``
|
||||
Specifies a folder where the generated APK files should be placed.
|
||||
``ANDROID_FASTLANE_METADATA_OUTPUT_DIR``
|
||||
Specifies a folder where the generated metadata for the F-Droid store
|
||||
should be placed.
|
||||
``ANDROIDDEPLOYQT_EXTRA_ARGS``
|
||||
Allows to pass additional arguments to `androiddeployqt`. This is an alternative to
|
||||
the `ARGS=` argument for `make` and unlike that works with all CMake generators.
|
||||
#]=======================================================================]
|
||||
|
||||
cmake_minimum_required(VERSION "3.18")
|
||||
|
||||
macro(set_deprecated_variable actual_variable deprecated_variable default_value)
|
||||
set(${deprecated_variable} "${default_value}" CACHE STRING "Deprecated. Use ${actual_variable}")
|
||||
if (NOT DEFINED ${actual_variable})
|
||||
set(${actual_variable} ${${deprecated_variable}})
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
set_deprecated_variable(CMAKE_ANDROID_NDK ANDROID_NDK "$ENV{ANDROID_NDK}")
|
||||
set_deprecated_variable(CMAKE_ANDROID_NDK_TOOLCHAIN_VERSION ANDROID_GCC_VERSION "clang")
|
||||
set_deprecated_variable(CMAKE_ANDROID_API ANDROID_API_LEVEL "21")
|
||||
if(NOT DEFINED ENV{ANDROID_ARCH})
|
||||
set(ENV{ANDROID_ARCH} "arm")
|
||||
endif()
|
||||
set_deprecated_variable(CMAKE_ANDROID_ARCH ANDROID_ARCHITECTURE $ENV{ANDROID_ARCH})
|
||||
if(NOT DEFINED ENV{ANDROID_ARCH_ABI})
|
||||
set(ENV{ANDROID_ARCH_ABI} "armeabi-v7a")
|
||||
endif()
|
||||
set_deprecated_variable(CMAKE_ANDROID_ARCH_ABI ANDROID_ABI "$ENV{ANDROID_ARCH_ABI}")
|
||||
|
||||
set(ANDROID_SDK_ROOT "$ENV{ANDROID_SDK_ROOT}" CACHE PATH "Android SDK path")
|
||||
|
||||
file(GLOB platforms LIST_DIRECTORIES TRUE RELATIVE ${ANDROID_SDK_ROOT}/platforms ${ANDROID_SDK_ROOT}/platforms/*)
|
||||
list(SORT platforms COMPARE NATURAL)
|
||||
list(GET platforms -1 _default_platform)
|
||||
set(ANDROID_SDK_COMPILE_API "${_default_platform}" CACHE STRING "Android API Level")
|
||||
if(ANDROID_SDK_COMPILE_API MATCHES "^android-([0-9]+)$")
|
||||
set(ANDROID_SDK_COMPILE_API ${CMAKE_MATCH_1})
|
||||
endif()
|
||||
|
||||
file(GLOB build-tools LIST_DIRECTORIES TRUE RELATIVE ${ANDROID_SDK_ROOT}/build-tools ${ANDROID_SDK_ROOT}/build-tools/*)
|
||||
list(SORT build-tools COMPARE NATURAL)
|
||||
list(GET build-tools -1 _default_sdk)
|
||||
set(ANDROID_SDK_BUILD_TOOLS_REVISION "${_default_sdk}" CACHE STRING "Android Build Tools version")
|
||||
|
||||
set(CMAKE_SYSTEM_VERSION ${CMAKE_ANDROID_API})
|
||||
set(CMAKE_SYSTEM_NAME Android)
|
||||
if (NOT CMAKE_ANDROID_STL_TYPE)
|
||||
set(CMAKE_ANDROID_STL_TYPE c++_shared)
|
||||
endif()
|
||||
|
||||
# Workaround link failure at FindThreads in CXX-only mode,
|
||||
# armv7 really doesn't like mixing PIC/PIE code.
|
||||
# Since we only have to care about a single compiler,
|
||||
# hard-code the values here.
|
||||
# Qt6 fixes this and breaks in nested CMake calls (e.g. try_compile) if we
|
||||
# define Threads::Threads here, at least if the "C" language is enabled. In
|
||||
# CXX-only projects we still need to do this unconditionally...
|
||||
#
|
||||
# We cannot use our usual Qt version check at this point though yet,
|
||||
# so check whether we are chainloaded by the Qt toolchain as an indicator
|
||||
# for Qt6.
|
||||
# When building Qt6Base itself the check does not work, hence we have
|
||||
# ECM_THREADS_WORKAROUND for that case which set to OFF in the Craft blueprints.
|
||||
# As that doesn't propagate to nested CMake calls (e.g. tye_compile), we also check
|
||||
# whether that is set via an environment variable (necessary with Qt >= 6.8.1).
|
||||
if (NOT DEFINED ECM_THREADS_WORKAROUND AND NOT DEFINED ENV{ECM_THREADS_WORKAROUND})
|
||||
set(ECM_THREADS_WORKAROUND TRUE)
|
||||
endif()
|
||||
get_property(_languages GLOBAL PROPERTY ENABLED_LANGUAGES)
|
||||
if (ECM_THREADS_WORKAROUND AND NOT TARGET Threads::Threads AND (NOT DEFINED __qt_chainload_toolchain_file OR NOT "C" IN_LIST _languages))
|
||||
set(Threads_FOUND TRUE)
|
||||
set(CMAKE_THREAD_LIBS_INIT "-pthread")
|
||||
add_library(Threads::Threads INTERFACE IMPORTED)
|
||||
set_property(TARGET Threads::Threads PROPERTY INTERFACE_COMPILE_OPTIONS "-pthread")
|
||||
set_property(TARGET Threads::Threads PROPERTY INTERFACE_LINK_LIBRARIES "-pthread")
|
||||
endif()
|
||||
|
||||
# let the Android NDK toolchain file do the actual work
|
||||
set(ANDROID_PLATFORM "android-${CMAKE_ANDROID_API}")
|
||||
set(ANDROID_STL ${CMAKE_ANDROID_STL_TYPE})
|
||||
include(${CMAKE_ANDROID_NDK}/build/cmake/android.toolchain.cmake REQUIRED)
|
||||
|
||||
# Export configurable variables for the try_compile() command.
|
||||
list(APPEND CMAKE_TRY_COMPILE_PLATFORM_VARIABLES
|
||||
CMAKE_ANDROID_NDK
|
||||
CMAKE_ANDROID_NDK_TOOLCHAIN_VERSION
|
||||
CMAKE_ANDROID_API
|
||||
CMAKE_ANDROID_ARCH
|
||||
CMAKE_ANDROID_ARCH_ABI
|
||||
ANDROID_SDK_ROOT
|
||||
ANDROID_SDK_COMPILE_API
|
||||
)
|
||||
|
||||
# needed for androiddeployqt's stdcpp-path setting
|
||||
if (ANDROID_TOOLCHAIN_ROOT)
|
||||
set(ANDROID_SYSROOT_PREFIX "${ANDROID_TOOLCHAIN_ROOT}/sysroot/usr")
|
||||
else()
|
||||
set(ANDROID_SYSROOT_PREFIX "${CMAKE_NDK_ROOT}/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr")
|
||||
endif()
|
||||
|
||||
## HACK: Remove when we can depend on NDK r23
|
||||
# Workaround issue https://github.com/android/ndk/issues/929
|
||||
if(ANDROID_NDK_MAJOR VERSION_LESS 23)
|
||||
unset(CMAKE_SYSROOT)
|
||||
|
||||
list(APPEND CMAKE_SYSTEM_INCLUDE_PATH
|
||||
"${ANDROID_SYSROOT_PREFIX}/include/${CMAKE_LIBRARY_ARCHITECTURE}")
|
||||
list(APPEND CMAKE_SYSTEM_INCLUDE_PATH "${ANDROID_SYSROOT_PREFIX}/include")
|
||||
|
||||
# Prepend in reverse order
|
||||
list(PREPEND CMAKE_SYSTEM_LIBRARY_PATH
|
||||
"${ANDROID_SYSROOT_PREFIX}/lib/${CMAKE_LIBRARY_ARCHITECTURE}")
|
||||
list(PREPEND CMAKE_SYSTEM_LIBRARY_PATH
|
||||
"${ANDROID_SYSROOT_PREFIX}/lib/${CMAKE_LIBRARY_ARCHITECTURE}/${ANDROID_PLATFORM_LEVEL}")
|
||||
endif()
|
||||
|
||||
# Qt6 still expects ABI suffixes but only applies them in its own qt_add_[executable|library] macros
|
||||
# as we typically don't use those we need another way to get those
|
||||
if (DEFINED __qt_chainload_toolchain_file) # indicator for Qt6, see above
|
||||
set(CMAKE_MODULE_LIBRARY_SUFFIX_C "_${CMAKE_ANDROID_ARCH_ABI}.so")
|
||||
set(CMAKE_MODULE_LIBRARY_SUFFIX_CXX "_${CMAKE_ANDROID_ARCH_ABI}.so")
|
||||
set(CMAKE_SHARED_LIBRARY_SUFFIX_C "_${CMAKE_ANDROID_ARCH_ABI}.so")
|
||||
set(CMAKE_SHARED_LIBRARY_SUFFIX_CXX "_${CMAKE_ANDROID_ARCH_ABI}.so")
|
||||
endif()
|
||||
|
||||
# these aren't set yet at this point by the Android toolchain, but without
|
||||
# those the find_package() call in ECMAndroidDeployQt5 will fail
|
||||
set(CMAKE_FIND_LIBRARY_PREFIXES "lib")
|
||||
set(CMAKE_FIND_LIBRARY_SUFFIXES "_${CMAKE_ANDROID_ARCH_ABI}.so" ".so" ".a")
|
||||
|
||||
# Work around Qt messing with CMAKE_SHARED_LIBRARY_SUFFIX and thus breaking find_library()
|
||||
# Unfortunately, just setting CMAKE_FIND_LIBRARY_SUFFIXES here won't help, as this will
|
||||
# be subsequently overwritten.
|
||||
macro(addAbiSuffix _var _access)
|
||||
if (${_access} STREQUAL "MODIFIED_ACCESS")
|
||||
list(PREPEND CMAKE_FIND_LIBRARY_SUFFIXES "_${CMAKE_ANDROID_ARCH_ABI}.so")
|
||||
endif()
|
||||
endmacro()
|
||||
variable_watch(CMAKE_FIND_LIBRARY_SUFFIXES addAbiSuffix)
|
||||
|
||||
# determine STL architecture, which is using a different format than ANDROID_ARCH_ABI
|
||||
string(REGEX REPLACE "-(clang)?([0-9].[0-9])?$" "" ECM_ANDROID_STL_ARCH "${ANDROID_TOOLCHAIN_NAME}")
|
||||
|
||||
if (NOT DEFINED ECM_ADDITIONAL_FIND_ROOT_PATH)
|
||||
SET(ECM_ADDITIONAL_FIND_ROOT_PATH ${CMAKE_PREFIX_PATH})
|
||||
endif()
|
||||
|
||||
LIST(APPEND CMAKE_FIND_ROOT_PATH ${ECM_ADDITIONAL_FIND_ROOT_PATH})
|
||||
|
||||
#we want executables to be shared libraries, hooks will invoke the exported cmake function
|
||||
set(CMAKE_CXX_LINK_EXECUTABLE
|
||||
"<CMAKE_CXX_COMPILER> <CMAKE_SHARED_LIBRARY_CXX_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS> <SONAME_FLAG><TARGET_SONAME> -o <TARGET> <OBJECTS> <LINK_LIBRARIES>"
|
||||
)
|
||||
|
||||
# As our executables are shared libraries, we also need them build with position independent code (PIC).
|
||||
# Qt 5 forces that anyway, but in Qt 6 that is no longer the case for exectuables (which we pretend to build here),
|
||||
# and so we end up with just PIE (coming from CMake).
|
||||
# And as subsequent steps overwrite that setting again, we have to watch for that and redo our change.
|
||||
set(CMAKE_CXX_COMPILE_OPTIONS_PIE "-fPIC")
|
||||
macro(resetPieOption _var _access)
|
||||
if (${_access} STREQUAL "MODIFIED_ACCESS")
|
||||
set(CMAKE_CXX_COMPILE_OPTIONS_PIE "-fPIC")
|
||||
endif()
|
||||
endmacro()
|
||||
variable_watch(CMAKE_CXX_COMPILE_OPTIONS_PIE resetPieOption)
|
||||
|
||||
set(ECM_DIR "${CMAKE_CURRENT_LIST_DIR}/../cmake" CACHE STRING "")
|
||||
|
||||
######### generation (Qt 5 only)
|
||||
|
||||
# Need to ensure we only get in here once, as this file is included twice:
|
||||
# from CMakeDetermineSystem.cmake and from CMakeSystem.cmake generated within the
|
||||
# build directory.
|
||||
if(DEFINED QTANDROID_EXPORTED_TARGET AND NOT TARGET "create-apk" AND NOT __qt_chainload_toolchain_file)
|
||||
get_filename_component(_CMAKE_ANDROID_DIR "${CMAKE_TOOLCHAIN_FILE}" PATH)
|
||||
list(LENGTH QTANDROID_EXPORTED_TARGET targetsCount)
|
||||
include(${_CMAKE_ANDROID_DIR}/ECMAndroidDeployQt5.cmake)
|
||||
|
||||
math(EXPR last "${targetsCount}-1")
|
||||
foreach(idx RANGE 0 ${last})
|
||||
list(GET QTANDROID_EXPORTED_TARGET ${idx} exportedTarget)
|
||||
list(GET ANDROID_APK_DIR ${idx} APK_DIR)
|
||||
if(APK_DIR AND NOT EXISTS "${ANDROID_APK_DIR}/AndroidManifest.xml" AND IS_ABSOLUTE ANDROID_APK_DIR)
|
||||
message(FATAL_ERROR "Cannot find ${APK_DIR}/AndroidManifest.xml according to ANDROID_APK_DIR. ${ANDROID_APK_DIR} ${exportedTarget}")
|
||||
elseif(NOT APK_DIR)
|
||||
get_filename_component(_qt5Core_install_prefix "${Qt5Core_DIR}/../../../" ABSOLUTE)
|
||||
set(APK_DIR "${_qt5Core_install_prefix}/src/android/templates/")
|
||||
endif()
|
||||
|
||||
ecm_androiddeployqt5("${exportedTarget}" "${ECM_ADDITIONAL_FIND_ROOT_PATH}")
|
||||
set_target_properties(create-apk-${exportedTarget} PROPERTIES ANDROID_APK_DIR "${APK_DIR}")
|
||||
endforeach()
|
||||
elseif (NOT __qt_chainload_toolchain_file)
|
||||
message(STATUS "You can export a target by specifying -DQTANDROID_EXPORTED_TARGET=<targetname> and -DANDROID_APK_DIR=<paths>")
|
||||
endif()
|
||||
Reference in New Issue
Block a user