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