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