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