-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathFindGDBusCodegen.cmake
More file actions
226 lines (160 loc) · 6.38 KB
/
Copy pathFindGDBusCodegen.cmake
File metadata and controls
226 lines (160 loc) · 6.38 KB
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
# SPDX-License-Identifier: GPL-3.0-or-later
# Copyright © 2019 Damien Flament
# This file is part of CMake Modules.
#[=======================================================================[.rst:
FindGDBusCodegen
----------------
``gdbus-codegen`` is a D-Bus interface C code generation tool provided
by GLib.
This module finds the ``gdbus-codegen`` executable and add the
:command:`gdbus_generate_code` command.
Result Variables
^^^^^^^^^^^^^^^^
The following variable will also be set:
..variable:: GDBUS_CODEGEN_FOUND
True if the ``gdbus-codegen`` executable was found.
Cache Variables
^^^^^^^^^^^^^^^
The following cache variable may also be set:
.. variable:: GDBUS_CODEGEN_EXECUTABLE
The path to the ``gdbus-codegen`` executable.
#]=======================================================================]
include_guard(GLOBAL)
include(FindPackageHandleStandardArgs)
find_program(GDBUS_CODEGEN_EXECUTABLE
NAMES gdbus-codegen
DOC "gdbus-codegen executable"
)
mark_as_advanced(GDBUS_CODEGEN_EXECUTABLE)
find_package_handle_standard_args(GDBUS_CODEGEN DEFAULT_MSG
GDBUS_CODEGEN_EXECUTABLE)
#[=======================================================================[.rst:
.. command:: gdbus_generate_code
Generates C code for a D-Bus interface introspection ``file``. ::
gdbus_generate_code(<file>
[PREFIX <prefix>]
[NAMESPACE <namespace]
[HEADER_ONLY | BODY_ONLY]
[PRAGMA_ONCE])
When the ``PREFIX`` argument is given, the specified ``prefix`` is stripped
from the D-Bus interface name when computing the type name and the generated
filenames.
When the ``NAMESPACE`` argument is given, the specified ``namespace`` is used
for generated identifier and is also prepended to the generated filenames.
When the ``HEADER_ONLY`` or ``BODY_ONLY`` options are given, only one C code
file is generated (respectively the header file or the body file).
When the ``PRAGMA_ONCE`` options is given and the ``BODY_ONLY`` is not, the
``#pragma once`` directive is used instead of include guards.
The generated file name is ``<namespace><name>.<ext>`` with:
``<namespace>``
the namespace given though the ``NAMESPACE`` arguments
``<name>``
the name computed by stripping the given ``prefix`` then converting
to _CamelCase_
``<ext>``
the file extension: `h` for the header and `c` for the body
Examples
""""""""
.. code-block:: cmake
gdbus_generate_code(org.example.foo1.Bar.xml)
The ``OrgExampleFoo1Bar.h`` and ``OrgExampleFoo1Bar.c`` files will be
generated.
.. code-block:: cmake
gdbus_generate_code(org.example.foo1.Bar.xml
PREFIX org.example.foo1
NAMESPACE Foo)
The ``FooBar.h`` and ``FooBar.c`` files will be generated.
.. code-block:: cmake
gdbus_generate_code(org.example.foo1.Bar.xml
PREFIX org.example.foo1
NAMESPACE Foo
HEADER_ONLY
PRAGMA_ONCE)
The ``FooBar.h`` header file will be generated using the ``#pragma once``
preprocessor directive instead of include guards.
A more complete example
"""""""""""""""""""""""
.. code-blocks:: cmake
find_package(PkgConfig REQUIRED)
find_package(GDBusCodegen REQUIRED)
set(target foo)
pkg_check_modules(GLIB REQUIRED glib-2.0 gio-2.0)
gdbus_generate_code(org.example.foo1.Bar.xml
PREFIX org.example.foo1
NAMESPACE Foo
PRAGMA_ONCE)
add_executable(${target} main.c FooBar.c)
target_include_directories(${target} PUBLIC GLIB_INCLUDE_DIRS})
target_compile_options(${target} PUBLIC GLIB_CFLAGS})
target_link_libraries(${target} GLIB_LIBRARIES})
#]=======================================================================]
function(gdbus_generate_code file)
cmake_parse_arguments(PARSE_ARGV 0 ""
"HEADER_ONLY;BODY_ONLY;PRAGMA_ONCE"
"PREFIX;NAMESPACE"
""
)
# Check options
if (_HEADER_ONLY AND _BODY_ONLY)
message(FATAL_ERROR "HEADER_ONLY and BODY_ONLY options can not be both given.")
endif()
if (_PRAGMA_ONCE AND _BODY_ONLY)
message(FATAL_ERROR "PRAGMA_ONCE and BODY_ONLY options can not be both given.")
endif()
# Compute command flags
set(body_flags)
if (_PREFIX)
list(APPEND body_flags "--interface-prefix" "${_PREFIX}")
endif()
if (_NAMESPACE)
list(APPEND body_flags "--c-namespace" "${_NAMESPACE}")
endif()
set(header_flags ${body_flags})
if (_PRAGMA_ONCE)
list(APPEND header_flags "--pragma-once")
endif()
# Compute filenames
get_filename_component(filename "${file}" NAME) # TODO Use WLE component when CMake 3.14 is out
if(NOT ${filename} MATCHES "^(.+)\\\.xml$")
message(FATAL_ERROR "Failed to strip extension `.xml` from filename `${filename}`.")
endif()
set(basename ${CMAKE_MATCH_1})
if(_PREFIX)
if(_PREFIX STREQUAL basename)
message(FATAL_ERROR "The prefix `${_PREFIX}` can not be the basename of `${filename}`.")
endif()
if(NOT ${basename} MATCHES "^${_PREFIX}\\\.(.+)$")
message(FATAL_ERROR "Failed to strip prefix `${_PREFIX}` from basename `${basename}`.")
endif()
set(basename ${CMAKE_MATCH_1})
endif()
string(REPLACE "." ";" basename_components "${basename}")
foreach(word ${basename_components})
string(SUBSTRING "${word}" 0 1 first_letter)
string(TOUPPER "${first_letter}" first_letter)
string(REGEX REPLACE "^.(.*)$" "${first_letter}\\1" word "${word}")
list(APPEND name_components ${word})
endforeach()
list(JOIN name_components "" name)
set(header "${_NAMESPACE}${name}.h")
set(body "${_NAMESPACE}${name}.c")
# Compute body dependency
set(body_dependency ${header})
if (_BODY_ONLY)
set(body_dependency ${file})
endif()
# Add commands to generate header and/or body files
if (NOT _BODY_ONLY)
add_custom_command(OUTPUT "${header}"
COMMAND ${GDBUS_CODEGEN_EXECUTABLE} --header ${header_flags} --output "${header}" "${file}"
MAIN_DEPENDENCY "${file}"
COMMENT "Generating D-Bus interface header ${header}"
)
endif()
if (NOT _HEADER_ONLY)
add_custom_command(OUTPUT "${body}"
COMMAND ${GDBUS_CODEGEN_EXECUTABLE} --body ${body_flags} --output "${body}" "${file}"
MAIN_DEPENDENCY "${body_dependency}"
COMMENT "Generating D-Bus interface body ${body}")
endif()
endfunction()