|
@@ -23,18 +23,13 @@
|
|
#
|
|
#
|
|
|
|
|
|
#
|
|
#
|
|
-# Depends on:
|
|
|
|
-# CTK/CMake/ctkMacroWrapPythonQt.cmake
|
|
|
|
-#
|
|
|
|
-
|
|
|
|
-#
|
|
|
|
# This script should be invoked either as a CUSTOM_COMMAND
|
|
# This script should be invoked either as a CUSTOM_COMMAND
|
|
# or from the command line using the following syntax:
|
|
# or from the command line using the following syntax:
|
|
#
|
|
#
|
|
-# cmake -DWRAPPING_NAMESPACE:STRING=org.commontk -DTARGET:STRING=MyLib
|
|
|
|
|
|
+# cmake -DWRAPPING_SCRIPT:FILEPATH=/path/to/ctkWrapPythonQt.py
|
|
|
|
+# -DWRAPPING_NAMESPACE:STRING=org.commontk -DTARGET:STRING=MyLib
|
|
# -DSOURCES:STRING="file1^^file2"
|
|
# -DSOURCES:STRING="file1^^file2"
|
|
-# -DWRAP_INT_DIR:STRING=subir/subir/
|
|
|
|
-# -DOUTPUT_DIR:PATH=/path -DQT_QMAKE_EXECUTABLE:PATH=/path/to/qt/qmake
|
|
|
|
|
|
+# -DOUTPUT_DIR:PATH=/path
|
|
# -DPYTHON_EXECUTABLE:FILEPATH=/path/to/python
|
|
# -DPYTHON_EXECUTABLE:FILEPATH=/path/to/python
|
|
# -DPYTHON_LIBRARY_PATH:PATH=/path/to/pythonlib
|
|
# -DPYTHON_LIBRARY_PATH:PATH=/path/to/pythonlib
|
|
# -DHAS_DECORATOR:BOOL=True
|
|
# -DHAS_DECORATOR:BOOL=True
|
|
@@ -47,221 +42,63 @@
|
|
# It will contain the list of class and the constructor signature that will be wrapped.
|
|
# It will contain the list of class and the constructor signature that will be wrapped.
|
|
#
|
|
#
|
|
|
|
|
|
-set(verbose 0)
|
|
|
|
-
|
|
|
|
-#
|
|
|
|
-# Convenient function allowing to log the reason why a given class hasn't been wrapped
|
|
|
|
-# If verbose=1, it will also be displayed on the standard output
|
|
|
|
-#
|
|
|
|
-function(log msg)
|
|
|
|
- if(verbose)
|
|
|
|
- message(${msg})
|
|
|
|
- endif()
|
|
|
|
- file(APPEND "${CMAKE_CURRENT_BINARY_DIR}/ctkScriptWrapPythonQt_Light_log.txt" "${msg}\n")
|
|
|
|
-endfunction()
|
|
|
|
-
|
|
|
|
-#
|
|
|
|
-# Convenient function allowing to invoke re.search(regex, string) using the given interpreter.
|
|
|
|
-# Note that is_matching will be set to True if there is a match
|
|
|
|
-#
|
|
|
|
-function(reSearchFile python_exe python_library_path regex file is_matching)
|
|
|
|
-
|
|
|
|
- set(python_cmd "import re\; f = open('${file}', 'r')\;
|
|
|
|
-res = re.search\(\"${regex}\", f.read(), re.MULTILINE\)\;
|
|
|
|
-if res == None: print \"FALSE\"
|
|
|
|
-else: print \"TRUE\"
|
|
|
|
-")
|
|
|
|
- #message("python_cmd: ${python_cmd}")
|
|
|
|
-
|
|
|
|
- if(WIN32)
|
|
|
|
- set(ENV{PATH} ${python_library_path};$ENV{PATH})
|
|
|
|
- elseif(APPLE)
|
|
|
|
- set(ENV{DYLD_LIBRARY_PATH} ${python_library_path}:$ENV{DYLD_LIBRARY_PATH})
|
|
|
|
- else()
|
|
|
|
- set(ENV{LD_LIBRARY_PATH} ${python_library_path}:$ENV{LD_LIBRARY_PATH})
|
|
|
|
- endif()
|
|
|
|
-
|
|
|
|
- execute_process(
|
|
|
|
- COMMAND ${python_exe} -c ${python_cmd};
|
|
|
|
- RESULT_VARIABLE result
|
|
|
|
- OUTPUT_VARIABLE output
|
|
|
|
- ERROR_VARIABLE error
|
|
|
|
- OUTPUT_STRIP_TRAILING_WHITESPACE
|
|
|
|
- )
|
|
|
|
-
|
|
|
|
- if(result)
|
|
|
|
- message(FATAL_ERROR "reSearchFile - Problem with regex: ${regex}\n${error}")
|
|
|
|
- endif()
|
|
|
|
- #message(${output})
|
|
|
|
- set(is_matching ${output} PARENT_SCOPE)
|
|
|
|
-
|
|
|
|
-endfunction()
|
|
|
|
-
|
|
|
|
-if(NOT DEFINED CMAKE_CURRENT_LIST_DIR)
|
|
|
|
- get_filename_component(CMAKE_CURRENT_LIST_DIR ${CMAKE_CURRENT_LIST_FILE} PATH)
|
|
|
|
-endif()
|
|
|
|
-if(NOT DEFINED CMAKE_CURRENT_LIST_FILENAME)
|
|
|
|
- get_filename_component(CMAKE_CURRENT_LIST_FILENAME ${CMAKE_CURRENT_LIST_FILE} NAME)
|
|
|
|
-endif()
|
|
|
|
-
|
|
|
|
# Check for non-defined var
|
|
# Check for non-defined var
|
|
-foreach(var WRAPPING_NAMESPACE TARGET SOURCES WRAP_INT_DIR HAS_DECORATOR)
|
|
|
|
|
|
+foreach(var WRAPPING_NAMESPACE TARGET SOURCES HAS_DECORATOR)
|
|
if(NOT DEFINED ${var})
|
|
if(NOT DEFINED ${var})
|
|
message(FATAL_ERROR "${var} not specified when calling ctkScriptWrapPythonQt")
|
|
message(FATAL_ERROR "${var} not specified when calling ctkScriptWrapPythonQt")
|
|
endif()
|
|
endif()
|
|
endforeach()
|
|
endforeach()
|
|
|
|
|
|
# Check for non-existing ${var}
|
|
# Check for non-existing ${var}
|
|
-foreach(var QT_QMAKE_EXECUTABLE OUTPUT_DIR PYTHON_EXECUTABLE PYTHON_LIBRARY_PATH)
|
|
|
|
|
|
+foreach(var WRAPPING_SCRIPT OUTPUT_DIR PYTHON_EXECUTABLE PYTHON_LIBRARY_PATH)
|
|
if(NOT EXISTS ${${var}})
|
|
if(NOT EXISTS ${${var}})
|
|
message(FATAL_ERROR "Failed to find ${var}=\"${${var}}\" when calling ctkScriptWrapPythonQt")
|
|
message(FATAL_ERROR "Failed to find ${var}=\"${${var}}\" when calling ctkScriptWrapPythonQt")
|
|
endif()
|
|
endif()
|
|
endforeach()
|
|
endforeach()
|
|
|
|
|
|
-# Clear log file
|
|
|
|
-file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/ctkScriptWrapPythonQt_Light_log.txt" "")
|
|
|
|
-
|
|
|
|
-# Convert wrapping namespace to subdir
|
|
|
|
-string(REPLACE "." "_" WRAPPING_NAMESPACE_UNDERSCORE ${WRAPPING_NAMESPACE})
|
|
|
|
-
|
|
|
|
# Convert ^^ separated string to list
|
|
# Convert ^^ separated string to list
|
|
string(REPLACE "^^" ";" SOURCES "${SOURCES}")
|
|
string(REPLACE "^^" ";" SOURCES "${SOURCES}")
|
|
|
|
|
|
-foreach(FILE ${SOURCES})
|
|
|
|
-
|
|
|
|
- # what is the filename without the extension
|
|
|
|
- get_filename_component(TMP_FILENAME ${FILE} NAME_WE)
|
|
|
|
-
|
|
|
|
- set(includes
|
|
|
|
- "${includes}\n#include \"${TMP_FILENAME}.h\"")
|
|
|
|
-
|
|
|
|
- # Extract classname - NOTE: We assume the filename matches the associated class
|
|
|
|
- set(className ${TMP_FILENAME})
|
|
|
|
- #message(STATUS "FILE:${FILE}, className:${className}")
|
|
|
|
-
|
|
|
|
- # Extract parent classname
|
|
|
|
- set(parentClassName)
|
|
|
|
-
|
|
|
|
- if("${parentClassName}" STREQUAL "")
|
|
|
|
- # Does constructor signature is of the form: myclass()
|
|
|
|
- set(regex "[^~]${className}[\\s\\n]*\\([\\s\\n]*\\)")
|
|
|
|
- reSearchfile(${PYTHON_EXECUTABLE} ${PYTHON_LIBRARY_PATH} ${regex} ${FILE} is_matching)
|
|
|
|
- if(is_matching)
|
|
|
|
- set(parentClassName "No")
|
|
|
|
- log("${TMP_FILENAME} - constructor of the form: ${className}\(\)")
|
|
|
|
- endif()
|
|
|
|
- endif()
|
|
|
|
-
|
|
|
|
- if("${parentClassName}" STREQUAL "")
|
|
|
|
- # Does constructor signature is of the form: myclass(QObject * parent ...)
|
|
|
|
- set(regex "${className}[\\s\\n]*\\([\\s\\n]*QObject[\\s\\n]*\\*[\\s\\n]*\\w+[\\s\\n]*(\\=[\\s\\n]*(0|NULL)|,.*\\=.*\\)|\\))")
|
|
|
|
- reSearchfile(${PYTHON_EXECUTABLE} ${PYTHON_LIBRARY_PATH} ${regex} ${FILE} is_matching)
|
|
|
|
- if(is_matching)
|
|
|
|
- set(parentClassName "QObject")
|
|
|
|
- log("${TMP_FILENAME} - constructor of the form: ${className}\(QObject * parent ... \)")
|
|
|
|
- endif()
|
|
|
|
- endif()
|
|
|
|
-
|
|
|
|
- if("${parentClassName}" STREQUAL "")
|
|
|
|
- # Does constructor signature is of the form: myclass(QWidget * parent ...)
|
|
|
|
- set(regex "${className}[\\s\\n]*\\([\\s\\n]*QWidget[\\s\\n]*\\*[\\s\\n]*\\w+[\\s\\n]*(\\=[\\s\\n]*(0|NULL)|,.*\\=.*\\)|\\))")
|
|
|
|
- reSearchfile(${PYTHON_EXECUTABLE} ${PYTHON_LIBRARY_PATH} ${regex} ${FILE} is_matching)
|
|
|
|
- if(is_matching)
|
|
|
|
- set(parentClassName "QWidget")
|
|
|
|
- log("${TMP_FILENAME} - constructor of the form: ${className}\(QWidget * parent ... \)")
|
|
|
|
- endif()
|
|
|
|
- endif()
|
|
|
|
-
|
|
|
|
- # Generate PythonQtWrapper class
|
|
|
|
- if("${parentClassName}" STREQUAL "QObject" OR "${parentClassName}" STREQUAL "QWidget")
|
|
|
|
-
|
|
|
|
- set(pythonqtWrappers
|
|
|
|
- "${pythonqtWrappers}
|
|
|
|
-//-----------------------------------------------------------------------------
|
|
|
|
-class PythonQtWrapper_${className} : public QObject
|
|
|
|
-{
|
|
|
|
-Q_OBJECT
|
|
|
|
-public:
|
|
|
|
-public Q_SLOTS:
|
|
|
|
- ${className}* new_${className}(${parentClassName}* parent = 0)
|
|
|
|
- {
|
|
|
|
- return new ${className}(parent);
|
|
|
|
- }
|
|
|
|
- void delete_${className}(${className}* obj) { delete obj; }
|
|
|
|
-};
|
|
|
|
-")
|
|
|
|
-
|
|
|
|
- elseif("${parentClassName}" STREQUAL "No")
|
|
|
|
-
|
|
|
|
- set(pythonqtWrappers
|
|
|
|
- "${pythonqtWrappers}
|
|
|
|
-//-----------------------------------------------------------------------------
|
|
|
|
-class Q_DECL_EXPORT PythonQtWrapper_${className} : public QObject
|
|
|
|
-{
|
|
|
|
-Q_OBJECT
|
|
|
|
-public:
|
|
|
|
-public Q_SLOTS:
|
|
|
|
- ${className}* new_${className}()
|
|
|
|
- {
|
|
|
|
- return new ${className}();
|
|
|
|
- }
|
|
|
|
- void delete_${className}(${className}* obj) { delete obj; }
|
|
|
|
-};
|
|
|
|
-")
|
|
|
|
|
|
+if(WIN32)
|
|
|
|
+ set(ENV{PATH} ${PYTHON_LIBRARY_PATH};$ENV{PATH})
|
|
|
|
+elseif(APPLE)
|
|
|
|
+ set(ENV{DYLD_LIBRARY_PATH} ${PYTHON_LIBRARY_PATH}:$ENV{DYLD_LIBRARY_PATH})
|
|
|
|
+else()
|
|
|
|
+ set(ENV{LD_LIBRARY_PATH} ${PYTHON_LIBRARY_PATH}:$ENV{LD_LIBRARY_PATH})
|
|
|
|
+endif()
|
|
|
|
|
|
- else() # Case parentClassName is empty
|
|
|
|
|
|
+set(verbose 0)
|
|
|
|
|
|
- message(WARNING "ctkScriptWrapPythonQt_Light - Problem wrapping ${FILE}")
|
|
|
|
|
|
+set(extra_args)
|
|
|
|
+if(verbose)
|
|
|
|
+ set(extra_args --extra-verbose)
|
|
|
|
+endif()
|
|
|
|
|
|
|
|
+execute_process(
|
|
|
|
+ COMMAND ${PYTHON_EXECUTABLE} ${WRAPPING_SCRIPT}
|
|
|
|
+ --target=${TARGET} --namespace=${WRAPPING_NAMESPACE} --output-dir=${OUTPUT_DIR} ${extra_args}
|
|
|
|
+ ${SOURCES}
|
|
|
|
+ RESULT_VARIABLE result
|
|
|
|
+ OUTPUT_VARIABLE output
|
|
|
|
+ ERROR_VARIABLE error
|
|
|
|
+ OUTPUT_STRIP_TRAILING_WHITESPACE
|
|
|
|
+ )
|
|
|
|
+if(NOT result EQUAL 0)
|
|
|
|
+ message(FATAL_ERROR "Failed to wrap target: ${TARGET}\n${output}\n${error}")
|
|
|
|
+else()
|
|
|
|
+ if(verbose)
|
|
|
|
+ message(${output})
|
|
endif()
|
|
endif()
|
|
|
|
+endif()
|
|
|
|
|
|
- # Generate code allowing to register the class metaobject and its associated "light" wrapper
|
|
|
|
- set(registerclasses "${registerclasses}
|
|
|
|
- PythonQt::self()->registerClass(
|
|
|
|
- &${className}::staticMetaObject, \"${TARGET}\",
|
|
|
|
- PythonQtCreateObject<PythonQtWrapper_${className}>);\n")
|
|
|
|
-
|
|
|
|
-endforeach()
|
|
|
|
-
|
|
|
|
-# Write master include file
|
|
|
|
-file(WRITE ${OUTPUT_DIR}/${WRAP_INT_DIR}${WRAPPING_NAMESPACE_UNDERSCORE}_${TARGET}0.h "//
|
|
|
|
-// File auto-generated by cmake macro ctkScriptWrapPythonQt_Light
|
|
|
|
-//
|
|
|
|
-
|
|
|
|
-#ifndef __${WRAPPING_NAMESPACE_UNDERSCORE}_${TARGET}0_h
|
|
|
|
-#define __${WRAPPING_NAMESPACE_UNDERSCORE}_${TARGET}0_h
|
|
|
|
-
|
|
|
|
-#include <QWidget>
|
|
|
|
-${includes}
|
|
|
|
-${pythonqtWrappers}
|
|
|
|
-#endif
|
|
|
|
-")
|
|
|
|
-
|
|
|
|
-# Write wrapper header
|
|
|
|
-file(WRITE ${OUTPUT_DIR}/${WRAP_INT_DIR}${WRAPPING_NAMESPACE_UNDERSCORE}_${TARGET}_init.cpp "//
|
|
|
|
-// File auto-generated by cmake macro ctkScriptWrapPythonQt_Light
|
|
|
|
-//
|
|
|
|
-
|
|
|
|
-#include <PythonQt.h>
|
|
|
|
-#include \"${WRAPPING_NAMESPACE_UNDERSCORE}_${TARGET}0.h\"
|
|
|
|
-
|
|
|
|
-void PythonQt_init_${WRAPPING_NAMESPACE_UNDERSCORE}_${TARGET}(PyObject* module)
|
|
|
|
-{
|
|
|
|
- Q_UNUSED(module);
|
|
|
|
- ${registerclasses}
|
|
|
|
-}
|
|
|
|
-")
|
|
|
|
|
|
+# Convert wrapping namespace to subdir
|
|
|
|
+string(REPLACE "." "_" WRAPPING_NAMESPACE_UNDERSCORE ${WRAPPING_NAMESPACE})
|
|
|
|
|
|
-# Configure 'ctkMacroWrapPythonQtModuleInit.cpp.in' replacing TARGET and
|
|
|
|
|
|
+# Configure 'ctkMacroWrapPythonQtModuleInit.cpp.in' using TARGET, HAS_DECORATOR and
|
|
# WRAPPING_NAMESPACE_UNDERSCORE.
|
|
# WRAPPING_NAMESPACE_UNDERSCORE.
|
|
configure_file(
|
|
configure_file(
|
|
${CMAKE_CURRENT_LIST_DIR}/ctkMacroWrapPythonQtModuleInit.cpp.in
|
|
${CMAKE_CURRENT_LIST_DIR}/ctkMacroWrapPythonQtModuleInit.cpp.in
|
|
${OUTPUT_DIR}/${WRAP_INT_DIR}${WRAPPING_NAMESPACE_UNDERSCORE}_${TARGET}_module_init.cpp
|
|
${OUTPUT_DIR}/${WRAP_INT_DIR}${WRAPPING_NAMESPACE_UNDERSCORE}_${TARGET}_module_init.cpp
|
|
)
|
|
)
|
|
|
|
|
|
-# Since file(WRITE ) doesn't update the timestamp - Let's touch the files
|
|
|
|
-execute_process(
|
|
|
|
- COMMAND ${CMAKE_COMMAND} -E touch
|
|
|
|
- ${OUTPUT_DIR}/${WRAP_INT_DIR}${WRAPPING_NAMESPACE_UNDERSCORE}_${TARGET}_init.cpp
|
|
|
|
- )
|
|
|
|
|
|
|