CTK  0.1.0
The Common Toolkit is a community effort to provide support code for medical image analysis, surgical navigation, and related projects.
ctkMacroBuildLibWrapper.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 # Depends on:
23 # CTK/CMake/ctkMacroParseArguments.cmake
24 #
25 
26 
27 #! When CTK is built as shared library, the following macro builds a python module
28 #! associated with the generated PythonQt wrappers. When loaded, it will
29 #! dynamically loads both the (1) generated decorators and the (2) hand written one.
30 #! On the other hand, when CTK is built statically, it creates a
31 #! static library providing a initialization function that will allow to load
32 #! both (1) and (2).
33 
34 # Function copied from https://github.com/scikit-build/scikit-build/pull/299
35 # XXX Update this CMake module to use function from scikit-build to build the wrapper
36 function(_ctk_set_python_extension_symbol_visibility _target)
37  if(PYTHON_VERSION_MAJOR VERSION_GREATER 2)
38  set(_modinit_prefix "PyInit_")
39  else()
40  set(_modinit_prefix "init")
41  endif()
42  if("${CMAKE_C_COMPILER_ID}" STREQUAL "MSVC")
43  set_target_properties(${_target} PROPERTIES LINK_FLAGS
44  "/EXPORT:${_modinit_prefix}${_target}"
45  )
46  elseif("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU")
47  set(_script_path
48  ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/${_target}-version-script.map
49  )
50  file(WRITE ${_script_path}
51  "{global: ${_modinit_prefix}${_target}; local: *; };"
52  )
53  set_property(TARGET ${_target} APPEND_STRING PROPERTY LINK_FLAGS
54  " -Wl,--version-script=${_script_path}"
55  )
56  endif()
57 endfunction()
58 
59 #! \ingroup CMakeAPI
60 macro(ctkMacroBuildLibWrapper)
61  ctkMacroParseArguments(MY
62  "NAMESPACE;TARGET;SRCS;WRAPPER_LIBRARY_TYPE;ARCHIVE_OUTPUT_DIRECTORY;LIBRARY_OUTPUT_DIRECTORY;RUNTIME_OUTPUT_DIRECTORY;INSTALL_BIN_DIR;INSTALL_LIB_DIR"
63  "NO_INSTALL"
64  ${ARGN}
65  )
66 
67  # Sanity checks
68  if(NOT DEFINED MY_TARGET)
69  message(FATAL_ERROR "NAME is mandatory")
70  endif()
71  if(NOT DEFINED MY_WRAPPER_LIBRARY_TYPE OR "${MY_WRAPPER_LIBRARY_TYPE}" STREQUAL "SHARED")
72  set(MY_WRAPPER_LIBRARY_TYPE "MODULE")
73  endif()
74 
75  if(NOT DEFINED MY_NAMESPACE)
76  set(MY_NAMESPACE "org.commontk")
77  endif()
78  foreach(type RUNTIME LIBRARY ARCHIVE)
79  if(NOT DEFINED MY_${type}_OUTPUT_DIRECTORY)
80  set(MY_${type}_OUTPUT_DIRECTORY ${CMAKE_${type}_OUTPUT_DIRECTORY})
81  endif()
82  endforeach()
83  if(NOT DEFINED MY_INSTALL_BIN_DIR)
84  set(MY_INSTALL_BIN_DIR ${CTK_INSTALL_BIN_DIR})
85  endif()
86  if(NOT DEFINED MY_INSTALL_LIB_DIR)
87  set(MY_INSTALL_LIB_DIR ${CTK_INSTALL_LIB_DIR})
88  endif()
89 
90  # Define library name
91  set(lib_name ${MY_TARGET})
92 
93  # Include dirs
94  set(my_includes
95  ${CMAKE_CURRENT_SOURCE_DIR}
96  ${CMAKE_CURRENT_BINARY_DIR}
97  )
98 
99  # Since the PythonQt decorator depends on PythonQt, Python and VTK, let's link against
100  # these ones to avoid complaints of MSVC
101  # Note: "LINK_DIRECTORIES" has to be invoked before "ADD_LIBRARY"
102  set(my_EXTRA_PYTHON_LIBRARIES ${PYTHON_LIBRARY} ${PYTHONQT_LIBRARIES})
103 
104  # Does a header having the expected filename exists ?
105  string(REGEX REPLACE "^CTK" "ctk" lib_name_lc_ctk ${lib_name})
106  set(DECORATOR_HEADER ${lib_name_lc_ctk}PythonQtDecorators.h)
107  set(HAS_DECORATOR FALSE)
108 
109  set(_msg "Looking for decorator header ${DECORATOR_HEADER}")
110  message(STATUS "${_msg}")
111  set(_status "Not found")
112  if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${DECORATOR_HEADER})
113  set(HAS_DECORATOR TRUE)
114  set(DECORATOR_HEADER ${DECORATOR_HEADER})
115  set_source_files_properties(${DECORATOR_HEADER} WRAP_EXCLUDE)
116  set(_status "Found")
117  endif()
118  message(STATUS "${_msg} - ${_status}")
119  #message("path/to/DECORATOR_HEADER:${CMAKE_CURRENT_SOURCE_DIR}/${DECORATOR_HEADER}")
120 
121  set(KIT_PYTHONQT_SRCS) # Clear variable
122  ctkMacroWrapPythonQt(${MY_NAMESPACE} ${lib_name}
123  KIT_PYTHONQT_SRCS "${MY_SRCS}" FALSE ${HAS_DECORATOR})
124  if(HAS_DECORATOR)
125  list(APPEND KIT_PYTHONQT_SRCS ${DECORATOR_HEADER})
126  if (CTK_QT_VERSION VERSION_GREATER "4")
127  qt5_wrap_cpp(KIT_PYTHONQT_SRCS ${DECORATOR_HEADER} OPTIONS -f${DECORATOR_HEADER})
128  else()
129  QT4_WRAP_CPP(KIT_PYTHONQT_SRCS ${DECORATOR_HEADER} OPTIONS -f${DECORATOR_HEADER})
130  endif()
131  endif()
132  add_library(${lib_name}PythonQt ${MY_WRAPPER_LIBRARY_TYPE} ${KIT_PYTHONQT_SRCS})
133  target_link_libraries(${lib_name}PythonQt ${lib_name} ${my_EXTRA_PYTHON_LIBRARIES})
134  if(MY_WRAPPER_LIBRARY_TYPE STREQUAL "STATIC")
135  if(CMAKE_SIZEOF_VOID_P EQUAL 8) # 64-bit
136  set_target_properties(${lib_name}PythonQt PROPERTIES COMPILE_FLAGS "-fPIC")
137  endif()
138  endif()
139  if(MY_WRAPPER_LIBRARY_TYPE STREQUAL "MODULE")
140  # Make sure that no prefix is set on the library
141  set_target_properties(${lib_name}PythonQt PROPERTIES PREFIX "")
142  # Python extension modules on Windows must have the extension ".pyd"
143  # instead of ".dll" as of Python 2.5. Older python versions do support
144  # this suffix.
145  # See http://docs.python.org/faq/windows.html#is-a-pyd-file-the-same-as-a-dll
146  if(WIN32 AND NOT CYGWIN)
147  set_target_properties(${lib_name}PythonQt PROPERTIES SUFFIX ".pyd")
148  endif()
149  endif()
150  _ctk_set_python_extension_symbol_visibility(${lib_name}PythonQt)
151  set_target_properties(${lib_name}PythonQt PROPERTIES
152  RUNTIME_OUTPUT_DIRECTORY "${MY_RUNTIME_OUTPUT_DIRECTORY}"
153  LIBRARY_OUTPUT_DIRECTORY "${MY_LIBRARY_OUTPUT_DIRECTORY}"
154  ARCHIVE_OUTPUT_DIRECTORY "${MY_ARCHIVE_OUTPUT_DIRECTORY}"
155  )
156 
157  # Set labels associated with the target.
158  set_target_properties(${lib_name}PythonQt PROPERTIES LABELS ${lib_name})
159 
160  # Update list of libraries wrapped with PythonQt
161  set(CTK_WRAPPED_LIBRARIES_PYTHONQT
162  ${CTK_WRAPPED_LIBRARIES_PYTHONQT} ${lib_name}
163  CACHE INTERNAL "CTK libraries wrapped using PythonQt" FORCE)
164 
165  # Install rules
166  if(NOT MY_NO_INSTALL AND MY_WRAPPER_LIBRARY_TYPE STREQUAL "MODULE")
167  install(TARGETS ${lib_name}PythonQt
168  RUNTIME DESTINATION ${MY_INSTALL_LIB_DIR} COMPONENT RuntimePlugins
169  LIBRARY DESTINATION ${MY_INSTALL_LIB_DIR} COMPONENT RuntimePlugins
170  ARCHIVE DESTINATION ${MY_INSTALL_LIB_DIR} COMPONENT Development)
171  endif()
172 
173 endmacro()
174 
175