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
|
cmake_minimum_required(VERSION 3.17.0 FATAL_ERROR)
# defines helper to link against Qt dynamically or statically
# prevent multiple inclusion
if (DEFINED QT_LINKAGE_DETERMINED)
return()
endif ()
set(QT_LINKAGE_DETERMINED ON)
# include validate_visibility from c++utilities' 3rdParty module
include(3rdParty)
# allow switching the Qt and KDE Frameworks version
set(QT_PACKAGE_PREFIX
"Qt5"
CACHE STRING "specifies the prefix for Qt packages")
set(KF_PACKAGE_PREFIX
"KF5"
CACHE STRING "specifies the prefix for KDE Frameworks packages")
# determine the minimum Qt version
if (NOT META_QT_VERSION)
if (META_QT5_VERSION)
# use deprecated META_QT5_VERSION variable (for compatibility)
set(META_QT_VERSION "${META_QT5_VERSION}")
else ()
# require Qt 5.6 or higher by default
set(META_QT_VERSION 5.6)
endif ()
endif ()
# avoid "add_custom_target cannot create target "apk" because another target…" errors produced by Qt's Android support module
# (which can not cope with Qt CMake modules already pulled in by a dependency)
if (ANDROID AND NOT ${PROJECT_NAME}-MultiAbiBuild)
set(${PROJECT_NAME}-MultiAbiBuild ON)
endif ()
# define function for using Qt and KDE Frameworks modules and static plugins
macro (use_qt_module)
# parse arguments
set(OPTIONAL_ARGS ONLY_PLUGINS PLUGINS_OPTIONAL)
set(ONE_VALUE_ARGS PREFIX MODULE VISIBILITY LIBRARIES_VARIABLE)
set(MULTI_VALUE_ARGS TARGETS PLUGINS)
cmake_parse_arguments(ARGS "${OPTIONAL_ARGS}" "${ONE_VALUE_ARGS}" "${MULTI_VALUE_ARGS}" ${ARGN})
# validate values
if (NOT ARGS_PREFIX)
message(FATAL_ERROR "use_qt_module called without PREFIX.")
endif ()
if (NOT ARGS_MODULE)
message(FATAL_ERROR "use_qt_module called without MODULE.")
endif ()
if (ARGS_VISIBILITY)
validate_visibility(${ARGS_VISIBILITY})
else ()
set(ARGS_VISIBILITY PRIVATE)
endif ()
if (NOT ARGS_LIBRARIES_VARIABLE)
set(ARGS_LIBRARIES_VARIABLE "${ARGS_VISIBILITY}_LIBRARIES")
endif ()
if (NOT ARGS_TARGETS)
if (${MODULE}_MODULE_TARGETS)
set(ARGS_TARGETS "${${MODULE}_MODULE_TARGETS}")
else ()
set(ARGS_TARGETS "${ARGS_PREFIX}::${ARGS_MODULE}")
endif ()
endif ()
if (ARGS_ONLY_PLUGINS AND NOT ARGS_PLUGINS)
message(FATAL_ERROR "ONLY_PLUGINS specified but no plugins.")
endif ()
# find and use module
if (NOT ONLY_PLUGINS)
find_package("${ARGS_PREFIX}${ARGS_MODULE}" "${META_QT_VERSION}" REQUIRED)
foreach (TARGET ${ARGS_TARGETS})
if (NOT TARGET "${TARGET}")
message(FATAL_ERROR "The CMake module ${ARGS_PREFIX}${ARGS_MODULE} does not provide the target ${TARGET}.")
endif ()
if ("${TARGET}" IN_LIST "${ARGS_LIBRARIES_VARIABLE}")
continue()
endif ()
set("${ARGS_LIBRARIES_VARIABLE}" "${${ARGS_LIBRARIES_VARIABLE}};${TARGET}")
set("PKG_CONFIG_${ARGS_PREFIX}_${ARGS_MODULE}" "${ARGS_PREFIX}${ARGS_MODULE}")
message(STATUS "Linking ${META_TARGET_NAME} against Qt module ${TARGET}.")
# hack for "StaticQt5": re-assign INTERFACE_LINK_LIBRARIES_RELEASE to INTERFACE_LINK_LIBRARIES
get_target_property("${ARGS_MODULE}_INTERFACE_LINK_LIBRARIES_RELEASE" "${TARGET}"
INTERFACE_LINK_LIBRARIES_RELEASE)
if ("${ARGS_MODULE}_INTERFACE_LINK_LIBRARIES_RELEASE")
set_target_properties("${TARGET}" PROPERTIES INTERFACE_LINK_LIBRARIES
"${${ARGS_MODULE}_INTERFACE_LINK_LIBRARIES_RELEASE}")
endif ()
endforeach ()
endif ()
# find and use plugins
foreach (PLUGIN ${ARGS_PLUGINS})
set(PLUGIN_TARGET "${ARGS_PREFIX}::Q${PLUGIN}Plugin")
if (NOT TARGET "${PLUGIN_TARGET}")
find_package("${ARGS_PREFIX}${ARGS_MODULE}" "${META_QT_VERSION}" REQUIRED)
endif ()
if (NOT TARGET "${PLUGIN_TARGET}"
AND PLUGIN MATCHES "Svg.*"
AND ARGS_MODULE STREQUAL "Svg")
# look for Svg plugins within the Gui module's directory as well
find_package("${ARGS_PREFIX}Gui" "${META_QT_VERSION}" REQUIRED)
set(PLUGIN_CONFIG "${${ARGS_PREFIX}Gui_DIR}/${ARGS_PREFIX}Q${PLUGIN}PluginConfig.cmake")
if (EXISTS "${PLUGIN_CONFIG}")
include("${PLUGIN_CONFIG}")
endif ()
endif ()
if (NOT TARGET "${PLUGIN_TARGET}")
if (NOT PLUGINS_OPTIONAL)
continue()
endif ()
message(
FATAL_ERROR
"The ${ARGS_PREFIX}${ARGS_MODULE} package does not provide the target ${ARGS_PREFIX}::Q${PLUGIN}Plugin.")
endif ()
if ("${PLUGIN_TARGET}" IN_LIST "${ARGS_LIBRARIES_VARIABLE}")
continue()
endif ()
set("${ARGS_LIBRARIES_VARIABLE}" "${${ARGS_LIBRARIES_VARIABLE}};${ARGS_PREFIX}::Q${PLUGIN}Plugin")
message(STATUS "Linking ${META_TARGET_NAME} against Qt plugin ${ARGS_PREFIX}::Q${PLUGIN}Plugin.")
endforeach ()
# unset variables (can not simply use a function because Qt's variables need to be exported)
foreach (ARGUMENT ${OPTIONAL_ARGS} ${ONE_VALUE_ARGS} ${MULTI_VALUE_ARGS})
unset(ARGS_${ARGUMENT})
endforeach ()
endmacro ()
# define function to make Qt variable available; queries qmake or uses variables provided by Qt 6
function (query_qmake_variable QMAKE_VARIABLE)
# prevent queries for variables already known
if (NOT "${${QMAKE_VARIABLE}}" STREQUAL "")
return()
endif ()
# check configuration variables provided by Qt 6
if (QMAKE_VARIABLE MATCHES "QT_(.*)")
set(VARIABLE_NAME "${CMAKE_MATCH_1}")
if (QT6_${VARIABLE_NAME})
set(VARIABLE_NAME QT6_${VARIABLE_NAME})
endif ()
if (NOT "${${VARIABLE_NAME}}" STREQUAL "")
set("${QMAKE_VARIABLE}"
"${${VARIABLE_NAME}}"
PARENT_SCOPE)
message(STATUS "Qt variable ${QMAKE_VARIABLE} taken from ${VARIABLE_NAME}: ${${VARIABLE_NAME}}")
return()
endif ()
endif ()
# execute qmake
get_target_property(QMAKE_BIN "${QT_QMAKE_TARGET}" IMPORTED_LOCATION)
execute_process(
COMMAND "${QMAKE_BIN}" -query "${QMAKE_VARIABLE}"
RESULT_VARIABLE "${QMAKE_VARIABLE}_RESULT"
OUTPUT_VARIABLE "${QMAKE_VARIABLE}")
if (NOT "${${QMAKE_VARIABLE}_RESULT}" STREQUAL 0 OR "${${QMAKE_VARIABLE}}" STREQUAL "")
message(
FATAL_ERROR
"Unable to read qmake variable ${QMAKE_VARIABLE} via \"${QMAKE_BIN} -query ${QMAKE_VARIABLE}\"; output was \"${${QMAKE_VARIABLE}}\"."
)
endif ()
# remove new-line character at the end
string(REGEX REPLACE "\n$" "" "${QMAKE_VARIABLE}" "${${QMAKE_VARIABLE}}")
# export variable to parent scope
set("${QMAKE_VARIABLE}"
"${${QMAKE_VARIABLE}}"
PARENT_SCOPE)
message(STATUS "Qt variable ${QMAKE_VARIABLE} queried from qmake: ${${QMAKE_VARIABLE}}")
endfunction ()
# define function to make Qt variable available, resolving relative paths via CMAKE_FIND_ROOT_PATH
function (query_qmake_variable_path QMAKE_VARIABLE)
# query the variable itself
query_qmake_variable("${QMAKE_VARIABLE}")
set(VARIABLE_VALUE "${${QMAKE_VARIABLE}}")
if (NOT VARIABLE_VALUE)
message(WARNING "Unable to resolve Qt variable ${QMAKE_VARIABLE}: it is empty")
return()
endif ()
# pass the variable as-is if it points to an existing dir/file
if (EXISTS "${VARIABLE_VALUE}")
get_filename_component(VARIABLE_VALUE "${VARIABLE_VALUE}" REALPATH)
message(STATUS "Qt variable ${QMAKE_VARIABLE} resolved to path: ${VARIABLE_VALUE}")
set("${QMAKE_VARIABLE}"
"${VARIABLE_VALUE}"
PARENT_SCOPE)
return()
endif ()
# assume VARIABLE_VALUE is relative within CMAKE_FIND_ROOT_PATH, e.g. QT_INSTALL_TRANSLATIONS might be set to
# "share/qt6/translations"
if ("${CMAKE_VERSION}" VERSION_LESS "3.12.0")
message(WARNING "Unable to resolve Qt variable ${QMAKE_VARIABLE} to an existing path, try using CMake 3.12 or newer")
return() # skip if CMake version too old like on Leap 15.1
endif ()
foreach (ROOT_PATH ${CMAKE_FIND_ROOT_PATH} "")
foreach (PREFIX_PATH ${CMAKE_INSTALL_PREFIX} ${CMAKE_PREFIX_PATH} ${CMAKE_SYSTEM_PREFIX_PATH} "")
string(JOIN "/" FULL_PATH ${ROOT_PATH} ${PREFIX_PATH} ${VARIABLE_VALUE})
if (EXISTS "${FULL_PATH}")
set("${QMAKE_VARIABLE}"
"${FULL_PATH}"
PARENT_SCOPE)
message(STATUS "Qt variable ${QMAKE_VARIABLE} resolved to path: ${FULL_PATH}")
return()
else ()
list(APPEND CHECKED_PATHS "${FULL_PATH}")
endif ()
endforeach ()
endforeach ()
message(
WARNING "Unable to resolve Qt variable ${QMAKE_VARIABLE} to an existing path, was checking for: ${CHECKED_PATHS}")
endfunction ()
|