aboutsummaryrefslogtreecommitdiff
path: root/modules/ECMSetupQtPluginMacroNames.cmake
blob: 9612f4626c9265a97b09394d8c8922a29e0608a0 (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
#.rst:
# ECMSetupQtPluginMacroNames
# --------------------------
#
# Instruct CMake's automoc about C++ preprocessor macros used to define Qt-style plugins.
#
# ::
#
#   ecm_setup_qtplugin_macro_names(
#       [JSON_NONE <macro_name> [<macro_name> [...]]]
#       [JSON_ARG1 <macro_name> [<macro_name> [...]]]
#       [JSON_ARG2 <macro_name> [<macro_name> [...]]]
#       [JSON_ARG3 <macro_name> [<macro_name> [...]]]
#       [CONFIG_CODE_VARIABLE <variable_name>] )
#
# CMake's automoc needs some support when parsing C++ source files to detect whether moc
# should be run on those files and if there are also dependencies on other files, like those
# with Qt plugin metadata in JSON format. Because automoc just greps overs the raw plain text
# of the sources without any C++ preprocessor-like processing.
# CMake in newer versions provides the variables ``CMAKE_AUTOMOC_DEPEND_FILTERS`` (CMake >= 3.9.0)
# and ``CMAKE_AUTOMOC_MACRO_NAMES`` (CMake >= 3.10) to allow the developer to assist automoc.
#
# This macro cares for the explicit setup needed for those variables for common cases of
# C++ preprocessor macros used for Qt-style plugins.
#
# JSON_NONE lists the names of C++ preprocessor macros for Qt-style plugins which do not refer to
# external files with the plugin metadata.
#
# JSON_ARG1 lists the names of C++ preprocessor macros for Qt-style plugins where the first argument
# to the macro is the name of the external file with the plugin metadata.
#
# JSON_ARG2 is the same as JSON_ARG1 but with the file name being the second argument.
#
# JSON_ARG3 is the same as JSON_ARG1 but with the file name being the third argument.
#
# CONFIG_CODE_VARIABLE specifies the name of the variable which will get set as
# value some generated CMake code for instructing automoc for the given macro names,
# as useful in an installed CMake config file. The variable can then be used as usual in
# the template file for such a CMake config file, by ``@<variable_name>@``.
#
#
# Example usage:
#
# Given some plugin-oriented Qt-based software which defines a custom C++ preprocessor
# macro ``EXPORT_MYPLUGIN`` for declaring the central plugin object:
#
# .. code-block:: c++
#
#   #define EXPORT_MYPLUGIN_WITH_JSON(classname, jsonFile) \
#   class classname : public QObject \
#   { \
#       Q_OBJECT \
#       Q_PLUGIN_METADATA(IID "myplugin" FILE jsonFile) \
#       explicit classname() {} \
#   };
#
# In the CMake buildsystem of the library one calls
#
# .. code-block:: cmake
#
#   ecm_setup_qtplugin_macro_names(
#       JSON_ARG2
#          EXPORT_MYPLUGIN_WITH_JSON
#   )
#
# to instruct automoc about the usage of that macro in the sources of the
# library itself.
#
# Given the software installs a library including the header with the macro
# definition and a CMake config file, so 3rd-party can create additional
# plugins by linking against the library, one passes additionally the name of
# a variable which shall be set as value the CMake code needed to instruct
# automoc about the usage of that macro.
#
# .. code-block:: cmake
#
#   ecm_setup_qtplugin_macro_names(
#       JSON_ARG2
#          EXPORT_MYPLUGIN_WITH_JSON
#       CONFIG_CODE_VARIABLE
#          PACKAGE_SETUP_AUTOMOC_VARIABLES
#   )
#
# This variable then is used in the template file (e.g.
# ``MyProjectConfig.cmake.in``) for the libary's installed CMake config file
# and that way will ensure that in the 3rd-party plugin's buildsystem
# automoc is instructed as well as needed:
#
# .. code-block:: cmake
#
#   @PACKAGE_SETUP_AUTOMOC_VARIABLES@
#
# Since 5.45.0.

#=============================================================================
# SPDX-FileCopyrightText: 2018 Friedrich W. H. Kossebau <kossebau@kde.org>
#
# SPDX-License-Identifier: BSD-3-Clause

include(CMakePackageConfigHelpers)

macro(ecm_setup_qtplugin_macro_names)
    set(options )
    set(oneValueArgs CONFIG_CODE_VARIABLE)
    set(multiValueArgs JSON_NONE JSON_ARG1 JSON_ARG2 JSON_ARG3)

    cmake_parse_arguments(ESQMN "${options}" "${oneValueArgs}" "${multiValueArgs}"  ${ARGN})

    if(ESQMN_UNPARSED_ARGUMENTS)
        message(FATAL_ERROR "Unknown keywords given to ECM_SETUP_QTPLUGIN_MACRO_NAMES(): \"${ESQMN_UNPARSED_ARGUMENTS}\"")
    endif()

    # CMAKE_AUTOMOC_MACRO_NAMES
    if(NOT CMAKE_VERSION VERSION_LESS "3.10.0")
        # CMake 3.9+ warns about automoc on files without Q_OBJECT, and doesn't know about other macros.
        # 3.10+ lets us provide more macro names that require automoc.
        list(APPEND CMAKE_AUTOMOC_MACRO_NAMES
            ${ESQMN_JSON_NONE}
            ${ESQMN_JSON_ARG1}
            ${ESQMN_JSON_ARG2}
            ${ESQMN_JSON_ARG3}
        )
    endif()

    # CMAKE_AUTOMOC_DEPEND_FILTERS
    if(NOT CMAKE_VERSION VERSION_LESS "3.9.0")
        # CMake's automoc needs help to find names of plugin metadata files in case Q_PLUGIN_METADATA
        # is indirectly used via other C++ preprocessor macros
        # 3.9+ lets us provide some filter rule pairs (keyword, regexp) to match the names of such files
        # in the plain text of the sources. See AUTOMOC_DEPEND_FILTERS docs for details.
        foreach(macro_name  ${ESQMN_JSON_ARG1})
            list(APPEND CMAKE_AUTOMOC_DEPEND_FILTERS
                "${macro_name}"
                "[\n^][ \t]*${macro_name}[ \t\n]*\\([ \t\n]*\"([^\"]+)\""
            )
        endforeach()
        foreach(macro_name  ${ESQMN_JSON_ARG2})
            list(APPEND CMAKE_AUTOMOC_DEPEND_FILTERS
                "${macro_name}"
                "[\n^][ \t]*${macro_name}[ \t\n]*\\([^,]*,[ \t\n]*\"([^\"]+)\""
            )
        endforeach()
        foreach(macro_name  ${ESQMN_JSON_ARG3})
            list(APPEND CMAKE_AUTOMOC_DEPEND_FILTERS
                "${macro_name}"
                "[\n^][ \t]*${macro_name}[ \t\n]*\\([^,]*,[^,]*,[ \t\n]*\"([^\"]+)\""
            )
        endforeach()
    endif()

    if (ESQMN_CONFIG_CODE_VARIABLE)
        set(_content
"####################################################################################
# CMAKE_AUTOMOC
")
        set(_all_macro_names
            ${ESQMN_JSON_NONE}
            ${ESQMN_JSON_ARG1}
            ${ESQMN_JSON_ARG2}
            ${ESQMN_JSON_ARG3}
        )
        string(APPEND _content "
if(NOT CMAKE_VERSION VERSION_LESS \"3.10.0\")
    # CMake 3.9+ warns about automoc on files without Q_OBJECT, and doesn't know about other macros.
    # 3.10+ lets us provide more macro names that require automoc.
    list(APPEND CMAKE_AUTOMOC_MACRO_NAMES ${_all_macro_names})
endif()
")

        if(ESQMN_JSON_ARG1 OR ESQMN_JSON_ARG2 OR ESQMN_JSON_ARG3)
            string(APPEND _content "
if(NOT CMAKE_VERSION VERSION_LESS \"3.9.0\")
    # CMake's automoc needs help to find names of plugin metadata files in case Q_PLUGIN_METADATA
    # is indirectly used via other C++ preprocessor macros
    # 3.9+ lets us provide some filter rule pairs (keyword, regexp) to match the names of such files
    # in the plain text of the sources. See AUTOMOC_DEPEND_FILTERS docs for details.
")
            if(ESQMN_JSON_ARG1)
                string(APPEND _content
"    foreach(macro_name  ${ESQMN_JSON_ARG1})
        list(APPEND CMAKE_AUTOMOC_DEPEND_FILTERS
            \"\${macro_name}\"
            \"[\\n^][ \\t]*\${macro_name}[ \\t\\n]*\\\\([ \\t\\n]*\\\"([^\\\"]+)\\\"\"
        )
    endforeach()
")
            endif()
            if(ESQMN_JSON_ARG2)
                string(APPEND _content
"    foreach(macro_name  ${ESQMN_JSON_ARG2})
        list(APPEND CMAKE_AUTOMOC_DEPEND_FILTERS
            \"\${macro_name}\"
            \"[\\n^][ \\t]*\${macro_name}[ \\t\\n]*\\\\([^,]*,[ \\t\\n]*\\\"([^\\\"]+)\\\"\"
        )
    endforeach()
")
            endif()
            if(ESQMN_JSON_ARG3)
                string(APPEND _content
"    foreach(macro_name  ${ESQMN_JSON_ARG3})
        list(APPEND CMAKE_AUTOMOC_DEPEND_FILTERS
            \"\${macro_name}\"
            \"[\\n^][ \\t]*\${macro_name}[ \\t\\n]*\\\\([^,]*,[^,]*,[ \\t\\n]*\\\"([^\\\"]+)\\\"\"
        )
    endforeach()
")
            endif()
            string(APPEND _content "endif()")
        endif()
        string(APPEND _content "
####################################################################################"
        )

        set(${ESQMN_CONFIG_CODE_VARIABLE} ${_content})
    endif()
endmacro()