CTK  0.1.0
The Common Toolkit is a community effort to provide support code for medical image analysis, surgical navigation, and related projects.
ctkMacroWrapPythonQt.cmake
Go to the documentation of this file.
1 ###########################################################################
2 #
3 # Library: CTK
4 #
5 # Copyright (c) Kitware Inc.
6 #
7 # Licensed under the Apache License, Version 2.0 (the "License");
8 # you may not use this file except in compliance with the License.
9 # You may obtain a copy of the License at
10 #
11 # http://www.apache.org/licenses/LICENSE-2.0.txt
12 #
13 # Unless required by applicable law or agreed to in writing, software
14 # distributed under the License is distributed on an "AS IS" BASIS,
15 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 # See the License for the specific language governing permissions and
17 # limitations under the License.
18 #
19 ###########################################################################
20 
21 #
22 # ctkMacroWrapPythonQt
23 #
24 
25 #!
26 #! Depends on:
27 #! PythonQt
28 #! PythonInterp
29 #!
30 
31 #!
32 #! The different parameters are:
33 #!
34 #! WRAPPING_NAMESPACE: Namespace that should contain the library. For example: org.commontk
35 #!
36 #! TARGET ...........: Name of the wrapped library. For example: CTKWidget
37 #!
38 #! SRCS_LIST_NAME ...: Name of the variable that should contain the generated wrapper source.
39 #! For example: KIT_PYTHONQT_SRCS
40 #!
41 #! SOURCES ..........: List of source files that should be wrapped.
42 #!
43 #! HAS_DECORATOR ....: Indicate if a custom PythonQt decorator header is expected.
44 #!
45 
46 #!
47 #! LOG FILE:
48 #! File ctkMacroWrapPythonQt_log.txt will be created in the current directory.
49 #! It will contain the list of file and the reason why a given class hasn't been wrapped.
50 #!
51 
52 set(verbose 0)
53 
54 #! \ingroup CMakeUtilities
55 macro(ctkMacroWrapPythonQt WRAPPING_NAMESPACE TARGET SRCS_LIST_NAME SOURCES IS_WRAP_FULL HAS_DECORATOR)
56 
57  # Sanity check
58  if(IS_WRAP_FULL)
59  message(FATAL_ERROR "IS_WRAP_FULL option is not supported anymore. See https://github.com/commontk/CTK/issues/449")
60  endif()
61 
62  # TODO: this find package seems not to work when called form a superbuild, but the call is needed
63  # in general to find the python interpreter. In CTK, the toplevel CMakeLists.txt does the find
64  # package so this is a no-op. Other uses of this file may need to have this call so it is still enabled.
65  find_package(PythonInterp)
66  if(NOT PYTHONINTERP_FOUND)
67  message(FATAL_ERROR "PYTHON_EXECUTABLE not specified or inexistent when calling ctkMacroWrapPythonQt")
68  endif()
69 
70  set(SOURCES_TO_WRAP)
71 
72  # For each class
73  foreach(FILE ${SOURCES})
74 
75  set(skip_wrapping FALSE)
76 
77  if(NOT skip_wrapping)
78  # Skip wrapping if file is NOT regular header
79  if(NOT ${FILE} MATCHES "^.*\\.[hH]$")
80  set(skip_wrapping TRUE)
81  if(verbose)
82  message("${FILE}: skipping - Not a regular header")
83  endif()
84  endif()
85  endif()
86 
87  if(NOT skip_wrapping)
88  # Skip wrapping if file is a pimpl header
89  if(${FILE} MATCHES "^.*_[pP]\\.[hH]$")
90  set(skip_wrapping TRUE)
91  if(verbose)
92  message("${FILE}: skipping - Pimpl header (*._p.h)")
93  endif()
94  endif()
95  endif()
96 
97  if(NOT skip_wrapping)
98  # Skip wrapping if file should excluded
99  set(skip_wrapping TRUE)
100  get_source_file_property(TMP_WRAP_EXCLUDE ${FILE} WRAP_EXCLUDE)
101  if(NOT TMP_WRAP_EXCLUDE)
102  set(skip_wrapping FALSE)
103  endif()
104  if(skip_wrapping)
105  if(verbose)
106  message("${FILE}: skipping - WRAP_EXCLUDE")
107  endif()
108  endif()
109  endif()
110 
111  # if we should wrap it
112  if(NOT skip_wrapping)
113 
114  # compute the input filename
115  if(IS_ABSOLUTE ${FILE})
116  set(TMP_INPUT ${FILE})
117  else()
118  set(TMP_INPUT ${CMAKE_CURRENT_SOURCE_DIR}/${FILE})
119  endif()
120 
121  list(APPEND SOURCES_TO_WRAP ${TMP_INPUT})
122  endif()
123  endforeach()
124 
125  # Convert wrapping namespace to subdir
126  string(REPLACE "." "_" WRAPPING_NAMESPACE_UNDERSCORE ${WRAPPING_NAMESPACE})
127 
128  # Define wrap type and wrap intermediate directory
129  set(wrap_int_dir generated_cpp/${WRAPPING_NAMESPACE_UNDERSCORE}_${TARGET}/)
130 
131  set(wrapper_module_init_cpp_filename ${wrap_int_dir}${WRAPPING_NAMESPACE_UNDERSCORE}_${TARGET}_module_init.cpp)
132 
133  # Configure 'ctkMacroWrapPythonQtModuleInit.cpp.in' using TARGET, HAS_DECORATOR and
134  # WRAPPING_NAMESPACE_UNDERSCORE.
135  set(TARGET_CONFIG ${TARGET})
136  configure_file(
137  ${CTK_CMAKE_DIR}/ctkMacroWrapPythonQtModuleInit.cpp.in
138  ${wrapper_module_init_cpp_filename}
139  @ONLY
140  )
141 
142  set(extra_args)
143  if(verbose)
144  set(extra_args --extra-verbose)
145  endif()
146 
147  # Custom command allow to generate ${WRAPPING_NAMESPACE_UNDERSCORE}_${TARGET}_init.cpp and
148  # associated wrappers ${WRAPPING_NAMESPACE_UNDERSCORE}_${TARGET}.cpp
149  set(wrapper_init_cpp_filename ${wrap_int_dir}${WRAPPING_NAMESPACE_UNDERSCORE}_${TARGET}_init.cpp)
150  set(wrapper_h_filename ${wrap_int_dir}${WRAPPING_NAMESPACE_UNDERSCORE}_${TARGET}.h)
151  add_custom_command(
152  OUTPUT
153  ${wrapper_init_cpp_filename}
154  ${wrapper_h_filename}
155  DEPENDS
156  ${SOURCES_TO_WRAP}
157  ${CTK_CMAKE_DIR}/ctkWrapPythonQt.py
158  COMMAND ${PYTHON_EXECUTABLE} ${CTK_CMAKE_DIR}/ctkWrapPythonQt.py
159  --target=${TARGET}
160  --namespace=${WRAPPING_NAMESPACE}
161  --output-dir=${CMAKE_CURRENT_BINARY_DIR}/${wrap_int_dir} ${extra_args}
162  ${SOURCES_TO_WRAP}
163  COMMENT "PythonQt Wrapping - Generating ${wrapper_init_cpp_filename}"
164  VERBATIM
165  )
166  if(CTK_QT_VERSION VERSION_GREATER "4")
167  qt5_wrap_cpp(${TARGET}_MOC_CXX ${CMAKE_CURRENT_BINARY_DIR}/${wrapper_h_filename})
168  else()
169  QT4_WRAP_CPP(${TARGET}_MOC_CXX ${CMAKE_CURRENT_BINARY_DIR}/${wrapper_h_filename})
170  endif()
171 
172  # The following files are generated
173  set_source_files_properties(
174  ${wrapper_init_cpp_filename}
175  ${wrapper_h_filename}
176  ${wrapper_module_init_cpp_filename}
177  PROPERTIES GENERATED TRUE)
178 
179  # Create the Init File
180  set(${SRCS_LIST_NAME}
181  ${${SRCS_LIST_NAME}}
182  ${wrapper_init_cpp_filename}
183  ${wrapper_module_init_cpp_filename}
184  ${${TARGET}_MOC_CXX}
185  )
186 
187  #
188  # Let's include the headers associated with PythonQt
189  #
190  find_package(PythonQt)
191  if(NOT PYTHONQT_FOUND)
192  message(FATAL_ERROR "error: PythonQt package is required to build ${TARGET}PythonQt")
193  endif()
194  include_directories(${PYTHON_INCLUDE_DIRS} ${PYTHONQT_INCLUDE_DIR})
195 
196 endmacro()
197