1#
2# CMake implementation of the Wrap Python command.
3#
4macro(VTK_WRAP_PYTHON2 TARGET SOURCE_LIST_NAME)
5  # convert to the WRAP3 signature
6  vtk_wrap_python3(${TARGET} ${SOURCE_LIST_NAME} "${ARGN}")
7endmacro()
8
9macro(VTK_WRAP_PYTHON3 TARGET SRC_LIST_NAME SOURCES)
10  if(NOT VTK_WRAP_PYTHON_INIT_EXE)
11    if(TARGET vtkWrapPythonInit)
12      set(VTK_WRAP_PYTHON_INIT_EXE vtkWrapPythonInit)
13    else()
14      message(SEND_ERROR
15        "VTK_WRAP_PYTHON_INIT_EXE not specified when calling VTK_WRAP_PYTHON3")
16    endif()
17  endif()
18  if(NOT VTK_WRAP_PYTHON_EXE)
19    if(TARGET vtkWrapPython)
20      set(VTK_WRAP_PYTHON_EXE vtkWrapPython)
21    else()
22      message(SEND_ERROR
23        "VTK_WRAP_PYTHON_EXE not specified when calling VTK_WRAP_PYTHON3")
24    endif()
25  endif()
26
27  # The shell into which nmake.exe executes the custom command has some issues
28  # with mixing quoted and unquoted arguments :( Let's help.
29  if(CMAKE_GENERATOR MATCHES "NMake Makefiles")
30    set(verbatim "")
31    set(quote "\"")
32  else()
33    set(verbatim "VERBATIM")
34    set(quote "")
35  endif()
36
37  # Initialize the custom target counter.
38  if(VTK_WRAP_PYTHON_NEED_CUSTOM_TARGETS)
39    set(VTK_WRAP_PYTHON_CUSTOM_COUNT "")
40    set(VTK_WRAP_PYTHON_CUSTOM_NAME ${TARGET})
41    set(VTK_WRAP_PYTHON_CUSTOM_LIST)
42  endif()
43
44  # start writing the input file for the init file
45  set(VTK_WRAPPER_INIT_DATA "${TARGET}")
46
47  # all the include directories
48  if(VTK_WRAP_INCLUDE_DIRS)
49    set(TMP_INCLUDE_DIRS ${VTK_WRAP_INCLUDE_DIRS})
50  else()
51    set(TMP_INCLUDE_DIRS ${VTK_INCLUDE_DIRS})
52  endif()
53
54  # collect the common wrapper-tool arguments
55  set(_common_args)
56  get_directory_property(_def_list DEFINITION COMPILE_DEFINITIONS)
57  foreach(TMP_DEF ${_def_list})
58    set(_common_args "${_common_args}-D${TMP_DEF}\n")
59  endforeach()
60  foreach(INCLUDE_DIR ${TMP_INCLUDE_DIRS})
61    set(_common_args "${_common_args}-I\"${INCLUDE_DIR}\"\n")
62  endforeach()
63  if(VTK_WRAP_HINTS)
64    set(_common_args "${_common_args}--hints \"${VTK_WRAP_HINTS}\"\n")
65  endif()
66  if(KIT_HIERARCHY_FILE)
67    set(_common_args "${_common_args}--types \"${KIT_HIERARCHY_FILE}\"\n")
68  endif()
69
70  # write wrapper-tool arguments to a file
71  string(STRIP "${_common_args}" CMAKE_CONFIGURABLE_FILE_CONTENT)
72  set(_args_file ${CMAKE_CURRENT_BINARY_DIR}/${TARGET}.args)
73  configure_file(${CMAKE_ROOT}/Modules/CMakeConfigurableFile.in
74                 ${_args_file} @ONLY)
75
76  # for each class
77  foreach(FILE ${SOURCES})
78    # should we wrap the file?
79    get_source_file_property(TMP_WRAP_EXCLUDE ${FILE} WRAP_EXCLUDE)
80    get_source_file_property(TMP_WRAP_SPECIAL ${FILE} WRAP_SPECIAL)
81
82    # if we should wrap it
83    if(TMP_WRAP_SPECIAL OR NOT TMP_WRAP_EXCLUDE)
84
85      # what is the filename without the extension
86      get_filename_component(TMP_FILENAME ${FILE} NAME_WE)
87
88      # the input file might be full path so handle that
89      get_filename_component(TMP_FILEPATH ${FILE} PATH)
90
91      # compute the input filename
92      if(TMP_FILEPATH)
93        set(TMP_INPUT ${TMP_FILEPATH}/${TMP_FILENAME}.h)
94      else()
95        set(TMP_INPUT ${CMAKE_CURRENT_SOURCE_DIR}/${TMP_FILENAME}.h)
96      endif()
97
98      # add the info to the init file
99      set(VTK_WRAPPER_INIT_DATA
100        "${VTK_WRAPPER_INIT_DATA}\n${TMP_FILENAME}")
101
102      # new source file is namePython.cxx, add to resulting list
103      set(${SRC_LIST_NAME} ${${SRC_LIST_NAME}}
104        ${TMP_FILENAME}Python.cxx)
105
106      # add custom command to output
107      add_custom_command(
108        OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${TMP_FILENAME}Python.cxx
109        DEPENDS ${VTK_WRAP_PYTHON_EXE} ${VTK_WRAP_HINTS} ${TMP_INPUT} ${_args_file}
110          ${KIT_HIERARCHY_FILE}
111        COMMAND ${VTK_WRAP_PYTHON_EXE}
112          ARGS
113          "${quote}@${_args_file}${quote}"
114          "-o" "${quote}${CMAKE_CURRENT_BINARY_DIR}/${TMP_FILENAME}Python.cxx${quote}"
115          "${quote}${TMP_INPUT}${quote}"
116        COMMENT "Python Wrapping - generating ${TMP_FILENAME}Python.cxx"
117          ${verbatim}
118        )
119
120      # Add this output to a custom target if needed.
121      if(VTK_WRAP_PYTHON_NEED_CUSTOM_TARGETS)
122        set(VTK_WRAP_PYTHON_CUSTOM_LIST ${VTK_WRAP_PYTHON_CUSTOM_LIST}
123          ${CMAKE_CURRENT_BINARY_DIR}/${TMP_FILENAME}Python.cxx)
124        set(VTK_WRAP_PYTHON_CUSTOM_COUNT ${VTK_WRAP_PYTHON_CUSTOM_COUNT}x)
125        if(VTK_WRAP_PYTHON_CUSTOM_COUNT MATCHES "^${VTK_WRAP_PYTHON_CUSTOM_LIMIT}$")
126          set(VTK_WRAP_PYTHON_CUSTOM_NAME ${VTK_WRAP_PYTHON_CUSTOM_NAME}Hack)
127          add_custom_target(${VTK_WRAP_PYTHON_CUSTOM_NAME}
128            DEPENDS ${VTK_WRAP_PYTHON_CUSTOM_LIST})
129          set(KIT_PYTHON_DEPS ${VTK_WRAP_PYTHON_CUSTOM_NAME})
130          set(VTK_WRAP_PYTHON_CUSTOM_LIST)
131          set(VTK_WRAP_PYTHON_CUSTOM_COUNT)
132        endif()
133      endif()
134    endif()
135  endforeach()
136
137  # finish the data file for the init file
138  configure_file(
139    ${VTK_CMAKE_DIR}/vtkWrapperInit.data.in
140    ${CMAKE_CURRENT_BINARY_DIR}/${TARGET}Init.data
141    @ONLY
142    )
143
144  add_custom_command(
145    OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${TARGET}Init.cxx
146           ${CMAKE_CURRENT_BINARY_DIR}/${TARGET}InitImpl.cxx
147    DEPENDS ${VTK_WRAP_PYTHON_INIT_EXE}
148      ${CMAKE_CURRENT_BINARY_DIR}/${TARGET}Init.data
149    COMMAND ${VTK_WRAP_PYTHON_INIT_EXE}
150    ARGS
151      "${quote}${CMAKE_CURRENT_BINARY_DIR}/${TARGET}Init.data${quote}"
152      "${quote}${CMAKE_CURRENT_BINARY_DIR}/${TARGET}Init.cxx${quote}"
153      "${quote}${CMAKE_CURRENT_BINARY_DIR}/${TARGET}InitImpl.cxx${quote}"
154    COMMENT "Python Wrapping - generating ${TARGET}Init.cxx"
155      ${verbatim}
156    )
157
158  # Create the Init File
159  set(${SRC_LIST_NAME} ${${SRC_LIST_NAME}} ${TARGET}InitImpl.cxx)
160
161endmacro()
162
163if(VTK_WRAP_PYTHON_FIND_LIBS)
164  get_filename_component(_CURRENT_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH)
165  find_package(PythonLibs)
166
167  # Use separate debug/optimized libraries if they are different.
168  if(PYTHON_DEBUG_LIBRARY)
169    if("${PYTHON_DEBUG_LIBRARY}" STREQUAL "${PYTHON_LIBRARY}")
170      set(VTK_PYTHON_LIBRARIES ${PYTHON_LIBRARY})
171    else()
172      set(VTK_PYTHON_LIBRARIES
173        optimized ${PYTHON_LIBRARY}
174        debug ${PYTHON_DEBUG_LIBRARY})
175    endif()
176    set(VTK_WINDOWS_PYTHON_DEBUGGABLE 0)
177    if(WIN32)
178      if(PYTHON_DEBUG_LIBRARY MATCHES "_d")
179        set(VTK_WINDOWS_PYTHON_DEBUGGABLE 1)
180      endif()
181    endif()
182  else()
183    set(VTK_PYTHON_LIBRARIES ${PYTHON_LIBRARY})
184  endif()
185
186  # Some python installations on UNIX need to link to extra libraries
187  # such as zlib (-lz).  It is hard to automatically detect the needed
188  # libraries so instead just give the user an easy way to specify
189  # the libraries.  This should be needed only rarely.  It should
190  # also be moved to the CMake FindPython.cmake module at some point.
191  if(UNIX)
192    if(NOT DEFINED PYTHON_EXTRA_LIBS)
193      set(PYTHON_EXTRA_LIBS "" CACHE STRING
194        "Extra libraries to link when linking to python (such as \"z\" for zlib).  Separate multiple libraries with semicolons.")
195      mark_as_advanced(PYTHON_EXTRA_LIBS)
196    endif()
197  endif()
198
199  # Include any extra libraries for python.
200  set(VTK_PYTHON_LIBRARIES ${VTK_PYTHON_LIBRARIES} ${PYTHON_EXTRA_LIBS})
201endif()
202
203# Determine the location of the supplied header in the include_dirs supplied.
204macro(vtk_find_header header include_dirs full_path)
205  unset(${full_path})
206  foreach(_dir ${include_dirs})
207    if(EXISTS "${_dir}/${header}")
208      set(${full_path} "${_dir}/${header}")
209      break()
210    endif()
211  endforeach()
212endmacro()
213
214# Macro that just takes the name of the module, figure the rest out from there.
215macro(vtk_wrap_python TARGET SRC_LIST_NAME module)
216  if(NOT VTK_WRAP_PYTHON_INIT_EXE)
217    if(TARGET vtkWrapPythonInit)
218      set(VTK_WRAP_PYTHON_INIT_EXE vtkWrapPythonInit)
219    else()
220      message(SEND_ERROR
221        "VTK_WRAP_PYTHON_INIT_EXE not specified when calling VTK_WRAP_PYTHON3")
222    endif()
223  endif()
224  if(NOT VTK_WRAP_PYTHON_EXE)
225    if(TARGET vtkWrapPython)
226      set(VTK_WRAP_PYTHON_EXE vtkWrapPython)
227    else()
228      message(SEND_ERROR
229        "VTK_WRAP_PYTHON_EXE not specified when calling vtk_wrap_python")
230    endif()
231  endif()
232
233  # The shell into which nmake.exe executes the custom command has some issues
234  # with mixing quoted and unquoted arguments :( Let's help.
235  if(CMAKE_GENERATOR MATCHES "NMake Makefiles")
236    set(verbatim "")
237    set(quote "\"")
238  else()
239    set(verbatim "VERBATIM")
240    set(quote "")
241  endif()
242
243  # Initialize the custom target counter.
244  if(VTK_WRAP_PYTHON_NEED_CUSTOM_TARGETS)
245    set(VTK_WRAP_PYTHON_CUSTOM_COUNT "")
246    set(VTK_WRAP_PYTHON_CUSTOM_NAME ${TARGET})
247    set(VTK_WRAP_PYTHON_CUSTOM_LIST)
248  endif()
249
250  # start writing the input file for the init file
251  set(VTK_WRAPPER_INIT_DATA "${TARGET}")
252
253  # all the include directories
254  if(${module}_INCLUDE_DIRS)
255    set(TMP_INCLUDE_DIRS ${${module}_INCLUDE_DIRS})
256  elseif(VTK_WRAP_INCLUDE_DIRS)
257    set(TMP_INCLUDE_DIRS ${VTK_WRAP_INCLUDE_DIRS})
258  else()
259    set(TMP_INCLUDE_DIRS ${VTK_INCLUDE_DIRS})
260  endif()
261  if(EXTRA_PYTHON_INCLUDE_DIRS)
262    list(APPEND TMP_INCLUDE_DIRS ${EXTRA_PYTHON_INCLUDE_DIRS})
263  endif()
264
265  # collect the common wrapper-tool arguments
266  set(_common_args)
267  get_directory_property(_def_list DEFINITION COMPILE_DEFINITIONS)
268  foreach(TMP_DEF ${_def_list})
269    set(_common_args "${_common_args}-D${TMP_DEF}\n")
270  endforeach()
271  foreach(INCLUDE_DIR ${TMP_INCLUDE_DIRS})
272    set(_common_args "${_common_args}-I\"${INCLUDE_DIR}\"\n")
273  endforeach()
274  if(VTK_WRAP_HINTS)
275    set(_common_args "${_common_args}--hints \"${VTK_WRAP_HINTS}\"\n")
276  endif()
277  if(KIT_HIERARCHY_FILE)
278    set(_common_args "${_common_args}--types \"${KIT_HIERARCHY_FILE}\"\n")
279  endif()
280
281  # write wrapper-tool arguments to a file
282  string(STRIP "${_common_args}" CMAKE_CONFIGURABLE_FILE_CONTENT)
283  set(_args_file ${CMAKE_CURRENT_BINARY_DIR}/${TARGET}.args)
284  configure_file(${CMAKE_ROOT}/Modules/CMakeConfigurableFile.in
285                 ${_args_file} @ONLY)
286
287  # Decide what to do for each header.
288  foreach(header ${${module}_HEADERS})
289    # Everything in this block is for headers that will be wrapped.
290    if(${module}_HEADER_${header}_WRAP_SPECIAL OR
291       NOT ${module}_HEADER_${header}_WRAP_EXCLUDE)
292
293      # Find the full path to the header file to be wrapped.
294      vtk_find_header(${header}.h "${${module}_INCLUDE_DIRS}" class_header_path)
295      if(NOT class_header_path)
296        message(FATAL_ERROR "Could not find the ${header} header file.")
297      endif()
298
299      # add the info to the init file
300      set(VTK_WRAPPER_INIT_DATA
301        "${VTK_WRAPPER_INIT_DATA}\n${header}")
302
303      # new source file is namePython.cxx, add to resulting list
304      set(${SRC_LIST_NAME} ${${SRC_LIST_NAME}} ${header}Python.cxx)
305
306      # add custom command to output
307      add_custom_command(
308        OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${header}Python.cxx
309        DEPENDS ${VTK_WRAP_PYTHON_EXE} ${VTK_WRAP_HINTS} ${class_header_path}
310          ${_args_file} ${KIT_HIERARCHY_FILE}
311        COMMAND ${VTK_WRAP_PYTHON_EXE}
312          ARGS
313          "${quote}@${_args_file}${quote}"
314          "-o" "${quote}${CMAKE_CURRENT_BINARY_DIR}/${header}Python.cxx${quote}"
315          "${quote}${class_header_path}${quote}"
316        COMMENT "Python Wrapping - generating ${header}Python.cxx"
317          ${verbatim}
318        )
319
320      # Add this output to a custom target if needed.
321      if(VTK_WRAP_PYTHON_NEED_CUSTOM_TARGETS)
322        set(VTK_WRAP_PYTHON_CUSTOM_LIST ${VTK_WRAP_PYTHON_CUSTOM_LIST}
323          ${CMAKE_CURRENT_BINARY_DIR}/${header}Python.cxx)
324        set(VTK_WRAP_PYTHON_CUSTOM_COUNT ${VTK_WRAP_PYTHON_CUSTOM_COUNT}x)
325        if(VTK_WRAP_PYTHON_CUSTOM_COUNT MATCHES "^${VTK_WRAP_PYTHON_CUSTOM_LIMIT}$")
326          set(VTK_WRAP_PYTHON_CUSTOM_NAME ${VTK_WRAP_PYTHON_CUSTOM_NAME}Hack)
327          add_custom_target(${VTK_WRAP_PYTHON_CUSTOM_NAME}
328            DEPENDS ${VTK_WRAP_PYTHON_CUSTOM_LIST})
329          set(KIT_PYTHON_DEPS ${VTK_WRAP_PYTHON_CUSTOM_NAME})
330          set(VTK_WRAP_PYTHON_CUSTOM_LIST)
331          set(VTK_WRAP_PYTHON_CUSTOM_COUNT)
332        endif()
333      endif()
334    else()
335      message("${header} will not be wrapped.")
336    endif()
337  endforeach()
338
339  # finish the data file for the init file
340  configure_file(
341    ${VTK_CMAKE_DIR}/vtkWrapperInit.data.in
342    ${CMAKE_CURRENT_BINARY_DIR}/${TARGET}Init.data
343    @ONLY
344    )
345
346  add_custom_command(
347    OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${TARGET}Init.cxx
348           ${CMAKE_CURRENT_BINARY_DIR}/${TARGET}InitImpl.cxx
349    DEPENDS ${VTK_WRAP_PYTHON_INIT_EXE}
350      ${CMAKE_CURRENT_BINARY_DIR}/${TARGET}Init.data
351    COMMAND ${VTK_WRAP_PYTHON_INIT_EXE}
352    ARGS
353      "${quote}${CMAKE_CURRENT_BINARY_DIR}/${TARGET}Init.data${quote}"
354      "${quote}${CMAKE_CURRENT_BINARY_DIR}/${TARGET}Init.cxx${quote}"
355      "${quote}${CMAKE_CURRENT_BINARY_DIR}/${TARGET}InitImpl.cxx${quote}"
356    COMMENT "Python Wrapping - generating ${TARGET}Init.cxx"
357      ${verbatim}
358    )
359
360  # Create the Init File
361  set(${SRC_LIST_NAME} ${${SRC_LIST_NAME}} ${TARGET}InitImpl.cxx)
362
363endmacro()
364