summaryrefslogtreecommitdiffstats
path: root/src/corelib/Qt6AndroidMacros.cmake
blob: 7b566a763366ee0057c0089fe958b845376d29e8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
# Generate deployment tool json
function(qt6_android_generate_deployment_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_DEPLOYMENT_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")

    set(file_contents "{\n")
    # content begin
    string(APPEND file_contents
        "   \"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_BUILDING_QT OR QT_STANDALONE_TEST_PATH)
        set(qt_path "${QT6_INSTALL_PREFIX}")
        set(android_plugin_dir_path "${qt_path}/${QT6_INSTALL_PLUGINS}/platforms")
        set(glob_expression "${android_plugin_dir_path}/*qtforandroid*${CMAKE_ANDROID_ARCH_ABI}.so")
        file(GLOB plugin_dir_files LIST_DIRECTORIES FALSE "${glob_expression}")
        if (NOT plugin_dir_files)
            message(SEND_ERROR
                "Detected Qt installation does not contain qtforandroid_${CMAKE_ANDROID_ARCH_ABI}.so in the following dir:
${android_plugin_dir_path}
This is most likely due to the installation not being a Qt for Android build.
Please recheck your build configuration.")
            return()
        else()
            list(GET plugin_dir_files 0 android_platform_plugin_path)
            message(STATUS "Found android platform plugin at: ${android_platform_plugin_path}")
        endif()
        set(qt_android_install_dir "${qt_path}")
    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)
    string(APPEND file_contents
        "   \"qt\": \"${qt_android_install_dir_native}\",\n")

    # Android SDK path
    file(TO_NATIVE_PATH "${ANDROID_SDK_ROOT}" android_sdk_root_native)
    string(APPEND file_contents
        "   \"sdk\": \"${android_sdk_root_native}\",\n")

    # Android SDK Build Tools Revision
    string(APPEND file_contents
        "   \"sdkBuildToolsRevision\": \"${QT_ANDROID_SDK_BUILD_TOOLS_VERSION}\",\n")

    # Android NDK
    file(TO_NATIVE_PATH "${ANDROID_NDK}" android_ndk_root_native)
    string(APPEND file_contents
        "   \"ndk\": \"${android_ndk_root_native}\",\n")

    # Setup LLVM toolchain
    string(APPEND file_contents
        "   \"toolchain-prefix\": \"llvm\",\n")
    string(APPEND file_contents
        "   \"tool-prefix\": \"llvm\",\n")
    string(APPEND file_contents
        "   \"useLLVM\": true,\n")

    # NDK Toolchain Version
    string(APPEND file_contents
        "   \"toolchain-version\": \"${CMAKE_ANDROID_NDK_TOOLCHAIN_VERSION}\",\n")

    # NDK Host
    string(APPEND file_contents
        "   \"ndk-host\": \"${ANDROID_NDK_HOST_SYSTEM_NAME}\",\n")

    if (CMAKE_ANDROID_ARCH_ABI STREQUAL "x86")
        set(arch_value "i686-linux-android")
    elseif (CMAKE_ANDROID_ARCH_ABI STREQUAL "x86_64")
        set(arch_value "x86_64-linux-android")
    elseif (CMAKE_ANDROID_ARCH_ABI STREQUAL "arm64-v8a")
        set(arch_value "aarch64-linux-android")
    else()
        set(arch_value "arm-linux-androideabi")
    endif()

    # Architecture
    string(APPEND file_contents
        "   \"architectures\": { \"${CMAKE_ANDROID_ARCH_ABI}\" : \"${arch_value}\" },\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)
        string(APPEND file_contents
            "   \"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)
        string(APPEND file_contents
            "   \"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)
        string(APPEND file_contents
            "   \"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)
        string(APPEND file_contents
            "   \"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?

    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)
        string(APPEND file_contents
            "   \"qml-import-path\": \"${qml_import_path_native}\",\n")
    endif()

    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)
    string(APPEND file_contents
        "   \"qml-root-path\": \"${qml_root_path_native}\",\n")

    # App binary
    string(APPEND file_contents
        "   \"application-binary\": \"${target_output_name}\",\n")

    # Override qmlimportscanner binary path
    set(qml_importscanner_binary_path "${QT_HOST_PATH}/bin/qmlimportscanner")
    if (WIN32)
        string(APPEND qml_importscanner_binary_path ".exe")
    endif()
    file(TO_NATIVE_PATH "${qml_importscanner_binary_path}" qml_importscanner_binary_path_native)
    string(APPEND file_contents
        "   \"qml-importscanner-binary\" : \"${qml_importscanner_binary_path_native}\",\n")

    # Override rcc binary path
    set(rcc_binary_path "${QT_HOST_PATH}/bin/rcc")
    if (WIN32)
        string(APPEND rcc_binary_path ".exe")
    endif()
    file(TO_NATIVE_PATH "${rcc_binary_path}" rcc_binary_path_native)
    string(APPEND file_contents
        "   \"rcc-binary\" : \"${rcc_binary_path_native}\",\n")

    # Last item in json file

    # base location of stdlibc++, will be suffixed by androiddeploy qt
    # Sysroot is set by Android toolchain file and is composed of ANDROID_TOOLCHAIN_ROOT.
    set(android_ndk_stdlib_base_path "${CMAKE_SYSROOT}/usr/lib/")
    string(APPEND file_contents
        "   \"stdcpp-path\": \"${android_ndk_stdlib_base_path}\"\n")

    # content end
    string(APPEND file_contents "}\n")

    file(WRITE ${deploy_file} ${file_contents})

    set_target_properties(${target}
        PROPERTIES
            QT_ANDROID_DEPLOYMENT_SETTINGS_FILE ${deploy_file}
    )
endfunction()

if(NOT QT_NO_CREATE_VERSIONLESS_FUNCTIONS)
    function(qt_android_generate_deployment_settings)
        qt6_android_generate_deployment_settings(${ARGV})
    endfunction()
endif()

function(qt6_android_apply_arch_suffix target)
    get_target_property(target_type ${target} TYPE)
    if (target_type STREQUAL "SHARED_LIBRARY" OR target_type STREQUAL "MODULE_LIBRARY")
        set_property(TARGET "${target}" PROPERTY SUFFIX "_${CMAKE_ANDROID_ARCH_ABI}.so")
    elseif (target_type STREQUAL "STATIC_LIBRARY")
        set_property(TARGET "${target}" PROPERTY SUFFIX "_${CMAKE_ANDROID_ARCH_ABI}.a")
    endif()
endfunction()

if(NOT QT_NO_CREATE_VERSIONLESS_FUNCTIONS)
    function(qt_android_apply_arch_suffix)
        qt6_android_apply_arch_suffix(${ARGV})
    endfunction()
endif()

# Add custom target to package the APK
function(qt6_android_add_apk_target target)
    get_target_property(deployment_file ${target} QT_ANDROID_DEPLOYMENT_SETTINGS_FILE)
    if (NOT deployment_file)
        message(FATAL_ERROR "Target ${target} is not a valid android executable target\n")
    endif()

    # Create a top-level "apk" target for convenience, so that users can call 'ninja apk'.
    # It will trigger building all the target specific apk build targets that are added via this
    # function.
    # Allow opt-out.
    if(NOT QT_NO_GLOBAL_APK_TARGET)
        if(NOT TARGET apk)
            add_custom_target(apk
                DEPENDS ${target}_prepare_apk_dir
                COMMENT "Building all apks"
            )
        endif()
        set(should_add_to_global_apk TRUE)
    endif()

    set(deployment_tool "${QT_HOST_PATH}/bin/androiddeployqt")
    set(apk_dir "$<TARGET_PROPERTY:${target},BINARY_DIR>/android-build")
    add_custom_target(${target}_prepare_apk_dir
        DEPENDS ${target}
        COMMAND ${CMAKE_COMMAND}
            -E copy $<TARGET_FILE:${target}>
            "${apk_dir}/libs/${CMAKE_ANDROID_ARCH_ABI}/$<TARGET_FILE_NAME:${target}>"
        COMMENT "Copying ${target} binarty to apk folder"
    )

    add_custom_target(${target}_make_apk
        DEPENDS ${target}_prepare_apk_dir
        COMMAND  ${deployment_tool}
            --input ${deployment_file}
            --output ${apk_dir}
        COMMENT "Creating APK for ${target}"
    )

    if(should_add_to_global_apk)
        add_dependencies(apk "${target}_make_apk")
    endif()
endfunction()

if(NOT QT_NO_CREATE_VERSIONLESS_FUNCTIONS)
    function(qt_android_add_apk_target)
        qt6_android_add_apk_target(${ARGV})
    endfunction()
endif()