|
| 1 | +# SPDX-FileCopyrightText: 2014 David Faure <faure@kde.org> |
| 2 | +# |
| 3 | +# SPDX-License-Identifier: BSD-3-Clause |
| 4 | + |
| 5 | +#[=======================================================================[.rst: |
| 6 | +ECMGeneratePriFile |
| 7 | +------------------ |
| 8 | +
|
| 9 | +Generate a ``.pri`` file for the benefit of qmake-based projects. |
| 10 | +
|
| 11 | +As well as the function below, this module creates the cache variable |
| 12 | +``ECM_MKSPECS_INSTALL_DIR`` and sets the default value to ``mkspecs/modules``. |
| 13 | +This assumes Qt and the current project are both installed to the same |
| 14 | +non-system prefix. Packagers who use ``-DCMAKE_INSTALL_PREFIX=/usr`` will |
| 15 | +certainly want to set ``ECM_MKSPECS_INSTALL_DIR`` to something like |
| 16 | +``share/qt5/mkspecs/modules``. |
| 17 | +
|
| 18 | +The main thing is that this should be the ``modules`` subdirectory of either |
| 19 | +the default qmake ``mkspecs`` directory or of a directory that will be in the |
| 20 | +``$QMAKEPATH`` environment variable when qmake is run. |
| 21 | +
|
| 22 | +:: |
| 23 | +
|
| 24 | + ecm_generate_pri_file(BASE_NAME <baseName> |
| 25 | + LIB_NAME <libName> |
| 26 | + [VERSION <version>] # since 5.83 |
| 27 | + [DEPS "<dep> [<dep> [...]]"] |
| 28 | + [FILENAME_VAR <filename_variable>] |
| 29 | + [INCLUDE_INSTALL_DIRS <dir> [<dir> [...]]] # since 5.92 |
| 30 | + [INCLUDE_INSTALL_DIR <dir>] # deprecated since 5.92 |
| 31 | + [LIB_INSTALL_DIR <dir>]) |
| 32 | +
|
| 33 | +If your CMake project produces a Qt-based library, you may expect there to be |
| 34 | +applications that wish to use it that use a qmake-based build system, rather |
| 35 | +than a CMake-based one. Creating a ``.pri`` file will make use of your |
| 36 | +library convenient for them, in much the same way that CMake config files make |
| 37 | +things convenient for CMake-based applications. ``ecm_generate_pri_file()`` |
| 38 | +generates just such a file. |
| 39 | +
|
| 40 | +VERSION specifies the version of the library the ``.pri`` file describes. If |
| 41 | +not set, the value is taken from the context variable ``PROJECT_VERSION``. |
| 42 | +This variable is usually set by the ``project(... VERSION ...)`` command or, |
| 43 | +if CMake policy CMP0048 is not NEW, by :module:`ECMSetupVersion`. |
| 44 | +For backward-compatibility with older ECM versions the |
| 45 | +``PROJECT_VERSION_STRING`` variable as set by :module:`ECMSetupVersion` |
| 46 | +will be preferred over ``PROJECT_VERSION`` if set, unless the minimum |
| 47 | +required version of ECM is 5.83 and newer. Since 5.83. |
| 48 | +
|
| 49 | +BASE_NAME specifies the name qmake project (.pro) files should use to refer to |
| 50 | +the library (eg: KArchive). LIB_NAME is the name of the actual library to |
| 51 | +link to (ie: the first argument to add_library()). DEPS is a space-separated |
| 52 | +list of the base names of other libraries (for Qt libraries, use the same |
| 53 | +names you use with the ``QT`` variable in a qmake project file, such as "core" |
| 54 | +for QtCore). FILENAME_VAR specifies the name of a variable to store the path |
| 55 | +to the generated file in. |
| 56 | +
|
| 57 | +INCLUDE_INSTALL_DIRS are the paths (relative to ``CMAKE_INSTALL_PREFIX``) that |
| 58 | +include files will be installed to. It defaults to |
| 59 | +``${INCLUDE_INSTALL_DIR}/<baseName>`` if the ``INCLUDE_INSTALL_DIR`` variable |
| 60 | +is set. If that variable is not set, the ``CMAKE_INSTALL_INCLUDEDIR`` variable |
| 61 | +is used instead, and if neither are set ``include`` is used. LIB_INSTALL_DIR |
| 62 | +operates similarly for the installation location for libraries; it defaults to |
| 63 | +``${LIB_INSTALL_DIR}``, ``${CMAKE_INSTALL_LIBDIR}`` or ``lib``, in that order. |
| 64 | +
|
| 65 | +INCLUDE_INSTALL_DIR is the old variant of INCLUDE_INSTALL_DIRS, taking only one |
| 66 | +directory. |
| 67 | +
|
| 68 | +Example usage: |
| 69 | +
|
| 70 | +.. code-block:: cmake |
| 71 | +
|
| 72 | + ecm_generate_pri_file( |
| 73 | + BASE_NAME KArchive |
| 74 | + LIB_NAME KF5KArchive |
| 75 | + DEPS "core" |
| 76 | + FILENAME_VAR pri_filename |
| 77 | + VERSION 4.2.0 |
| 78 | + ) |
| 79 | + install(FILES ${pri_filename} DESTINATION ${ECM_MKSPECS_INSTALL_DIR}) |
| 80 | +
|
| 81 | +A qmake-based project that wished to use this would then do:: |
| 82 | +
|
| 83 | + QT += KArchive |
| 84 | +
|
| 85 | +in their ``.pro`` file. |
| 86 | +
|
| 87 | +Since pre-1.0.0. |
| 88 | +#]=======================================================================] |
| 89 | + |
| 90 | +# Replicate the logic from KDEInstallDirs.cmake as we can't depend on it |
| 91 | +# Ask qmake if we're using the same prefix as Qt |
| 92 | +set(_should_query_qt OFF) |
| 93 | +if(NOT DEFINED KDE_INSTALL_USE_QT_SYS_PATHS) |
| 94 | + include(ECMQueryQt) |
| 95 | + ecm_query_qt(qt_install_prefix_dir QT_INSTALL_PREFIX TRY) |
| 96 | + if(qt_install_prefix_dir STREQUAL "${CMAKE_INSTALL_PREFIX}") |
| 97 | + set(_should_query_qt ON) |
| 98 | + endif() |
| 99 | +endif() |
| 100 | + |
| 101 | +if(KDE_INSTALL_USE_QT_SYS_PATHS OR _should_query_qt) |
| 102 | + include(ECMQueryQt) |
| 103 | + ecm_query_qt(qt_install_prefix_dir QT_INSTALL_PREFIX) |
| 104 | + ecm_query_qt(qt_host_data_dir QT_HOST_DATA) |
| 105 | + if(qt_install_prefix_dir STREQUAL "${CMAKE_INSTALL_PREFIX}") |
| 106 | + file(RELATIVE_PATH qt_host_data_dir ${qt_install_prefix_dir} ${qt_host_data_dir}) |
| 107 | + endif() |
| 108 | + if(qt_host_data_dir STREQUAL "") |
| 109 | + set(mkspecs_install_dir mkspecs/modules) |
| 110 | + else() |
| 111 | + set(mkspecs_install_dir ${qt_host_data_dir}/mkspecs/modules) |
| 112 | + endif() |
| 113 | + set(ECM_MKSPECS_INSTALL_DIR ${mkspecs_install_dir} CACHE PATH "The directory where mkspecs will be installed to.") |
| 114 | +else() |
| 115 | + set(ECM_MKSPECS_INSTALL_DIR mkspecs/modules CACHE PATH "The directory where mkspecs will be installed to.") |
| 116 | +endif() |
| 117 | + |
| 118 | +function(ECM_GENERATE_PRI_FILE) |
| 119 | + set(options INTERFACE) |
| 120 | + set(oneValueArgs BASE_NAME LIB_NAME DEPS FILENAME_VAR INCLUDE_INSTALL_DIR LIB_INSTALL_DIR VERSION) |
| 121 | + set(multiValueArgs INCLUDE_INSTALL_DIRS) |
| 122 | + |
| 123 | + cmake_parse_arguments(EGPF "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) |
| 124 | + |
| 125 | + if(EGPF_UNPARSED_ARGUMENTS) |
| 126 | + message(FATAL_ERROR "Unknown keywords given to ECM_GENERATE_PRI_FILE(): \"${EGPF_UNPARSED_ARGUMENTS}\"") |
| 127 | + endif() |
| 128 | + |
| 129 | + if(ECM_GLOBAL_FIND_VERSION VERSION_LESS 5.83.0) |
| 130 | + set(_support_backward_compat_version_string_var TRUE) |
| 131 | + else() |
| 132 | + set(_support_backward_compat_version_string_var FALSE) |
| 133 | + endif() |
| 134 | + |
| 135 | + if(NOT EGPF_BASE_NAME) |
| 136 | + message(FATAL_ERROR "Required argument BASE_NAME missing in ECM_GENERATE_PRI_FILE() call") |
| 137 | + endif() |
| 138 | + if(NOT EGPF_LIB_NAME) |
| 139 | + message(FATAL_ERROR "Required argument LIB_NAME missing in ECM_GENERATE_PRI_FILE() call") |
| 140 | + endif() |
| 141 | + if(NOT EGPF_VERSION) |
| 142 | + if(_support_backward_compat_version_string_var) |
| 143 | + if(NOT PROJECT_VERSION_STRING AND NOT PROJECT_VERSION) |
| 144 | + message(FATAL_ERROR "Required variable PROJECT_VERSION_STRING or PROJECT_VERSION not set before ECM_GENERATE_PRI_FILE() call. Missing call of ecm_setup_version() or project(VERSION)?") |
| 145 | + endif() |
| 146 | + else() |
| 147 | + if(NOT PROJECT_VERSION) |
| 148 | + message(FATAL_ERROR "Required variable PROJECT_VERSION not set before ECM_GENERATE_PRI_FILE() call. Missing call of ecm_setup_version() or project(VERSION)?") |
| 149 | + endif() |
| 150 | + endif() |
| 151 | + endif() |
| 152 | + if(EGPF_INCLUDE_INSTALL_DIR) |
| 153 | + if(EGPF_INCLUDE_INSTALL_DIRS) |
| 154 | + message(FATAL_ERROR "Only one argument of INCLUDE_INSTALL_DIR & INCLUDE_INSTALL_DIRS can be used in ECM_GENERATE_PRI_FILE() call") |
| 155 | + endif() |
| 156 | + set(EGPF_INCLUDE_INSTALL_DIRS ${EGPF_INCLUDE_INSTALL_DIR}) |
| 157 | + endif() |
| 158 | + if(NOT EGPF_INCLUDE_INSTALL_DIRS) |
| 159 | + if(INCLUDE_INSTALL_DIR) |
| 160 | + set(EGPF_INCLUDE_INSTALL_DIRS "${INCLUDE_INSTALL_DIR}/${EGPF_BASE_NAME}") |
| 161 | + elseif(CMAKE_INSTALL_INCLUDEDIR) |
| 162 | + set(EGPF_INCLUDE_INSTALL_DIRS "${CMAKE_INSTALL_INCLUDEDIR}/${EGPF_BASE_NAME}") |
| 163 | + else() |
| 164 | + set(EGPF_INCLUDE_INSTALL_DIRS "include/${EGPF_BASE_NAME}") |
| 165 | + endif() |
| 166 | + endif() |
| 167 | + if(NOT EGPF_LIB_INSTALL_DIR) |
| 168 | + if(LIB_INSTALL_DIR) |
| 169 | + set(EGPF_LIB_INSTALL_DIR "${LIB_INSTALL_DIR}") |
| 170 | + elseif(CMAKE_INSTALL_LIBDIR) |
| 171 | + set(EGPF_LIB_INSTALL_DIR "${CMAKE_INSTALL_LIBDIR}") |
| 172 | + else() |
| 173 | + set(EGPF_LIB_INSTALL_DIR "lib") |
| 174 | + endif() |
| 175 | + endif() |
| 176 | + |
| 177 | + if(EGPF_VERSION) |
| 178 | + set(PRI_VERSION "${EGPF_VERSION}") |
| 179 | + else() |
| 180 | + if(_support_backward_compat_version_string_var AND PROJECT_VERSION_STRING) |
| 181 | + set(PRI_VERSION "${PROJECT_VERSION_STRING}") |
| 182 | + if(NOT PROJECT_VERSION_STRING STREQUAL PROJECT_VERSION) |
| 183 | + message(DEPRECATION "ECM_GENERATE_PRI_FILE() will no longer support PROJECT_VERSION_STRING when the required minimum version of ECM is 5.83 or newer. Set VERSION parameter or use PROJECT_VERSION instead.") |
| 184 | + endif() |
| 185 | + else() |
| 186 | + set(PRI_VERSION "${PROJECT_VERSION}") |
| 187 | + endif() |
| 188 | + endif() |
| 189 | + |
| 190 | + string(REGEX REPLACE "^([0-9]+)\\.[0-9]+\\.[0-9]+.*" "\\1" PRI_VERSION_MAJOR "${PRI_VERSION}") |
| 191 | + string(REGEX REPLACE "^[0-9]+\\.([0-9]+)\\.[0-9]+.*" "\\1" PRI_VERSION_MINOR "${PRI_VERSION}") |
| 192 | + string(REGEX REPLACE "^[0-9]+\\.[0-9]+\\.([0-9]+).*" "\\1" PRI_VERSION_PATCH "${PRI_VERSION}") |
| 193 | + |
| 194 | + # Prepare the right number of "../.." to go from ECM_MKSPECS_INSTALL_DIR to the install prefix |
| 195 | + # This allows to make the generated pri files relocatable (no absolute paths) |
| 196 | + if (IS_ABSOLUTE ${ECM_MKSPECS_INSTALL_DIR}) |
| 197 | + set(BASEPATH ${CMAKE_INSTALL_PREFIX}) |
| 198 | + else() |
| 199 | + string(REGEX REPLACE "[^/]+" ".." PRI_ROOT_RELATIVE_TO_MKSPECS ${ECM_MKSPECS_INSTALL_DIR}) |
| 200 | + set(BASEPATH "$$PWD/${PRI_ROOT_RELATIVE_TO_MKSPECS}") |
| 201 | + endif() |
| 202 | + |
| 203 | + set(PRI_TARGET_BASENAME ${EGPF_BASE_NAME}) |
| 204 | + set(PRI_TARGET_LIBNAME ${EGPF_LIB_NAME}) |
| 205 | + set(PRI_TARGET_QTDEPS ${EGPF_DEPS}) |
| 206 | + set(PRI_TARGET_INCLUDES) |
| 207 | + foreach(_dir ${EGPF_INCLUDE_INSTALL_DIRS}) |
| 208 | + # separate list entries with space |
| 209 | + if(IS_ABSOLUTE "${_dir}") |
| 210 | + string(APPEND PRI_TARGET_INCLUDES " ${_dir}") |
| 211 | + else() |
| 212 | + string(APPEND PRI_TARGET_INCLUDES " ${BASEPATH}/${_dir}") |
| 213 | + endif() |
| 214 | + endforeach() |
| 215 | + if(IS_ABSOLUTE "${EGPF_LIB_INSTALL_DIR}") |
| 216 | + set(PRI_TARGET_LIBS "${EGPF_LIB_INSTALL_DIR}") |
| 217 | + else() |
| 218 | + set(PRI_TARGET_LIBS "${BASEPATH}/${EGPF_LIB_INSTALL_DIR}") |
| 219 | + endif() |
| 220 | + set(PRI_TARGET_DEFINES "") |
| 221 | + |
| 222 | + set(PRI_FILENAME ${CMAKE_CURRENT_BINARY_DIR}/qt_${PRI_TARGET_BASENAME}.pri) |
| 223 | + if (EGPF_FILENAME_VAR) |
| 224 | + set(${EGPF_FILENAME_VAR} ${PRI_FILENAME} PARENT_SCOPE) |
| 225 | + endif() |
| 226 | + |
| 227 | + set(PRI_TARGET_MODULE_CONFIG "") |
| 228 | + # backward compat: it was not obvious LIB_NAME needs to be a target name, |
| 229 | + # and some projects where the target name was not the actual library output name |
| 230 | + # passed the output name for LIB_NAME, so .name & .module prperties are correctly set. |
| 231 | + # TODO: improve API dox, allow control over module name if target name != output name |
| 232 | + if(TARGET ${EGPF_LIB_NAME}) |
| 233 | + get_target_property(target_type ${EGPF_LIB_NAME} TYPE) |
| 234 | + if (target_type STREQUAL "STATIC_LIBRARY") |
| 235 | + set(PRI_TARGET_MODULE_CONFIG "staticlib") |
| 236 | + endif() |
| 237 | + endif() |
| 238 | + |
| 239 | + if (EGPF_INTERFACE) |
| 240 | + set(PRI_TARGET_MODULE "") |
| 241 | + else() |
| 242 | + set(PRI_TARGET_MODULE "${PRI_TARGET_LIBNAME}") |
| 243 | + endif() |
| 244 | + |
| 245 | + |
| 246 | + file(GENERATE |
| 247 | + OUTPUT ${PRI_FILENAME} |
| 248 | + CONTENT |
| 249 | + "QT.${PRI_TARGET_BASENAME}.VERSION = ${PRI_VERSION} |
| 250 | +QT.${PRI_TARGET_BASENAME}.MAJOR_VERSION = ${PRI_VERSION_MAJOR} |
| 251 | +QT.${PRI_TARGET_BASENAME}.MINOR_VERSION = ${PRI_VERSION_MINOR} |
| 252 | +QT.${PRI_TARGET_BASENAME}.PATCH_VERSION = ${PRI_VERSION_PATCH} |
| 253 | +QT.${PRI_TARGET_BASENAME}.name = ${PRI_TARGET_LIBNAME} |
| 254 | +QT.${PRI_TARGET_BASENAME}.module = ${PRI_TARGET_MODULE} |
| 255 | +QT.${PRI_TARGET_BASENAME}.defines = ${PRI_TARGET_DEFINES} |
| 256 | +QT.${PRI_TARGET_BASENAME}.includes = ${PRI_TARGET_INCLUDES} |
| 257 | +QT.${PRI_TARGET_BASENAME}.private_includes = |
| 258 | +QT.${PRI_TARGET_BASENAME}.libs = ${PRI_TARGET_LIBS} |
| 259 | +QT.${PRI_TARGET_BASENAME}.depends = ${PRI_TARGET_QTDEPS} |
| 260 | +QT.${PRI_TARGET_BASENAME}.module_config = ${PRI_TARGET_MODULE_CONFIG} |
| 261 | +" |
| 262 | + ) |
| 263 | +endfunction() |
0 commit comments