Skip to content
Snippets Groups Projects
Commit 10909897 authored by Alexandru Croitor's avatar Alexandru Croitor
Browse files

CMake: Add qt6_add_executable Android API samples

To discuss how to overcome the issue of setting target properties and
then calling some function to act on them.
parent 88ec2496
No related branches found
No related tags found
No related merge requests found
# https://bugreports.qt.io/browse/QTBUG-88840
# Current qt6_add_executable implementation
function(qt6_add_executable target)
if(ANDROID)
add_library("${target}" MODULE ${ARGN})
else()
add_executable("${target}" ${ARGN})
endif()
target_link_libraries("${target}" PRIVATE Qt::Core)
if(ANDROID)
qt_android_generate_deployment_settings("${target}") # <--------- there's a problem here
qt_android_add_apk_target("${target}")
endif()
endfunction()
function(qt6_android_generate_deployment_settings target)
# ...
# Trying to access a property that can never bet set before the qt6_add_executable call.
get_target_property(android_package_source_dir ${target} QT_ANDROID_PACKAGE_SOURCE_DIR)
get_target_property(android_extra_libs ${target} QT_ANDROID_EXTRA_LIBS)
# ....
endfunction()
# Possible solutions
# =====================================================================================
# Approach 1: Don't call qt_android_generate_deployment_settings in
# qt6_add_executable, user needs to do it.
qt6_add_executable(foo)
set_target_properties(foo PROPERTIES QT_ANDROID_PACKAGE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/bla")
qt_android_generate_deployment_settings(foo)
qt_android_add_apk_target(foo)
# Pros: explicit, qt6_add_executable not bloated
# Cons: Easy to forget to add it.
# Android projects written by hand (not from a pre-made
# template like from Qt Creator) don't work out of the box.
#
# =====================================================================================
# Approach 2: Allow qt6_add_executable to take a huge list of options
qt6_add_executable(foo
QT_ANDROID_PACKAGE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/bla"
QT_ANDROID_EXTRA_LIBS "baz")
# Pros: No need to call a function manually at the end of the project
# Cons: Bloats qt6_add_executable API.
# =====================================================================================
# Approach 3: Use DEFER CALL when CMake >= 3.19
function(qt6_add_executable target)
add_library("${target}" MODULE ${ARGN})
if(ANDROID)
if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.19")
cmake_language(EVAL CODE "cmake_language(DEFER CALL \"qt_android_generate_deployment_settings(${target})\")")
else()
qt_android_generate_deployment_settings("${target}")
endif()
endif()
endfunction()
# Sample
qt6_add_executable(foo)
set_target_properties(foo PROPERTIES QT_ANDROID_PACKAGE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/bla")
# qt_android_generate_deployment_settings called automatically at end of scope.
# Pros: Automatically works when CMake >= 3.19
# Cons: API still broken with <= 3.18
# So-so: Can be worked around by calling qt_android_generate_deployment_settings
# a second time after setting the properties.
# =====================================================================================
# Approach 4: Use approach from Qt5, where variables have to be set before the creation
# of the target, instead of target properties.
set(QT_ANDROID_PACKAGE_SOURCE_DIR"${​​​​​​​​CMAKE_CURRENT_SOURCE_DIR}​​​​​​​​/android")
qt6_add_executable(foo)
# The qt_android_generate_deployment_settings call
# reads the variable value instead of a target property.
# Pros: Compatible with Qt5 behaviour.
# No need for target propeties or DEFER CALL or high CMake versions.
# Cons: Arguably bad API because the variable pollutes current and child scopes,
# not tied to specific target.
# Some additional variations
# =====================================================================================
# Approach 1.1: Provide a qt6_finalize_executable that users need to
# add to the end of their project. Inside we'd call Android specific functions
# like qt_android_generate_deployment_settings and qt_android_add_apk_target, and other
# possible ones for other platforms. Will be a no-op for CMake 3.19 >= due to DEFER CALL.
qt6_add_executable(foo)
set_target_properties(foo PROPERTIES QT_ANDROID_PACKAGE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/bla")
qt6_finalize_executable(foo)
function(qt6_add_executable target)
# ....
if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.19")
cmake_language(EVAL CODE "cmake_language(DEFER CALL \"qt6_finalize_executable(${target})\")")
set_target_properties(${target} PROPERTIES _qt_finalize_will_be_called 1)
endif()
endfunction()
function(qt6_finalize_executable target) # qt6_finalize_executableS (aka multiple) ?
get_target_property(will_be_called ${target} _qt_finalize_will_be_called)
if(will_be_called)
return()
endif()
qt_android_generate_deployment_settings("${target}")
qt_android_add_apk_target("${target}")
# ....
endfunction()
# Pros: With CMake <= 3.18 users need to call only 1 function at the end of the scope
# instead of multiple depending on platform.
# Automatically called with >= 3.19.
# Cons: User still needs to call function manually with CMake <= 3.18.
# Hard to say if 1 function taking one target will be enough.
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment