vtkModuleWrapClientServer.cmake
Go to the documentation of this file.
1 #[==[.md
2 # `vtkModuleWrapClientServer`
3 
4 This module includes logic necessary in order to wrap VTK modules using
5 ParaView's ClientServer "language". This allows for classes in the module to be
6 used as proxies between ParaView client and server programs.
7 #]==]
8 
9 #[==[.md INTERNAL
10 ## Wrapping a single module
11 
12 This function generates the wrapped sources for a module. It places the list of
13 generated source files and classes in variables named in the second and third
14 arguments, respectively.
15 
16 ```
17 _vtk_module_wrap_client_server_sources(<module> <sources> <classes>)
18 ```
19 #]==]
20 
21 cmake_policy(PUSH)
22 cmake_policy(SET CMP0053 NEW)
23 
24 function (_vtk_module_wrap_client_server_sources module sources classes)
25  _vtk_module_get_module_property("${module}"
26  PROPERTY "exclude_wrap"
27  VARIABLE _vtk_client_server_exclude_wrap)
28  if (_vtk_client_server_exclude_wrap)
29  return ()
30  endif ()
31  _vtk_module_get_module_property("${module}"
32  PROPERTY "client_server_exclude"
33  VARIABLE _vtk_client_server_exclude)
34  if (_vtk_client_server_exclude)
35  return ()
36  endif ()
37 
38  set(_vtk_client_server_args_file "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/${_vtk_client_server_library_name}-client-server.$<CONFIGURATION>.args")
39 
40  set(_vtk_client_server_genex_compile_definitions
41  "$<TARGET_PROPERTY:${_vtk_client_server_target_name},COMPILE_DEFINITIONS>")
42  set(_vtk_client_server_genex_include_directories
43  "$<TARGET_PROPERTY:${_vtk_client_server_target_name},INCLUDE_DIRECTORIES>")
44  file(GENERATE
45  OUTPUT "${_vtk_client_server_args_file}"
46  CONTENT "$<$<BOOL:${_vtk_client_server_genex_compile_definitions}>:\n-D\'$<JOIN:${_vtk_client_server_genex_compile_definitions},\'\n-D\'>\'>\n
47 $<$<BOOL:${_vtk_client_server_genex_include_directories}>:\n-I\'$<JOIN:${_vtk_client_server_genex_include_directories},\'\n-I\'>\'>\n")
48 
49  _vtk_module_get_module_property("${module}"
50  PROPERTY "hierarchy"
51  VARIABLE _vtk_client_server_hierarchy_file)
52 
53  get_property(_vtk_client_server_is_imported
54  TARGET "${_vtk_client_server_target_name}"
55  PROPERTY "IMPORTED")
56  if (_vtk_client_server_is_imported OR CMAKE_GENERATOR MATCHES "Ninja")
57  set(_vtk_client_server_command_depend "${_vtk_client_server_hierarchy_file}")
58  else ()
59  if (TARGET "${_vtk_client_server_library_name}-hierarchy")
60  set(_vtk_client_server_command_depend "${_vtk_client_server_library_name}-hierarchy")
61  else ()
62  message(FATAL_ERROR
63  "The ${module} hierarchy file is attached to a non-imported target "
64  "and a hierarchy target "
65  "(${_vtk_client_server_library_name}-hierarchy) is missing.")
66  endif ()
67  endif ()
68 
69  # create directory for wrapped source files
70  file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/${_vtk_client_server_library_name}CS")
71 
72  set(_vtk_client_server_sources)
73 
74  _vtk_module_get_module_property("${module}"
75  PROPERTY "headers"
76  VARIABLE _vtk_client_server_headers)
77  set(_vtk_client_server_classes)
78  foreach (_vtk_client_server_header IN LISTS _vtk_client_server_headers)
79  get_filename_component(_vtk_client_server_basename "${_vtk_client_server_header}" NAME_WE)
80  list(APPEND _vtk_client_server_classes
81  "${_vtk_client_server_basename}")
82 
83  set(_vtk_client_server_source_output
84  "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/${_vtk_client_server_library_name}CS/${_vtk_client_server_basename}ClientServer.cxx")
85  list(APPEND _vtk_client_server_sources
86  "${_vtk_client_server_source_output}")
87 
88  add_custom_command(
89  OUTPUT "${_vtk_client_server_source_output}"
90  COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR}
91  "$<TARGET_FILE:ParaView::WrapClientServer>"
92  "@${_vtk_client_server_args_file}"
93  -o "${_vtk_client_server_source_output}"
94  "${_vtk_client_server_header}"
95  --types "${_vtk_client_server_hierarchy_file}"
96  IMPLICIT_DEPENDS
97  CXX "${_vtk_client_server_header}"
98  COMMENT "Generating client_server wrapper sources for ${_vtk_client_server_basename}"
99  DEPENDS
100  "$<TARGET_FILE:ParaView::WrapClientServer>"
101  "${_vtk_client_server_header}"
102  "${_vtk_client_server_args_file}"
103  "${_vtk_client_server_command_depend}")
104  endforeach ()
105 
106  set("${sources}"
107  "${_vtk_client_server_sources}"
108  PARENT_SCOPE)
109  set("${classes}"
110  "${_vtk_client_server_classes}"
111  PARENT_SCOPE)
112 endfunction ()
113 
114 #[==[.md INTERNAL
115 ## Generating a client server library
116 
117 A client server library may consist of the wrappings of multiple VTK modules.
118 This is useful for kit-based builds where the modules part of the same kit
119 belong to the same client server library as well.
120 
121 ```
122 _vtk_module_wrap_client_server_library(<name> <module>...)
123 ```
124 
125 The first argument is the name of the client server library. The remaining
126 arguments are VTK modules to include in the library.
127 
128 The remaining information it uses is assumed to be provided by the
129 `vtk_module_wrap_client_server` function.
130 #]==]
131 function (_vtk_module_wrap_client_server_library name)
132  set(_vtk_client_server_library_sources)
133  set(_vtk_client_server_library_classes)
134  foreach (_vtk_client_server_module IN LISTS ARGN)
135  _vtk_module_get_module_property("${_vtk_client_server_module}"
136  PROPERTY "exclude_wrap"
137  VARIABLE _vtk_client_server_exclude_wrap)
138  if (_vtk_client_server_exclude_wrap)
139  continue ()
140  endif ()
141  _vtk_module_get_module_property("${_vtk_client_server_module}"
142  PROPERTY "client_server_exclude"
143  VARIABLE _vtk_client_server_exclude)
144  if (_vtk_client_server_exclude)
145  return ()
146  endif ()
147 
148  _vtk_module_wrap_client_server_sources("${_vtk_client_server_module}" _vtk_client_server_sources _vtk_client_server_classes)
149  list(APPEND _vtk_client_server_library_sources
150  ${_vtk_client_server_sources})
151  list(APPEND _vtk_client_server_library_classes
152  ${_vtk_client_server_classes})
153  endforeach ()
154 
155  if (NOT _vtk_client_server_library_sources)
156  return ()
157  endif ()
158 
159  set(_vtk_client_server_declarations)
160  set(_vtk_client_server_calls)
161  foreach (_vtk_client_server_class IN LISTS _vtk_client_server_library_classes)
162  string(APPEND _vtk_client_server_declarations
163  "extern void ${_vtk_client_server_class}_Init(vtkClientServerInterpreter*);\n")
164  string(APPEND _vtk_client_server_calls
165  " ${_vtk_client_server_class}_Init(csi);\n")
166  endforeach ()
167  set(_vtk_client_server_init_content
168  "#include \"vtkABI.h\"
169 #include \"vtkClientServerInterpreter.h\"
170 
171 ${_vtk_client_server_declarations}
172 extern \"C\" void VTK_ABI_EXPORT ${name}_Initialize(vtkClientServerInterpreter* csi)
173 {
174  (void)csi;
175 ${_vtk_client_server_calls}}\n")
176 
177  set(_vtk_client_server_init_file
178  "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/${name}Init.cxx")
179  file(GENERATE
180  OUTPUT "${_vtk_client_server_init_file}"
181  CONTENT "${_vtk_client_server_init_content}")
182  # XXX(cmake): Why is this necessary? One would expect that `file(GENERATE)`
183  # would do this automatically.
184  set_property(SOURCE "${_vtk_client_server_init_file}"
185  PROPERTY
186  GENERATED 1)
187 
188  add_library("${name}" STATIC
189  ${_vtk_client_server_library_sources}
190  "${_vtk_client_server_init_file}")
191  if (BUILD_SHARED_LIBS)
192  set_property(TARGET "${name}"
193  PROPERTY
194  POSITION_INDEPENDENT_CODE 1)
195  endif ()
196  set(_vtk_build_LIBRARY_NAME_SUFFIX "${_vtk_client_server_LIBRARY_NAME_SUFFIX}")
197  set(_vtk_build_ARCHIVE_DESTINATION "${_vtk_client_server_DESTINATION}")
198  _vtk_module_apply_properties("${name}")
199 
200  vtk_module_autoinit(
201  MODULES ${ARGN}
202  TARGETS "${name}")
203 
204  target_link_libraries("${name}"
205  PRIVATE
206  ${ARGN}
207  ParaView::RemotingClientServerStream
208  VTK::CommonCore)
209 
210  set(_vtk_client_server_export)
211  if (_vtk_client_server_INSTALL_EXPORT)
212  list(APPEND _vtk_client_server_export
213  EXPORT "${_vtk_client_server_INSTALL_EXPORT}")
214  endif ()
215 
216  install(
217  TARGETS "${name}"
218  ${_vtk_client_server_export}
219  COMPONENT "${_vtk_client_server_COMPONENT}"
220  ARCHIVE DESTINATION "${_vtk_client_server_DESTINATION}")
221 endfunction ()
222 
223 #[==[.md
224 ## Wrapping a set of VTK modules for ClientServer
225 
226 ```
227 vtk_module_wrap_client_server(
228  MODULES <module>...
229  TARGET <target>
230  [WRAPPED_MODULES <varname>]
231 
232  [FUNCTION_NAME <function>]
233  [DESTINATION <destination>]
234 
235  [INSTALL_EXPORT <export>]
236  [COMPONENT <component>])
237 ```
238 
239  * `MODULES`: (Required) The list of modules to wrap.
240  * `TARGET`: (Required) The target to create which represents all wrapped
241  ClientServer modules. This is used to provide the function used to
242  initialize the bindings.
243  * `WRAPPED_MODULES`: (Recommended) Not all modules are wrappable. This
244  variable will be set to contain the list of modules which were wrapped.
245  * `FUNCTION_NAME`: (Recommended) (Defaults to `<TARGET>_initialize`) The
246  function name to generate in order to initialize the client server
247  bindings.A header with the name `<TARGET>.h` should be included in order to
248  access the initialization function.
249  * `DESTINATION`: (Defaults to `${CMAKE_INSTALL_LIBDIR}`) Where to install the
250  generated libraries.
251  * `INSTALL_EXPORT`: If provided, installs will add the installed
252  libraries and generated interface target to the provided export set.
253  * `COMPONENT`: (Defaults to `development`) All install rules created by this
254  function will use this installation component.
255 #]==]
256 function (vtk_module_wrap_client_server)
257  cmake_parse_arguments(_vtk_client_server
258  ""
259  "DESTINATION;INSTALL_EXPORT;TARGET;COMPONENT;FUNCTION_NAME;WRAPPED_MODULES"
260  "MODULES"
261  ${ARGN})
262 
263  if (_vtk_client_server_UNPARSED_ARGUMENTS)
264  message(FATAL_ERROR
265  "Unparsed arguments for vtk_module_wrap_client_server: "
266  "${_vtk_client_server_UNPARSED_ARGUMENTS}")
267  endif ()
268 
269  if (NOT _vtk_client_server_MODULES)
270  message(WARNING
271  "No modules were requested for client server wrapping.")
272  return ()
273  endif ()
274 
275  if (NOT _vtk_client_server_TARGET)
276  message(FATAL_ERROR
277  "The `TARGET` argument is required.")
278  endif ()
279 
280  if (NOT DEFINED _vtk_client_server_DESTINATION)
281  set(_vtk_client_server_DESTINATION "${CMAKE_INSTALL_LIBDIR}")
282  endif ()
283 
284  if (NOT DEFINED _vtk_client_server_COMPONENT)
285  set(_vtk_client_server_COMPONENT "development")
286  endif ()
287 
288  if (NOT DEFINED _vtk_client_server_FUNCTION_NAME)
289  set(_vtk_client_server_FUNCTION_NAME "${_vtk_client_server_TARGET}_initialize")
290  endif ()
291 
292  # Disable CMake's automoc support for these targets.
293  set(CMAKE_AUTOMOC 0)
294  set(CMAKE_AUTORCC 0)
295  set(CMAKE_AUTOUIC 0)
296 
297  # TODO: Install cmake properties?
298 
299  set(_vtk_client_server_all_modules)
300  set(_vtk_client_server_all_wrapped_modules)
301  foreach (_vtk_client_server_module IN LISTS _vtk_client_server_MODULES)
302  _vtk_module_get_module_property("${_vtk_client_server_module}"
303  PROPERTY "exclude_wrap"
304  VARIABLE _vtk_client_server_exclude_wrap)
305  if (_vtk_client_server_exclude_wrap)
306  continue ()
307  endif ()
308  _vtk_module_get_module_property("${_vtk_client_server_module}"
309  PROPERTY "client_server_exclude"
310  VARIABLE _vtk_client_server_exclude)
311  if (_vtk_client_server_exclude)
312  continue ()
313  endif ()
314  _vtk_module_real_target(_vtk_client_server_target_name "${_vtk_client_server_module}")
315  _vtk_module_get_module_property("${_vtk_client_server_module}"
316  PROPERTY "library_name"
317  VARIABLE _vtk_client_server_library_name)
318  _vtk_module_wrap_client_server_library("${_vtk_client_server_library_name}CS" "${_vtk_client_server_module}")
319 
320  if (TARGET "${_vtk_client_server_library_name}CS")
321  list(APPEND _vtk_client_server_all_modules
322  "${_vtk_client_server_library_name}CS")
323  list(APPEND _vtk_client_server_all_wrapped_modules
324  "${_vtk_client_server_module}")
325  endif ()
326  endforeach ()
327 
328  if (NOT _vtk_client_server_all_modules)
329  message(FATAL_ERROR
330  "No modules given could be wrapped.")
331  endif ()
332 
333  if (DEFINED _vtk_client_server_WRAPPED_MODULES)
334  set("${_vtk_client_server_WRAPPED_MODULES}"
335  "${_vtk_client_server_all_wrapped_modules}"
336  PARENT_SCOPE)
337  endif ()
338 
339  if (_vtk_client_server_TARGET)
340  add_library("${_vtk_client_server_TARGET}" INTERFACE)
341  target_include_directories("${_vtk_client_server_TARGET}"
342  INTERFACE
343  "$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/${_vtk_client_server_TARGET}>")
344 
345  set(_vtk_client_server_all_modules_include_file
346  "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/${_vtk_client_server_TARGET}/${_vtk_client_server_TARGET}.h")
347 
348  set(_vtk_client_server_declarations)
349  set(_vtk_client_server_calls)
350  foreach (_vtk_client_server_module IN LISTS _vtk_client_server_all_modules)
351  string(APPEND _vtk_client_server_declarations
352  "extern \"C\" void ${_vtk_client_server_module}_Initialize(vtkClientServerInterpreter*);\n")
353  string(APPEND _vtk_client_server_calls
354  " ${_vtk_client_server_module}_Initialize(csi);\n")
355  endforeach ()
356 
357  set(_vtk_client_server_all_modules_include_content
358  "#ifndef ${_vtk_client_server_TARGET}_h
359 #define ${_vtk_client_server_TARGET}_h
360 
361 #include \"vtkClientServerInterpreter.h\"
362 
363 ${_vtk_client_server_declarations}
364 void ${_vtk_client_server_FUNCTION_NAME}(vtkClientServerInterpreter* csi)
365 {
366  (void)csi;
367 ${_vtk_client_server_calls}}
368 
369 #endif\n")
370 
371  file(GENERATE
372  OUTPUT "${_vtk_client_server_all_modules_include_file}"
373  CONTENT "${_vtk_client_server_all_modules_include_content}")
374 
375  target_link_libraries("${_vtk_client_server_TARGET}"
376  INTERFACE
377  ${_vtk_client_server_all_modules})
378 
379  set(_vtk_client_server_export)
380  if (_vtk_client_server_INSTALL_EXPORT)
381  list(APPEND _vtk_client_server_export
382  EXPORT "${_vtk_client_server_INSTALL_EXPORT}")
383  endif ()
384 
385  install(
386  TARGETS "${_vtk_client_server_TARGET}"
387  ${_vtk_client_server_export}
388  COMPONENT "${_vtk_client_server_COMPONENT}"
389  ARCHIVE DESTINATION "${_vtk_client_server_DESTINATION}")
390  endif ()
391 endfunction ()
392 
393 #[==[.md
394 ## Excluding a module from wrapping
395 
396 Some modules should not be wrapped using client server bindings. Since this is
397 independent of general wrapping facilities, an additional property is used to
398 check. This may be set using the `vtk_module_client_server_exclude` function.
399 
400 ```
402  [MODULE <module>])
403 ```
404 
405 The `MODULE` defaults to the module currently being built. If a module is not
406 being built when this function is called, it must be provided.
407 #]==]
409  cmake_parse_arguments(_vtk_client_server_exclude
410  ""
411  "MODULE"
412  ""
413  ${ARGN})
414 
415  if (_vtk_client_server_exclude_UNPARSED_ARGUMENTS)
416  message(FATAL_ERROR
417  "Unparsed arguments for vtk_module_wrap_client_server_exclude: "
418  "${_vtk_client_server_exclude_UNPARSED_ARGUMENTS}")
419  endif ()
420 
421  if (NOT DEFINED _vtk_client_server_exclude_MODULE)
422  if (NOT DEFINED _vtk_build_module)
423  message(FATAL_ERROR
424  "The `MODULE` argument must be provided outside of a module build.")
425  endif ()
426  set(_vtk_client_server_exclude_MODULE "${_vtk_build_module}")
427  endif ()
428 
429  _vtk_module_set_module_property("${_vtk_client_server_exclude_MODULE}"
430  PROPERTY "client_server_exclude"
431  VALUE 1)
432 endfunction ()
433 
434 cmake_policy(POP)
order
function _vtk_module_get_module_property(module)
Get a module property.
EXPORT
function vtk_module_client_server_exclude()
.md Excluding a module from wrapping
function _vtk_module_set_module_property(module)
Set a module property.