1 ###########################################################################
5 # Copyright (c) Kitware Inc.
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
11 # http://www.apache.org/licenses/LICENSE-2.0.txt
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.
19 ###########################################################################
23 # CTK/CMake/ctkMacroParseArguments.cmake
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
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_")
40 set(_modinit_prefix "init")
42 if("${CMAKE_C_COMPILER_ID}" STREQUAL "MSVC")
43 set_target_properties(${_target} PROPERTIES LINK_FLAGS
44 "/EXPORT:${_modinit_prefix}${_target}"
46 elseif("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU")
48 ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/${_target}-version-script.map
50 file(WRITE ${_script_path}
51 "{global: ${_modinit_prefix}${_target}; local: *; };"
53 set_property(TARGET ${_target} APPEND_STRING PROPERTY LINK_FLAGS
54 " -Wl,--version-script=${_script_path}"
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"
68 if(NOT DEFINED MY_TARGET)
69 message(FATAL_ERROR "NAME is mandatory")
71 if(NOT DEFINED MY_WRAPPER_LIBRARY_TYPE OR "${MY_WRAPPER_LIBRARY_TYPE}" STREQUAL "SHARED")
72 set(MY_WRAPPER_LIBRARY_TYPE "MODULE")
75 if(NOT DEFINED MY_NAMESPACE)
76 set(MY_NAMESPACE "org.commontk")
78 foreach(type RUNTIME LIBRARY ARCHIVE)
79 if(NOT DEFINED MY_${type}_OUTPUT_DIRECTORY)
80 set(MY_${type}_OUTPUT_DIRECTORY ${CMAKE_${type}_OUTPUT_DIRECTORY})
83 if(NOT DEFINED MY_INSTALL_BIN_DIR)
84 set(MY_INSTALL_BIN_DIR ${CTK_INSTALL_BIN_DIR})
86 if(NOT DEFINED MY_INSTALL_LIB_DIR)
87 set(MY_INSTALL_LIB_DIR ${CTK_INSTALL_LIB_DIR})
91 set(lib_name ${MY_TARGET})
95 ${CMAKE_CURRENT_SOURCE_DIR}
96 ${CMAKE_CURRENT_BINARY_DIR}
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})
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)
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)
118 message(STATUS "${_msg} - ${_status}")
119 #message("path/to/DECORATOR_HEADER:${CMAKE_CURRENT_SOURCE_DIR}/${DECORATOR_HEADER}")
121 set(KIT_PYTHONQT_SRCS) # Clear variable
122 ctkMacroWrapPythonQt(${MY_NAMESPACE} ${lib_name}
123 KIT_PYTHONQT_SRCS "${MY_SRCS}" FALSE ${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})
129 QT4_WRAP_CPP(KIT_PYTHONQT_SRCS ${DECORATOR_HEADER} OPTIONS -f${DECORATOR_HEADER})
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")
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
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")
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}"
157 # Set labels associated with the target.
158 set_target_properties(${lib_name}PythonQt PROPERTIES LABELS ${lib_name})
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)
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)