diff options
26 files changed, 608 insertions, 97 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 74c45ace..61fcd03c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,7 +11,7 @@ cmake_minimum_required(VERSION 3.5 FATAL_ERROR) # Preliminary setup # -set(VERSION "5.75.0") # handled by release scripts +set(VERSION "5.78.0") # handled by release scripts if (POLICY CMP0048) cmake_policy(SET CMP0048 NEW) diff --git a/docs/find-module/FindGradle.rst b/docs/find-module/FindGradle.rst new file mode 100644 index 00000000..74e69411 --- /dev/null +++ b/docs/find-module/FindGradle.rst @@ -0,0 +1 @@ +.. ecm-module:: ../../find-modules/FindGradle.cmake diff --git a/docs/sphinx/ext/ecm.py b/docs/sphinx/ext/ecm.py index 2bab34a7..8667b367 100644 --- a/docs/sphinx/ext/ecm.py +++ b/docs/sphinx/ext/ecm.py @@ -76,7 +76,7 @@ class ECMModule(Directive): settings.record_dependencies.add(path) f = io.FileInput(source_path=path, encoding=encoding, error_handler=e_handler) - except UnicodeEncodeError as error: + except UnicodeEncodeError: raise self.severe('Problems with "%s" directive path:\n' 'Cannot encode input file path "%s" ' '(wrong locale?).' % diff --git a/find-modules/FindGradle.cmake b/find-modules/FindGradle.cmake new file mode 100644 index 00000000..414ea661 --- /dev/null +++ b/find-modules/FindGradle.cmake @@ -0,0 +1,90 @@ +#.rst: +# FindGradle +# ---------- +# +# Provides the ability to build Android AAR libraries using Gradle. +# +# This relies on the Qt provided Gradle, so a Qt for Android installation +# is required. +# +# gradle_add_aar(<target> +# BUIDLFILE build.gradle +# NAME <aar-name>) +# +# This builds an Android AAR library using the given ``build.gradle`` file. +# +# gradle_install_aar(<target> +# DESTINATION <dest>) +# +# Installs a Android AAR library that has been created with ``gradle_add_aar``. +# +# Since 5.76.0. + +#============================================================================= +# SPDX-FileCopyrightText: 2019 Volker Krause <vkrause@kde.org> +# +# SPDX-License-Identifier: BSD-3-Clause +#============================================================================= + +include(CMakeParseArguments) +include(FindPackageHandleStandardArgs) + +find_package(Qt5Core REQUIRED) + +if (NOT WIN32) + set(Gradle_EXECUTABLE ${CMAKE_BINARY_DIR}/gradle/gradlew) +else() + set(Gradle_EXECUTABLE ${CMAKE_BINARY_DIR}/gradle/gradlew.bat) +endif() + +get_target_property(_qt_core_location Qt5::Core LOCATION) +get_filename_component(_qt_install_root ${_qt_core_location} DIRECTORY) +get_filename_component(_qt_install_root ${_qt_install_root}/../ ABSOLUTE) + +set(_gradle_template_dir ${CMAKE_CURRENT_LIST_DIR}) + +add_custom_command(OUTPUT ${Gradle_EXECUTABLE} + COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR}/gradle + COMMAND ${CMAKE_COMMAND} -E copy_directory ${_qt_install_root}/src/3rdparty/gradle ${CMAKE_BINARY_DIR}/gradle +) +add_custom_target(gradle DEPENDS ${Gradle_EXECUTABLE}) + +find_package_handle_standard_args(Gradle DEFAULT_MSG Gradle_EXECUTABLE) + +function(gradle_add_aar target) + cmake_parse_arguments(ARG "" "BUILDFILE;NAME" "" ${ARGN}) + + set(_build_root ${CMAKE_CURRENT_BINARY_DIR}/gradle_build/${ARG_NAME}) + configure_file(${_gradle_template_dir}/local.properties.cmake ${_build_root}/local.properties) + configure_file(${_gradle_template_dir}/settings.gradle.cmake ${_build_root}/settings.gradle) + configure_file(${ARG_BUILDFILE} ${_build_root}/build.gradle) + + if (CMAKE_BUILD_TYPE MATCHES "[Dd][Ee][Bb][Uu][Gg]") + set(_aar_suffix "-debug") + set(_aar_gradleCmd "assembleDebug") + else() + set(_aar_suffix "-release") + set(_aar_gradleCmd "assembleRelease") + endif() + + file(GLOB_RECURSE _src_files CONFIGURE_DEPENDS "*") + add_custom_command( + OUTPUT ${_build_root}/build/outputs/aar/${ARG_NAME}${_aar_suffix}.aar + COMMAND ${Gradle_EXECUTABLE} ${_aar_gradleCmd} + # this allows make create-apk to work without installations for apps with AAR libs in the same repository + COMMAND ${CMAKE_COMMAND} -E copy ${_build_root}/build/outputs/aar/${ARG_NAME}${_aar_suffix}.aar ${CMAKE_BINARY_DIR}/jar/${ARG_NAME}.aar + DEPENDS ${Gradle_EXECUTABLE} ${_src_files} + DEPENDS gradle + WORKING_DIRECTORY ${_build_root} + ) + add_custom_target(${target} ALL DEPENDS ${_build_root}/build/outputs/aar/${ARG_NAME}${_aar_suffix}.aar) + set_target_properties(${target} PROPERTIES LOCATION ${_build_root}/build/outputs/aar/${ARG_NAME}${_aar_suffix}.aar) + set_target_properties(${target} PROPERTIES OUTPUT_NAME ${ARG_NAME}) +endfunction() + +function(gradle_install_aar target) + cmake_parse_arguments(ARG "" "DESTINATION" "" ${ARGN}) + get_target_property(_loc ${target} LOCATION) + get_target_property(_name ${target} OUTPUT_NAME) + install(FILES ${_loc} DESTINATION ${ARG_DESTINATION} RENAME ${_name}.aar) +endfunction() diff --git a/find-modules/FindQtWaylandScanner.cmake b/find-modules/FindQtWaylandScanner.cmake index 65da5d2e..efbbe87a 100644 --- a/find-modules/FindQtWaylandScanner.cmake +++ b/find-modules/FindQtWaylandScanner.cmake @@ -117,8 +117,6 @@ function(ecm_add_qtwayland_client_protocol out_var) BASENAME ${ARGS_BASENAME}) get_filename_component(_infile ${ARGS_PROTOCOL} ABSOLUTE) - set(_ccode "${CMAKE_CURRENT_BINARY_DIR}/wayland-${ARGS_BASENAME}-client-protocol.c") - set(_cheader "${CMAKE_CURRENT_BINARY_DIR}/wayland-${ARGS_BASENAME}-client-protocol.h") set(_header "${CMAKE_CURRENT_BINARY_DIR}/qwayland-${ARGS_BASENAME}.h") set(_code "${CMAKE_CURRENT_BINARY_DIR}/qwayland-${ARGS_BASENAME}.cpp") @@ -132,7 +130,7 @@ function(ecm_add_qtwayland_client_protocol out_var) COMMAND ${QtWaylandScanner_EXECUTABLE} client-code ${_infile} "" ${_prefix} > ${_code} DEPENDS ${_infile} ${_header} VERBATIM) - set_property(SOURCE ${_header} ${_code} ${_cheader} ${_ccode} PROPERTY SKIP_AUTOMOC ON) + set_property(SOURCE ${_header} ${_code} PROPERTY SKIP_AUTOMOC ON) list(APPEND ${out_var} "${_code}") set(${out_var} ${${out_var}} PARENT_SCOPE) diff --git a/find-modules/FindReuseTool.cmake b/find-modules/FindReuseTool.cmake index 9377f49e..adceeeb9 100644 --- a/find-modules/FindReuseTool.cmake +++ b/find-modules/FindReuseTool.cmake @@ -3,8 +3,8 @@ # Finds the REUSE Tool by FSFE: https://github.com/fsfe/reuse-tool # -# REUSE_TOOL_FOUND - True if REUSE tool is found. -# REUSE_TOOL_EXECUTABLE - Path to executable +# REUSETOOL_FOUND - True if REUSE tool is found. +# REUSETOOL_EXECUTABLE - Path to executable #============================================================================= # SPDX-FileCopyrightText: 2020 Andreas Cord-Landwehr <cordlandwehr@kde.org> @@ -19,5 +19,5 @@ find_package_handle_standard_args(ReuseTool FOUND_VAR REUSETOOL_FOUND REQUIRED_VARS - REUSE_TOOL_EXECUTABLE + REUSETOOL_EXECUTABLE ) diff --git a/find-modules/FindWaylandScanner.cmake b/find-modules/FindWaylandScanner.cmake index 61b4875e..08b0650b 100644 --- a/find-modules/FindWaylandScanner.cmake +++ b/find-modules/FindWaylandScanner.cmake @@ -134,7 +134,8 @@ function(ecm_add_wayland_server_protocol out_var) get_filename_component(_infile ${ARGS_PROTOCOL} ABSOLUTE) set(_server_header "${CMAKE_CURRENT_BINARY_DIR}/wayland-${ARGS_BASENAME}-server-protocol.h") - set_property(SOURCE ${_server_header} PROPERTY SKIP_AUTOMOC ON) + set(_server_code "${CMAKE_CURRENT_BINARY_DIR}/wayland-${ARGS_BASENAME}-protocol.c") + set_property(SOURCE ${_server_header} ${_server_code} PROPERTY SKIP_AUTOMOC ON) set_source_files_properties(${_server_header} GENERATED) add_custom_command(OUTPUT "${_server_header}" diff --git a/find-modules/local.properties.cmake b/find-modules/local.properties.cmake new file mode 100644 index 00000000..4f14cc3f --- /dev/null +++ b/find-modules/local.properties.cmake @@ -0,0 +1 @@ +sdk.dir=@ANDROID_SDK_ROOT@ diff --git a/find-modules/rules_engine.py b/find-modules/rules_engine.py index 60611eeb..b9e9dedd 100755 --- a/find-modules/rules_engine.py +++ b/find-modules/rules_engine.py @@ -18,7 +18,6 @@ import os import re import sys import textwrap -import traceback from copy import deepcopy from clang.cindex import CursorKind @@ -51,7 +50,7 @@ class Rule(object): # Derive a useful name for diagnostic purposes. # caller = os.path.basename(inspect.stack()[3][1]) - self.name = "{}:{}[{}],{}".format(caller, type(db).__name__, rule_number, fn.__name__) + self.name = "{}:{}[{}],{}".format(caller, type(db).__name__, rule_number, fn.__name__) self.rule_number = rule_number self.fn = fn self.usage = 0 diff --git a/find-modules/run-sip.py b/find-modules/run-sip.py index fc8a5e2b..e745a607 100755 --- a/find-modules/run-sip.py +++ b/find-modules/run-sip.py @@ -1,6 +1,7 @@ #!/usr/bin/env python -import os, sys +import os +import sys import fnmatch import subprocess diff --git a/find-modules/settings.gradle.cmake b/find-modules/settings.gradle.cmake new file mode 100644 index 00000000..6628d9e7 --- /dev/null +++ b/find-modules/settings.gradle.cmake @@ -0,0 +1 @@ +rootProject.name = '@ARG_NAME@' diff --git a/find-modules/sip_generator.py b/find-modules/sip_generator.py index 2dd2ef11..b8418649 100644 --- a/find-modules/sip_generator.py +++ b/find-modules/sip_generator.py @@ -12,12 +12,10 @@ import argparse import gettext import inspect import logging -import os -import re import sys import traceback from clang import cindex -from clang.cindex import AccessSpecifier, AvailabilityKind, CursorKind, SourceRange, StorageClass, TokenKind, TypeKind, TranslationUnit +from clang.cindex import AccessSpecifier, AvailabilityKind, CursorKind, SourceRange, TokenKind, TypeKind, TranslationUnit import rules_engine @@ -784,7 +782,7 @@ def main(argv=None): body, includes = g.create_sip(args.source, args.include_filename) with open(args.output, "w") as outputFile: outputFile.write(body) - except Exception as e: + except Exception: tbk = traceback.format_exc() print(tbk) return -1 diff --git a/kde-modules/KDECMakeSettings.cmake b/kde-modules/KDECMakeSettings.cmake index 0690a2ed..03d10d16 100644 --- a/kde-modules/KDECMakeSettings.cmake +++ b/kde-modules/KDECMakeSettings.cmake @@ -254,6 +254,13 @@ if(NOT KDE_SKIP_BUILD_SETTINGS) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin") endif() + # For Android we need to put shared libraries into "lib" for androiddeployqt to work without prior installation. + # That fact that this conflicts with the above isn't really an issue, as we can't run things while cross-compiling + # for Android anyway. + if (ANDROID) + set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib") + endif() + if (APPLE) # Disable detection of X11 and related package on OS X because when using # brew or macports, X11 can be installed and thus is detected. @@ -300,7 +307,7 @@ function(_repository_name reponame dir) WORKING_DIRECTORY "${dir}") if(exitCode EQUAL 0) - string(REGEX MATCHALL ".+[:\\/]([-A-Za-z0-9]+)(.git)?\\s*" "" ${giturl}) + string(REGEX MATCHALL ".+kde\\.org[:\\/]([-A-Za-z0-9\\/]+)(.git)?\\s*" "" ${giturl}) set(${reponame} ${CMAKE_MATCH_1}) endif() @@ -325,7 +332,7 @@ if(NOT EXISTS ${CMAKE_SOURCE_DIR}/po AND NOT TARGET fetch-translations) _repository_name(_reponame "${CMAKE_SOURCE_DIR}") set(releaseme_clone_commands - COMMAND git clone --depth 1 https://anongit.kde.org/releaseme.git + COMMAND git clone --depth 1 https://invent.kde.org/sdk/releaseme.git ) add_custom_command( OUTPUT "${CMAKE_BINARY_DIR}/releaseme" diff --git a/kde-modules/KDEInstallDirs.cmake b/kde-modules/KDEInstallDirs.cmake index d739cf19..bba3a9c8 100644 --- a/kde-modules/KDEInstallDirs.cmake +++ b/kde-modules/KDEInstallDirs.cmake @@ -7,6 +7,10 @@ # Note that none of the variables defined by this module provide any # information about the location of already-installed KDE software. # +# Also sets ``CMAKE_INSTALL_PREFIX`` to the installation prefix of ECM, +# unless that variable has been already explicitly set by something else +# (since 5.61 and with CMake >= 3.7). +# # Inclusion of this module defines the following variables: # # ``KDE_INSTALL_<dir>`` @@ -573,8 +577,12 @@ _define_relative(KNOTIFY5RCDIR DATAROOTDIR "knotifications5" _define_relative(KXMLGUI5DIR DATAROOTDIR "kxmlgui5" "kxmlgui .rc files" KXMLGUI_INSTALL_DIR) -_define_relative(KTEMPLATESDIR DATAROOTDIR "kdevappwizard/templates" - "Kapptemplate and Kdevelop templates") +_define_relative(KAPPTEMPLATESDIR DATAROOTDIR "kdevappwizard/templates" + "KAppTemplate and KDevelop templates" + KDE_INSTALL_KTEMPLATESDIR + ) +_define_relative(KFILETEMPLATESDIR DATAROOTDIR "kdevfiletemplates/templates" + "KDevelop file templates") _define_relative(LOGGINGCATEGORIESDIR DATAROOTDIR "qlogging-categories5" "Qt Logging categories files") _define_relative(JARDIR "" "jar" diff --git a/kde-modules/KDEPackageAppTemplates.cmake b/kde-modules/KDEPackageAppTemplates.cmake index 7d2ddb3c..9403d63b 100644 --- a/kde-modules/KDEPackageAppTemplates.cmake +++ b/kde-modules/KDEPackageAppTemplates.cmake @@ -101,41 +101,39 @@ function(kde_package_app_templates) endif() foreach(_templateName ${ARG_TEMPLATES}) - get_filename_component(_tmp_file ${_templateName} ABSOLUTE) get_filename_component(_baseName ${_tmp_file} NAME_WE) set(_template ${CMAKE_CURRENT_BINARY_DIR}/${_baseName}.tar.bz2) - file(GLOB _files "${CMAKE_CURRENT_SOURCE_DIR}/${_templateName}/*") - set(_deps) - foreach(_file ${_files}) - get_filename_component(_fileName ${_file} NAME) - string(COMPARE NOTEQUAL ${_fileName} .kdev_ignore _v1) - string(REGEX MATCH "\\.svn" _v2 ${_fileName}) - if(WIN32) - string(REGEX MATCH "_svn" _v3 ${_fileName}) - else(WIN32) - set(_v3 FALSE) - endif() - if (_v1 AND NOT _v2 AND NOT _v3) - set(_deps ${_deps} ${_file}) - endif () - endforeach() - + # CONFIGURE_DEPENDS is only available for cmake >= 3.12 + if(NOT CMAKE_VERSION VERSION_LESS "3.12.0") + # also enlist directories as deps to catch file removals + file(GLOB_RECURSE _subdirs_entries LIST_DIRECTORIES true CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/${_templateName}/*") + else() + file(GLOB_RECURSE _subdirs_entries LIST_DIRECTORIES true "${CMAKE_CURRENT_SOURCE_DIR}/${_templateName}/*") + # custom code to implement CONFIGURE_DEPENDS + foreach(_direntry ${_subdirs_entries}) + if(IS_DIRECTORY ${_direntry}) + set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${_direntry}) + endif() + endforeach() + endif() add_custom_target(${_baseName} ALL DEPENDS ${_template}) if(GNU_TAR_FOUND) # Make tar archive reproducible, the arguments are only available with GNU tar add_custom_command(OUTPUT ${_template} - COMMAND ${_tar_executable} ARGS -c ${CMAKE_CURRENT_SOURCE_DIR}/${_templateName} - --exclude .kdev_ignore --exclude .svn --sort=name --mode=go=rX,u+rw,a-s --owner=root - --group=root --numeric-owner -j -v -f ${_template} . - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/${_templateName} + COMMAND ${_tar_executable} ARGS -c ${CMAKE_CURRENT_SOURCE_DIR}/${_templateName} + --exclude .kdev_ignore --exclude .svn --sort=name --mode=go=rX,u+rw,a-s --owner=root + --group=root --numeric-owner -j -v -f ${_template} . + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/${_templateName} + DEPENDS ${_subdirs_entries} ) else() add_custom_command(OUTPUT ${_template} COMMAND ${CMAKE_COMMAND} -E tar "cvfj" ${_template} . WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/${_templateName} + DEPENDS ${_subdirs_entries} ) endif() diff --git a/kde-modules/clang-format.cmake b/kde-modules/clang-format.cmake index 9e7bbc71..c3e43485 100644 --- a/kde-modules/clang-format.cmake +++ b/kde-modules/clang-format.cmake @@ -32,9 +32,6 @@ PointerAlignment: Right # horizontally aligns arguments after an open bracket. AlignAfterOpenBracket: Align -# align trailing comments -AlignTrailingComments: true - # don't move all parameters to new line AllowAllParametersOfDeclarationOnNextLine: false @@ -56,6 +53,9 @@ BreakBeforeBinaryOperators: None # format C++11 braced lists like function calls Cpp11BracedListStyle: true +# do not put a space before C++11 braced lists +SpaceBeforeCpp11BracedList: false + # remove empty lines KeepEmptyLinesAtTheStartOfBlocks: false @@ -67,3 +67,6 @@ SpaceAfterTemplateKeyword: false # macros for which the opening brace stays attached. ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH, forever, Q_FOREVER, QBENCHMARK, QBENCHMARK_ONCE ] + +# keep lambda formatting multi-line if not empty +AllowShortLambdasOnASingleLine: Empty diff --git a/modules/ECMAddTests.cmake b/modules/ECMAddTests.cmake index 4bc7fb8b..7e518212 100644 --- a/modules/ECMAddTests.cmake +++ b/modules/ECMAddTests.cmake @@ -94,13 +94,14 @@ function(ecm_add_test) target_link_libraries(${_targetname} ${ARG_LINK_LIBRARIES}) ecm_mark_as_test(${_targetname}) if (CMAKE_LIBRARY_OUTPUT_DIRECTORY) - if(CMAKE_HOST_SYSTEM MATCHES "Windows") - set(PATHSEP ";") + if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows") + # https://stackoverflow.com/questions/59862894/how-do-i-make-a-list-in-cmake-with-the-semicolon-value + set(PATHSEP "\\\;") # Don't want cmake to treat it like a list else() # e.g. Linux set(PATHSEP ":") endif() - set(_plugin_path $ENV{QT_PLUGIN_PATH}) - set_property(TEST ${_testname} PROPERTY ENVIRONMENT QT_PLUGIN_PATH=${CMAKE_LIBRARY_OUTPUT_DIRECTORY}${PATHSEP}${_plugin_path}) + set(_plugin_path "$ENV{QT_PLUGIN_PATH}") + set_property(TEST ${_testname} PROPERTY ENVIRONMENT "QT_PLUGIN_PATH=${CMAKE_LIBRARY_OUTPUT_DIRECTORY}${PATHSEP}${_plugin_path}") endif() if (ARG_TARGET_NAME_VAR) set(${ARG_TARGET_NAME_VAR} "${_targetname}" PARENT_SCOPE) diff --git a/modules/ECMGenerateDBusServiceFile.cmake b/modules/ECMGenerateDBusServiceFile.cmake index eabc1b42..12c37c7b 100644 --- a/modules/ECMGenerateDBusServiceFile.cmake +++ b/modules/ECMGenerateDBusServiceFile.cmake @@ -12,7 +12,7 @@ # EXECUTABLE <executable> # [SYSTEMD_SERVICE <systemd service>] # DESTINATION <install_path> -# [RENAME <dbus service filename>] +# [RENAME <dbus service filename>] # Since 5.75 # ) # # A D-Bus service file ``<service name>.service`` will be generated and installed diff --git a/modules/check-outbound-license.py b/modules/check-outbound-license.py index b8c1ef23..2657e628 100755 --- a/modules/check-outbound-license.py +++ b/modules/check-outbound-license.py @@ -125,15 +125,15 @@ if __name__ == '__main__': spdxDictionary[fileName] = licenses fileName = "" licenses = [] - f.close(); + f.close() # read file with list of test files f = open(args.input, "r") testfiles = f.readlines() f.close() - if check_outbound_license(args.license, testfiles, spdxDictionary) == True: - sys.exit(0); + if check_outbound_license(args.license, testfiles, spdxDictionary) is True: + sys.exit(0) # in any other case, return error code sys.exit(1) diff --git a/tests/GenerateSipBindings/rules_SipTest.py b/tests/GenerateSipBindings/rules_SipTest.py index c570a039..a75a5826 100644 --- a/tests/GenerateSipBindings/rules_SipTest.py +++ b/tests/GenerateSipBindings/rules_SipTest.py @@ -1,5 +1,6 @@ -import os, sys +import os +import sys import rules_engine sys.path.append(os.path.dirname(os.path.dirname(rules_engine.__file__))) diff --git a/tests/KDEFetchTranslations/CMakeLists.txt b/tests/KDEFetchTranslations/CMakeLists.txt index e68c7966..8b07c30d 100644 --- a/tests/KDEFetchTranslations/CMakeLists.txt +++ b/tests/KDEFetchTranslations/CMakeLists.txt @@ -18,8 +18,8 @@ foreach(module ${all_kde_modules}) endforeach() _repository_name(name "${CMAKE_CURRENT_SOURCE_DIR}/../../") -if (NOT ${name} STREQUAL "extra-cmake-modules") - message(FATAL_ERROR "Wrong repository name: ${name}, should be 'extra-cmake-modules'") +if (NOT ${name} STREQUAL "frameworks/extra-cmake-modules") + message(FATAL_ERROR "Wrong repository name: ${name}, should be 'frameworks/extra-cmake-modules'") endif() add_executable(dummy ../ExecuteKDEModules/main.c) ecm_mark_nongui_executable(dummy) diff --git a/toolchain/Android.cmake b/toolchain/Android.cmake index 80720711..182fa0ac 100644 --- a/toolchain/Android.cmake +++ b/toolchain/Android.cmake @@ -19,7 +19,7 @@ # # .. note:: # -# This module requires CMake 3.7. +# This module requires CMake 3.18. # # Since 1.7.0. # @@ -118,7 +118,7 @@ # # SPDX-License-Identifier: BSD-3-Clause -cmake_minimum_required(VERSION "3.7") +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}") diff --git a/toolchain/ECMAndroidDeployQt.cmake b/toolchain/ECMAndroidDeployQt.cmake index b04b5dd7..65b68c67 100644 --- a/toolchain/ECMAndroidDeployQt.cmake +++ b/toolchain/ECMAndroidDeployQt.cmake @@ -1,5 +1,36 @@ -cmake_minimum_required (VERSION 3.7 FATAL_ERROR) +cmake_minimum_required (VERSION 3.19 FATAL_ERROR) find_package(Qt5Core REQUIRED) +find_package(Python3 COMPONENTS Interpreter REQUIRED) + +# Taken from https://stackoverflow.com/a/62311397 +function(_ecm_get_all_targets var) + set(targets) + _ecm_get_all_targets_recursive(targets ${CMAKE_CURRENT_SOURCE_DIR}) + set(${var} ${targets} PARENT_SCOPE) +endfunction() + +macro(_ecm_get_all_targets_recursive targets dir) + get_property(subdirectories DIRECTORY ${dir} PROPERTY SUBDIRECTORIES) + foreach(subdir ${subdirectories}) + _ecm_get_all_targets_recursive(${targets} ${subdir}) + endforeach() + + get_property(current_targets DIRECTORY ${dir} PROPERTY BUILDSYSTEM_TARGETS) + list(APPEND ${targets} ${current_targets}) +endmacro() + +function(_ecm_deferred_androiddeployqt) + _ecm_get_all_targets(all_targets) + set(module_targets) + foreach(tgt ${all_targets}) + get_target_property(tgt_type ${tgt} TYPE) + if(tgt_type STREQUAL "MODULE_LIBRARY") + list(APPEND module_targets "$<TARGET_FILE:${tgt}>") + endif() + endforeach() + file(GENERATE OUTPUT "module-plugins" CONTENT "${module_targets}") +endfunction() +cmake_language(DEFER DIRECTORY "${CMAKE_SOURCE_DIR}" CALL _ecm_deferred_androiddeployqt) function(ecm_androiddeployqt QTANDROID_EXPORTED_TARGET ECM_ADDITIONAL_FIND_ROOT_PATH) set(EXPORT_DIR "${CMAKE_BINARY_DIR}/${QTANDROID_EXPORTED_TARGET}_build_apk/") @@ -9,6 +40,10 @@ function(ecm_androiddeployqt QTANDROID_EXPORTED_TARGET ECM_ADDITIONAL_FIND_ROOT_ set(EXECUTABLE_DESTINATION_PATH "${EXPORT_DIR}/libs/${CMAKE_ANDROID_ARCH_ABI}/lib${QTANDROID_EXPORTED_TARGET}_${CMAKE_ANDROID_ARCH_ABI}.so") endif() set(QML_IMPORT_PATHS "") + # add build directory to the search path as well, so this works without installation + if (EXISTS ${CMAKE_BINARY_DIR}/lib) + set(QML_IMPORT_PATHS ${CMAKE_BINARY_DIR}/lib) + endif() foreach(prefix ${ECM_ADDITIONAL_FIND_ROOT_PATH}) # qmlimportscanner chokes on symlinks, so we need to resolve those first get_filename_component(qml_path "${prefix}/lib/qml" REALPATH) @@ -24,13 +59,9 @@ function(ecm_androiddeployqt QTANDROID_EXPORTED_TARGET ECM_ADDITIONAL_FIND_ROOT_ set(DEFINE_QML_IMPORT_PATHS "\"qml-import-paths\": \"${QML_IMPORT_PATHS}\",") endif() - set(EXTRA_PREFIX_DIRS "") + set(EXTRA_PREFIX_DIRS "\"${CMAKE_BINARY_DIR}\"") foreach(prefix ${ECM_ADDITIONAL_FIND_ROOT_PATH}) - if (EXTRA_PREFIX_DIRS) - set(EXTRA_PREFIX_DIRS "${EXTRA_PREFIX_DIRS}, \"${prefix}\"") - else() - set(EXTRA_PREFIX_DIRS "\"${prefix}\"") - endif() + set(EXTRA_PREFIX_DIRS "${EXTRA_PREFIX_DIRS}, \"${prefix}\"") endforeach() if (Qt5Core_VERSION VERSION_LESS 5.14.0) @@ -64,6 +95,12 @@ function(ecm_androiddeployqt QTANDROID_EXPORTED_TARGET ECM_ADDITIONAL_FIND_ROOT_ if (NOT TARGET create-apk) add_custom_target(create-apk) + if (NOT DEFINED ANDROID_FASTLANE_METADATA_OUTPUT_DIR) + set(ANDROID_FASTLANE_METADATA_OUTPUT_DIR ${CMAKE_BINARY_DIR}/fastlane) + endif() + add_custom_target(create-fastlane + COMMAND Python3::Interpreter ${CMAKE_CURRENT_LIST_DIR}/generate-fastlane-metadata.py --output ${ANDROID_FASTLANE_METADATA_OUTPUT_DIR} --source ${CMAKE_SOURCE_DIR} + ) endif() if (NOT DEFINED ANDROID_APK_OUTPUT_DIR) @@ -77,7 +114,7 @@ function(ecm_androiddeployqt QTANDROID_EXPORTED_TARGET ECM_ADDITIONAL_FIND_ROOT_ COMMAND cmake -E copy_directory "$<TARGET_PROPERTY:create-apk-${QTANDROID_EXPORTED_TARGET},ANDROID_APK_DIR>" "${EXPORT_DIR}" COMMAND cmake -E copy "$<TARGET_FILE:${QTANDROID_EXPORTED_TARGET}>" "${EXECUTABLE_DESTINATION_PATH}" COMMAND LANG=C cmake "-DTARGET=$<TARGET_FILE:${QTANDROID_EXPORTED_TARGET}>" -P ${_CMAKE_ANDROID_DIR}/hasMainSymbol.cmake - COMMAND LANG=C cmake -DINPUT_FILE="${QTANDROID_EXPORTED_TARGET}-deployment.json.in2" -DOUTPUT_FILE="${QTANDROID_EXPORTED_TARGET}-deployment.json" "-DTARGET=$<TARGET_FILE:${QTANDROID_EXPORTED_TARGET}>" "-DOUTPUT_DIR=$<TARGET_FILE_DIR:${QTANDROID_EXPORTED_TARGET}>" "-DEXPORT_DIR=${CMAKE_INSTALL_PREFIX}" "-DECM_ADDITIONAL_FIND_ROOT_PATH=\"${ECM_ADDITIONAL_FIND_ROOT_PATH}\"" "-DANDROID_EXTRA_LIBS=\"${ANDROID_EXTRA_LIBS}\"" -P ${_CMAKE_ANDROID_DIR}/specifydependencies.cmake + COMMAND LANG=C cmake -DINPUT_FILE="${QTANDROID_EXPORTED_TARGET}-deployment.json.in2" -DOUTPUT_FILE="${QTANDROID_EXPORTED_TARGET}-deployment.json" "-DTARGET=$<TARGET_FILE:${QTANDROID_EXPORTED_TARGET}>" "-DOUTPUT_DIR=$<TARGET_FILE_DIR:${QTANDROID_EXPORTED_TARGET}>" "-DEXPORT_DIR=${CMAKE_INSTALL_PREFIX}" "-DECM_ADDITIONAL_FIND_ROOT_PATH=\"${ECM_ADDITIONAL_FIND_ROOT_PATH}\"" "-DANDROID_EXTRA_LIBS=\"${ANDROID_EXTRA_LIBS}\"" "-DUSE_LLVM=\"${USE_LLVM}\"" -P ${_CMAKE_ANDROID_DIR}/specifydependencies.cmake COMMAND $<TARGET_FILE_DIR:Qt5::qmake>/androiddeployqt --gradle --input "${QTANDROID_EXPORTED_TARGET}-deployment.json" --apk "${ANDROID_APK_OUTPUT_DIR}/${QTANDROID_EXPORTED_TARGET}-${CMAKE_ANDROID_ARCH_ABI}.apk" --output "${EXPORT_DIR}" --android-platform android-${ANDROID_SDK_COMPILE_API} --deployment bundled ${arguments} ) # --android-platform above is only available as a command line option @@ -88,4 +125,5 @@ function(ecm_androiddeployqt QTANDROID_EXPORTED_TARGET ECM_ADDITIONAL_FIND_ROOT_ COMMAND adb install -r "${ANDROID_APK_OUTPUT_DIR}/${QTANDROID_EXPORTED_TARGET}-${CMAKE_ANDROID_ARCH_ABI}.apk" ) add_dependencies(create-apk ${CREATEAPK_TARGET_NAME}) + add_dependencies(${CREATEAPK_TARGET_NAME} create-fastlane) endfunction() diff --git a/toolchain/deployment-file.json.in b/toolchain/deployment-file.json.in index 206e069d..c870b5f4 100644 --- a/toolchain/deployment-file.json.in +++ b/toolchain/deployment-file.json.in @@ -17,5 +17,6 @@ "sdkBuildToolsRevision": "@ANDROID_SDK_BUILD_TOOLS_REVISION@", "android-min-sdk-version": "@ANDROID_API_LEVEL@", "android-target-sdk-version": "@ANDROID_SDK_COMPILE_API@", - "extraPrefixDirs": [ @EXTRA_PREFIX_DIRS@ ] + "extraPrefixDirs": [ @EXTRA_PREFIX_DIRS@ ], + "useLLVM": ##USE_LLVM## } diff --git a/toolchain/generate-fastlane-metadata.py b/toolchain/generate-fastlane-metadata.py new file mode 100755 index 00000000..30d16927 --- /dev/null +++ b/toolchain/generate-fastlane-metadata.py @@ -0,0 +1,343 @@ +#!/usr/bin/env python3 +# +# SPDX-FileCopyrightText: 2018-2020 Aleix Pol Gonzalez <aleixpol@kde.org> +# SPDX-FileCopyrightText: 2019-2020 Ben Cooksley <bcooksley@kde.org> +# SPDX-FileCopyrightText: 2020 Volker Krause <vkrause@kde.org> +# +# SPDX-License-Identifier: GPL-2.0-or-later +# +# Generates fastlane metadata for Android apps from appstream files. +# + +import argparse +import glob +import io +import os +import re +import requests +import shutil +import subprocess +import sys +import tempfile +import xdg.DesktopEntry +import xml.etree.ElementTree as ET +import yaml +import zipfile + +# Constants used in this script +languageMap = { + None: "en-US", + "ca": "ca-ES" +} + +# see https://f-droid.org/en/docs/All_About_Descriptions_Graphics_and_Screenshots/ +supportedRichTextTags = { 'li', 'ul', 'ol', 'li', 'b', 'u', 'i' } + +# Android appdata.xml textual item parser +# This function handles reading standard text entries within an Android appdata.xml file +# In particular, it handles splitting out the various translations, and converts some HTML to something which F-Droid can make use of +def readText(elem, found): + # Determine the language this entry is in + lang = elem.get('{http://www.w3.org/XML/1998/namespace}lang') + if lang == 'x-test': + return + + # Do we have any text for this language yet? + # If not, get everything setup + if not lang in found: + found[lang] = "" + + # If there is text available, we'll want to extract it + # Additionally, if this element has any children, make sure we read those as well + # It isn't clear if it is possible for an item to not have text, but to have children which do have text + # The code will currently skip these if they're encountered + if elem.text: + if elem.tag in supportedRichTextTags: + found[lang] += '<' + elem.tag + '>' + found[lang] += elem.text + for child in elem: + readText(child, found) + if elem.tag in supportedRichTextTags: + found[lang] += '</' + elem.tag + '>' + + # Finally, if this element is a HTML Paragraph (p) or HTML List Item (li) make sure we add a new line for presentation purposes + if elem.tag == 'li' or elem.tag == 'p': + found[lang] += "\n" + + +# Create the various Fastlane format files per the information we've previously extracted +# These files are laid out following the Fastlane specification (links below) +# https://github.com/fastlane/fastlane/blob/2.28.7/supply/README.md#images-and-screenshots +# https://docs.fastlane.tools/actions/supply/ +def createFastlaneFile( applicationName, filenameToPopulate, fileContent ): + # Go through each language and content pair we've been given + for lang, text in fileContent.items(): + # First, do we need to amend the language id, to turn the Android language ID into something more F-Droid/Fastlane friendly? + languageCode = languageMap.get(lang, lang) + + # Next we need to determine the path to the directory we're going to be writing the data into + repositoryBasePath = arguments.output + path = os.path.join( repositoryBasePath, 'metadata', applicationName, languageCode ) + + # Make sure the directory exists + os.makedirs(path, exist_ok=True) + + # Now write out file contents! + with open(path + '/' + filenameToPopulate, 'w') as f: + f.write(text) + +# Create the summary appname.yml file used by F-Droid to summarise this particular entry in the repository +# see https://f-droid.org/en/docs/Build_Metadata_Reference/ +def createYml(appname, data): + # Prepare to retrieve the existing information + info = {} + + # Determine the path to the appname.yml file + repositoryBasePath = arguments.output + path = os.path.join( repositoryBasePath, 'metadata', appname + '.yml' ) + + # Update the categories first + # Now is also a good time to add 'KDE' to the list of categories as well + if 'categories' in data: + info['Categories'] = data['categories'][None] + ['KDE'] + else: + info['Categories'] = ['KDE'] + + # Update the general sumamry as well + info['Summary'] = data['summary'][None] + + # Check to see if we have a Homepage... + if 'url-homepage' in data: + info['WebSite'] = data['url-homepage'][None] + + # What about a bug tracker? + if 'url-bugtracker' in data: + info['IssueTracker'] = data['url-bugtracker'][None] + + if 'project_license' in data: + info["License"] = data['project_license'][None] + + if 'source-repo' in data: + info['SourceCode'] = data['source-repo'] + + # static data + info['Donate'] = 'https://kde.org/community/donations/' + info['Translation'] = 'https://l10n.kde.org/' + + # Finally, with our updates completed, we can save the updated appname.yml file back to disk + with open(path, 'w') as output: + yaml.dump(info, output, default_flow_style=False) + +# Download screenshots referenced in the appstream data +# see https://f-droid.org/en/docs/All_About_Descriptions_Graphics_and_Screenshots/ +def downloadScreenshots(applicationName, data): + if not 'screenshots' in data: + return + + basePath = arguments.output + path = os.path.join(basePath, 'metadata', applicationName, 'en-US', 'images', 'phoneScreenshots') + shutil.rmtree(path, ignore_errors=True) + os.makedirs(path, exist_ok=True) + + i = 0 + for screenshot in data['screenshots']: + fileName = str(i) + '-' + screenshot[screenshot.rindex('/') + 1:] + r = requests.get(screenshot) + if r.status_code < 400: + with open(os.path.join(path, fileName), 'wb') as f: + f.write(r.content) + i += 1 + +# Put all metadata for the given application name into an archive +# We need this to easily transfer the entire metadata to the signing machine for integration +# into the F-Droid nightly repository +def createMetadataArchive(applicationName): + srcPath = os.path.join(arguments.output, 'metadata') + zipFileName = os.path.join(srcPath, 'fastlane-' + applicationName + '.zip') + if os.path.exists(zipFileName): + os.unlink(zipFileName) + archive = zipfile.ZipFile(zipFileName, 'w') + archive.write(os.path.join(srcPath, applicationName + '.yml'), applicationName + '.yml') + + oldcwd = os.getcwd() + os.chdir(srcPath) + for file in glob.iglob(applicationName + '/**', recursive=True): + archive.write(file, file) + os.chdir(oldcwd) + +# Main function for extracting metadata from APK files +def processApkFile(apkFilepath): + # First, determine the name of the application we have here + # This is needed in order to locate the metadata files within the APK that have the information we need + + # Prepare the aapt (Android SDK command) to inspect the provided APK + commandToRun = "aapt dump badging %s" % (apkFilepath) + manifest = subprocess.check_output( commandToRun, shell=True ).decode('utf-8') + # Search through the aapt output for the name of the application + result = re.search(' name=\'([^\']*)\'', manifest) + applicationName = result.group(1) + + # Attempt to look within the APK provided for the metadata information we will need + with zipfile.ZipFile(apkFilepath, 'r') as contents: + appdataFile = contents.open("assets/share/metainfo/%s.appdata.xml" % applicationName) + desktopFileContent = None + try: + desktopFileContent = contents.read("assets/share/applications/%s.desktop" % applicationName) + except: + None + processAppstreamData(applicationName, appdataFile.read(), desktopFileContent) + +# Extract meta data from appstream/desktop file contents +def processAppstreamData(applicationName, appstreamData, desktopData): + data = {} + # Within this file we look at every entry, and where possible try to export it's content so we can use it later + root = ET.fromstring(appstreamData) + for child in root: + # Make sure we start with a blank slate for this entry + output = {} + + # Grab the name of this particular attribute we're looking at + # Within the Fastlane specification, it is possible to have several items with the same name but as different types + # We therefore include this within our extracted name for the attribute to differentiate them + tag = child.tag + if 'type' in child.attrib: + tag += '-' + child.attrib['type'] + + # Have we found some information already for this particular attribute? + if tag in data: + output = data[tag] + + # Are we dealing with category information here? + # If so, then we need to look into this items children to find out all the categories this APK belongs in + if tag == 'categories': + cats = [] + for x in child: + cats.append(x.text) + output = { None: cats } + + # screenshot links + elif tag == 'screenshots': + output = [] + for screenshot in child: + if screenshot.tag == 'screenshot': + for image in screenshot: + if image.tag == 'image': + output.append(image.text) + + # Otherwise this is just textual information we need to extract + else: + readText(child, output) + + # Save the information we've gathered! + data[tag] = output + + # Did we find any categories? + # Sometimes we don't find any within the Fastlane information, but without categories the F-Droid store isn't of much use + # In the event this happens, fallback to the *.desktop file for the application to see if it can provide any insight. + if not 'categories' in data and desktopData: + # The Python XDG extension/wrapper requires that it be able to read the file itself + # To ensure it is able to do this, we transfer the content of the file from the APK out to a temporary file to keep it happy + (fd, path) = tempfile.mkstemp(suffix=applicationName + ".desktop") + handle = open(fd, "wb") + handle.write(desktopData) + handle.close() + # Parse the XDG format *.desktop file, and extract the categories within it + desktopFile = xdg.DesktopEntry.DesktopEntry(path) + data['categories'] = { None: desktopFile.getCategories() } + + # Try to figure out the source repository + if arguments.source and os.path.exists(os.path.join(arguments.source, '.git')): + output = subprocess.check_output('git remote show -n origin', shell=True, cwd = arguments.source).decode('utf-8') + result = re.search(' Fetch URL: (.*)\n', output) + data['source-repo'] = result.group(1) + + # write meta data + createFastlaneFile( applicationName, "title.txt", data['name'] ) + createFastlaneFile( applicationName, "short_description.txt", data['summary'] ) + createFastlaneFile( applicationName, "full_description.txt", data['description'] ) + createYml(applicationName, data) + downloadScreenshots(applicationName, data) + createMetadataArchive(applicationName) + +# Generate metadata for the given appstream and desktop files +def processAppstreamFile(appstreamFileName, desktopFileName): + appstreamFile = open(appstreamFileName, "rb") + desktopData = None + if desktopFileName and os.path.exists(desktopFileName): + desktopFile = open(desktopFileName, "rb") + desktopData = desktopFile.read() + applicationName = os.path.basename(appstreamFileName)[:-12] + processAppstreamData(applicationName, appstreamFile.read(), desktopData) + +# scan source directory for manifests/metadata we can work with +def scanSourceDir(): + files = glob.iglob(arguments.source + "/**/AndroidManifest.xml*", recursive=True) + for file in files: + # third-party libraries might contain AndroidManifests which we are not interested in + if "3rdparty" in file: + continue + + # find application id from manifest files + root = ET.parse(file) + appname = root.getroot().attrib['package'] + is_app = False + prefix = '{http://schemas.android.com/apk/res/android}' + for md in root.findall("application/activity/meta-data"): + if md.attrib[prefix + 'name'] == 'android.app.lib_name': + is_app = True + + if not appname or not is_app: + continue + + # now that we have the app id, look for matching appdata/desktop files + appdataFiles = glob.iglob(arguments.source + "/**/" + appname + ".appdata.xml", recursive=True) + appdataFile = None + for f in appdataFiles: + appdataFile = f + break + if not appdataFile: + continue + + desktopFiles = glob.iglob(arguments.source + "/**/" + appname + ".desktop", recursive=True) + desktopFile = None + for f in desktopFiles: + desktopFile = f + break + + processAppstreamFile(appdataFile, desktopFile) + + +### Script Commences + +# Parse the command line arguments we've been given +parser = argparse.ArgumentParser(description='Generate fastlane metadata for Android apps from appstream metadata') +parser.add_argument('--apk', type=str, required=False, help='APK file to extract metadata from') +parser.add_argument('--appstream', type=str, required=False, help='Appstream file to extract metadata from') +parser.add_argument('--desktop', type=str, required=False, help='Desktop file to extract additional metadata from') +parser.add_argument('--source', type=str, required=False, help='Source directory to find metadata in') +parser.add_argument('--output', type=str, required=True, help='Path to which the metadata output should be written to') +arguments = parser.parse_args() + +# ensure the output path exists +os.makedirs(arguments.output, exist_ok=True) + +# if we have an appstream file explicitly specified, let's use that one +if arguments.appstream and os.path.exists(arguments.appstream): + processAppstreamFile(arguments.appstream, arguments.desktop) + sys.exit(0) + +# else, if we have an APK, try to find the appstream file in there +# this ensures compatibility with the old metadata generation +if arguments.apk and os.path.exists(arguments.apk): + processApkFile(arguments.apk) + sys.exit(0) + +# else, look in the source dir for appstream/desktop files +# this follows roughly what get-apk-args from binary factory does +if arguments.source and os.path.exists(arguments.source): + scanSourceDir() + sys.exit(0) + +# else: missing arguments +print("Either one of --appstream, --apk or --source have to be provided!") +sys.exit(1) diff --git a/toolchain/specifydependencies.cmake b/toolchain/specifydependencies.cmake index d21250c1..69a7f534 100644 --- a/toolchain/specifydependencies.cmake +++ b/toolchain/specifydependencies.cmake @@ -1,25 +1,31 @@ -execute_process(COMMAND readelf --wide --dynamic ${TARGET} ERROR_VARIABLE readelf_errors OUTPUT_VARIABLE out RESULT_VARIABLE result) -if (NOT result EQUAL 0) - message(FATAL_ERROR "readelf failed on ${TARGET} exit(${result}): ${readelf_errors}") -endif() +function(list_dependencies target libs) + execute_process(COMMAND readelf --wide --dynamic ${target} ERROR_VARIABLE readelf_errors OUTPUT_VARIABLE out RESULT_VARIABLE result) -string(REPLACE "\n" ";" lines "${out}") -set(extralibs) -foreach(line ${lines}) - string(REGEX MATCH ".*\\(NEEDED\\) +Shared library: +\\[(.+)\\]$" matched ${line}) - set(currentLib ${CMAKE_MATCH_1}) + if (NOT result EQUAL 0) + message(FATAL_ERROR "readelf failed on ${target} exit(${result}): ${readelf_errors}") + endif() - if(NOT ${currentLib} MATCHES "libQt5.*" AND matched) - find_file(ourlib-${currentLib} ${currentLib} HINTS ${OUTPUT_DIR} ${EXPORT_DIR} ${ECM_ADDITIONAL_FIND_ROOT_PATH} NO_DEFAULT_PATH PATH_SUFFIXES lib) + string(REPLACE "\n" ";" lines "${out}") + set(extralibs ${${libs}}) + foreach(line ${lines}) + string(REGEX MATCH ".*\\(NEEDED\\) +Shared library: +\\[(.+)\\]$" matched ${line}) + set(currentLib ${CMAKE_MATCH_1}) - if(ourlib-${currentLib}) - list(APPEND extralibs "${ourlib-${currentLib}}") - else() - message(STATUS "could not find ${currentLib} in ${OUTPUT_DIR} ${EXPORT_DIR}/lib/ ${ECM_ADDITIONAL_FIND_ROOT_PATH}") + if(NOT ${currentLib} MATCHES "libQt5.*" AND matched) + find_file(ourlib-${currentLib} ${currentLib} HINTS ${OUTPUT_DIR} ${EXPORT_DIR} ${ECM_ADDITIONAL_FIND_ROOT_PATH} NO_DEFAULT_PATH PATH_SUFFIXES lib) + + if(ourlib-${currentLib}) + list(APPEND extralibs "${ourlib-${currentLib}}") + else() + message(STATUS "could not find ${currentLib} in ${OUTPUT_DIR} ${EXPORT_DIR}/lib/ " ${ECM_ADDITIONAL_FIND_ROOT_PATH}) + endif() endif() - endif() -endforeach() + endforeach() + set(${libs} ${extralibs} PARENT_SCOPE) +endfunction() + +list_dependencies(${TARGET} extralibs) function(contains_library libpath IS_EQUAL) get_filename_component (name ${libpath} NAME) @@ -47,23 +53,29 @@ if (ANDROID_EXTRA_LIBS) endforeach() endif() -if(extralibs) - string(REPLACE ";" "," libs "${extralibs}") - set(extralibs "\"android-extra-libs\": \"${libs}\",") -endif() - set(extraplugins) -foreach(folder "share" "lib/qml") #now we check for folders with extra stuff +foreach(folder "plugins" "share" "lib/qml") #now we check for folders with extra stuff set(plugin "${EXPORT_DIR}/${folder}") if(EXISTS "${plugin}") - if(extraplugins) - set(extraplugins "${extraplugins},${plugin}") - else() - set(extraplugins "${plugin}") - endif() + list(APPEND extraplugins "${plugin}") endif() endforeach() + +if(EXISTS "module-plugins") + file(READ "module-plugins" moduleplugins) + foreach(module ${moduleplugins}) + list_dependencies(${module} extralibs) + endforeach() + list(REMOVE_DUPLICATES extralibs) +endif() + +if(extralibs) + string(REPLACE ";" "," extralibs "${extralibs}") + set(extralibs "\"android-extra-libs\": \"${extralibs}\",") +endif() + if(extraplugins) + string(REPLACE ";" "," extraplugins "${extraplugins}") set(extraplugins "\"android-extra-plugins\": \"${extraplugins}\",") endif() @@ -73,9 +85,18 @@ file(READ "stl" stl_contents) file(READ "ranlib" ranlib_contents) string(REGEX MATCH ".+/toolchains/(.+)-([^\\-]+)/prebuilt/.*/bin/(.*)-ranlib" x ${ranlib_contents}) -string(REPLACE "##ANDROID_TOOL_PREFIX##" "${CMAKE_MATCH_1}" NEWCONTENTS "${CONTENTS}") -string(REPLACE "##ANDROID_TOOLCHAIN_VERSION##" "${CMAKE_MATCH_2}" NEWCONTENTS "${NEWCONTENTS}") -string(REPLACE "##ANDROID_COMPILER_PREFIX##" "${CMAKE_MATCH_3}" NEWCONTENTS "${NEWCONTENTS}") +if (USE_LLVM) + string(REPLACE "##ANDROID_TOOL_PREFIX##" "llvm" NEWCONTENTS "${CONTENTS}") + string(REPLACE "##ANDROID_COMPILER_PREFIX##" "llvm" NEWCONTENTS "${NEWCONTENTS}") + string(REPLACE "##USE_LLVM##" true NEWCONTENTS "${NEWCONTENTS}") +else() + string(REPLACE "##ANDROID_TOOL_PREFIX##" "${CMAKE_MATCH_1}" NEWCONTENTS "${CONTENTS}") + string(REPLACE "##ANDROID_COMPILER_PREFIX##" "${CMAKE_MATCH_3}" NEWCONTENTS "${NEWCONTENTS}") + string(REPLACE "##USE_LLVM##" false NEWCONTENTS "${NEWCONTENTS}") +endif() + +string(REPLACE "##ANDROID_TOOLCHAIN_VERSION##" "${CMAKE_MATCH_2}" NEWCONTENTS "${NEWCONTENTS}") # not used when USE_LLVM is set + string(REPLACE "##EXTRALIBS##" "${extralibs}" NEWCONTENTS "${NEWCONTENTS}") string(REPLACE "##EXTRAPLUGINS##" "${extraplugins}" NEWCONTENTS "${NEWCONTENTS}") string(REPLACE "##CMAKE_CXX_STANDARD_LIBRARIES##" "${stl_contents}" NEWCONTENTS "${NEWCONTENTS}") |