瀏覽代碼

Merge branch '449-speedup-cmake-config-and-generation'

* 449-speedup-cmake-config-and-generation:
  Fix python script compilation removing inputs from custom target deps. See #449
  Re-create python compile script only if needed and fix dependency. See #449
  Simplify QT4_GENERATE_MOCS. See #449
  Optimize QT4_GENERATE_MOCS macro getting moc flags only when needed
  Do not log PythonQt wrapping output. See #449
  Remove Light wrapping CMake script and directly invoke python executable
  Simplify moc'ing of generated PythonQt wrapper. See #449
  Simplify how path of generated file are specified. See #449
  Configure module init file at configure times. See #449
  Optimize ctkMacroWrapPythonQt creating required source list in a single loop.
  Move all PythonQt wrapping code into one script. See #449
  Remove setting of INCLUDE_DIRS variable specific to PythonQtGenerator
  Remove 'CTK_WRAP_PYTHONQT_FULL' obsolete option. See #449
  Remove code referencing unexisting variable. See #449
Jean-Christophe Fillion-Robin 11 年之前
父節點
當前提交
909073a042
共有 33 個文件被更改,包括 429 次插入983 次删除
  1. 2 3
      Applications/ctkSimplePythonShell/CMakeLists.txt
  2. 3 3
      Applications/ctkSimplePythonShell/ctkSimplePythonManager.cpp.in
  3. 0 1
      Applications/ctkSimplePythonShell/ctkSimplePythonShellConfigure.h.in
  4. 1 4
      CMake/ctkMacroBuildLibWrapper.cmake
  5. 6 105
      CMake/ctkMacroCompilePythonScript.cmake
  6. 10 5
      CMake/ctkMacroGenerateMocs.cmake
  7. 47 219
      CMake/ctkMacroWrapPythonQt.cmake
  8. 14 14
      CMake/ctkMacroWrapPythonQtModuleInit.cpp.in
  9. 0 120
      CMake/ctkScriptMocPythonQtWrapper.cmake
  10. 0 153
      CMake/ctkScriptWrapPythonQt_Full.cmake
  11. 0 267
      CMake/ctkScriptWrapPythonQt_Light.cmake
  12. 228 0
      CMake/ctkWrapPythonQt.py
  13. 97 0
      CMake/ctk_compile_python_scripts.cmake.in
  14. 0 59
      CMakeExternals/PythonQtGenerator.cmake
  15. 3 12
      CMakeLists.txt
  16. 1 1
      Libs/CommandLineModules/Backend/FunctionPointer/CMakeLists.txt
  17. 1 1
      Libs/CommandLineModules/Backend/LocalProcess/CMakeLists.txt
  18. 1 1
      Libs/CommandLineModules/Backend/XMLChecker/CMakeLists.txt
  19. 1 1
      Libs/CommandLineModules/Core/CMakeLists.txt
  20. 1 1
      Libs/CommandLineModules/Frontend/QtGui/CMakeLists.txt
  21. 1 1
      Libs/CommandLineModules/Frontend/QtWebKit/CMakeLists.txt
  22. 1 1
      Libs/Core/CMakeLists.txt
  23. 1 1
      Libs/DICOM/Core/CMakeLists.txt
  24. 1 1
      Libs/DICOM/Widgets/CMakeLists.txt
  25. 1 1
      Libs/ImageProcessing/ITK/Core/CMakeLists.txt
  26. 1 1
      Libs/PluginFramework/CMakeLists.txt
  27. 1 1
      Libs/QtTesting/CMakeLists.txt
  28. 1 1
      Libs/Scripting/Python/Core/Python/CMakeLists.txt
  29. 1 1
      Libs/Scripting/Python/Widgets/CMakeLists.txt
  30. 1 1
      Libs/Visualization/VTK/Core/CMakeLists.txt
  31. 1 1
      Libs/Visualization/VTK/Widgets/CMakeLists.txt
  32. 1 1
      Libs/Visualization/XIP/CMakeLists.txt
  33. 1 1
      Libs/Widgets/CMakeLists.txt

+ 2 - 3
Applications/ctkSimplePythonShell/CMakeLists.txt

@@ -81,7 +81,7 @@ if(CTK_LIB_Scripting/Python/Core AND CTK_LIB_Scripting/Python/Core_PYTHONQT_USE_
     )
 endif()
 
-# Configure file will be configured using CTK_WRAP_PYTHONQT_{LIGHT, FULL} and
+# Configure file will be configured using CTK_WRAP_PYTHONQT_LIGHT and
 # CTK_BUILD_SHARED_LIBS variables
 configure_file(
   ctkSimplePythonShellConfigure.h.in
@@ -90,8 +90,7 @@ configure_file(
 
 # The following block generate the code required to initialize the wrapper
 # when CTK is statically built.
-if(NOT CTK_BUILD_SHARED_LIBS
-   AND (CTK_WRAP_PYTHONQT_LIGHT OR CTK_WRAP_PYTHONQT_FULL))
+if(NOT CTK_BUILD_SHARED_LIBS AND CTK_WRAP_PYTHONQT_LIGHT)
 
   # Update list of target libraries with the list of available PythonQt libraries
   # and set variables holding list of pythonqt initialization method

+ 3 - 3
Applications/ctkSimplePythonShell/ctkSimplePythonManager.cpp.in

@@ -10,13 +10,13 @@
 // CTK includes
 #include "ctkSimplePythonManager.h"
 #include "ctkSimplePythonQtDecorators.h"
-#include "ctkSimplePythonShellConfigure.h" // For CTK_WRAP_PYTHONQT_{LIGHT, FULL}, CTK_WRAP_PYTHONQT_USE_VTK and CTK_BUILD_SHARED_LIBS
+#include "ctkSimplePythonShellConfigure.h" // For CTK_WRAP_PYTHONQT_LIGHT, CTK_WRAP_PYTHONQT_USE_VTK and CTK_BUILD_SHARED_LIBS
 #ifdef CTK_WRAP_PYTHONQT_USE_VTK
 # include "ctkVTKPythonQtWrapperFactory.h"
 #endif
 
 
-#if defined(CTK_WRAP_PYTHONQT_LIGHT) || defined(CTK_WRAP_PYTHONQT_FULL)
+#if defined(CTK_WRAP_PYTHONQT_LIGHT)
 # ifndef CTK_BUILD_SHARED_LIBS
   // PythonQt wrapper initialization methods
   @CTK_PYTHONQT_INITIALIZATION_METHOD_DEFINITION@
@@ -93,7 +93,7 @@ void ctkSimplePythonManager::preInitialization()
 {
   Superclass::preInitialization();
 
-#if defined(CTK_WRAP_PYTHONQT_LIGHT) || defined(CTK_WRAP_PYTHONQT_FULL)
+#if defined(CTK_WRAP_PYTHONQT_LIGHT)
 # ifndef CTK_BUILD_SHARED_LIBS
   // Initialize wrappers
   @CTK_PYTHONQT_INITIALIZATION_METHOD_CALL@

+ 0 - 1
Applications/ctkSimplePythonShell/ctkSimplePythonShellConfigure.h.in

@@ -8,7 +8,6 @@
 
 #cmakedefine CTK_BUILD_SHARED_LIBS
 #cmakedefine CTK_WRAP_PYTHONQT_LIGHT
-#cmakedefine CTK_WRAP_PYTHONQT_FULL
 
 //#define CTK_PYTHON_LIBRARY_DIR_BUILD "@LIBRARY_OUTPUT_DIRECTORY@"
 

+ 1 - 4
CMake/ctkMacroBuildLibWrapper.cmake

@@ -50,9 +50,6 @@ macro(ctkMacroBuildLibWrapper)
   if(NOT DEFINED MY_NAMESPACE)
     set(MY_NAMESPACE "org.commontk")
   endif()
-  if(NOT DEFINED CTK_WRAP_PYTHONQT_FULL)
-    set(CTK_WRAP_PYTHONQT_FULL FALSE)
-  endif()
   foreach(type RUNTIME LIBRARY ARCHIVE)
     if(NOT DEFINED MY_${type}_OUTPUT_DIRECTORY)
       set(MY_${type}_OUTPUT_DIRECTORY ${CMAKE_${type}_OUTPUT_DIRECTORY})
@@ -93,7 +90,7 @@ macro(ctkMacroBuildLibWrapper)
 
   set(KIT_PYTHONQT_SRCS) # Clear variable
   ctkMacroWrapPythonQt(${MY_NAMESPACE} ${lib_name}
-    KIT_PYTHONQT_SRCS "${MY_SRCS}" ${CTK_WRAP_PYTHONQT_FULL} ${HAS_DECORATOR})
+    KIT_PYTHONQT_SRCS "${MY_SRCS}" FALSE ${HAS_DECORATOR})
   if(HAS_DECORATOR)
     list(APPEND KIT_PYTHONQT_SRCS ${DECORATOR_HEADER})
     QT4_WRAP_CPP(KIT_PYTHONQT_SRCS ${DECORATOR_HEADER} OPTIONS -f${DECORATOR_HEADER})

+ 6 - 105
CMake/ctkMacroCompilePythonScript.cmake

@@ -119,7 +119,6 @@ function(_ctk_add_copy_python_files_target target type)
     if(entries)
       add_custom_target(${target_name} ALL
         DEPENDS
-          ${input_files}
           ${copied_files}
           )
     endif()
@@ -153,112 +152,15 @@ function(_ctk_add_compile_python_directories_target target)
     # Configure cmake script associated with the custom command
     # required to properly update the library path with PYTHON_LIBRARY_PATH
     set(compile_all_cmake_script "${CMAKE_CURRENT_BINARY_DIR}/compile_${target}_python_scripts.cmake")
-    file(WRITE ${compile_all_cmake_script} "
-#
-# Generated by ctkMacroCompilePythonScript CMAKE macro
-#
-
-# Generate compile_${target}_python_scripts.py
-file(WRITE \"@compile_all_script@\" \"
-#
-# Generated by ctkMacroCompilePythonScript CMake macro
-#
-
-#
-# Copied function 'compileall.compile_file' introduced in python 2.7 so that code compiled
-# using python 2.6 works.
-#
-# This version of the function has been copied from:
-#   https://github.com/jonashaag/cpython/blob/ce5e5df0c9d8098da05dee26e12ffe2aa331889e/Lib/compileall.py#L61-111
-#
-
-import os
-import sys
-import py_compile
-import struct
-import imp
-
-def ctk_compile_file(fullname, ddir=None, force=0, rx=None, quiet=0):
-    \\\"\\\"\\\"Byte-compile one file.
-
-    Arguments (only fullname is required):
-
-    fullname:  the file to byte-compile
-    ddir:      if given, the directory name compiled in to the
-               byte-code file.
-    force:     if 1, force compilation, even if timestamps are up-to-date
-    quiet:     if 1, be quiet during compilation
-    \\\"\\\"\\\"
-    success = 1
-    name = os.path.basename(fullname)
-    if ddir is not None:
-        dfile = os.path.join(ddir, name)
-    else:
-        dfile = None
-    if rx is not None:
-        mo = rx.search(fullname)
-        if mo:
-            return success
-    if os.path.isfile(fullname):
-        head, tail = name[:-3], name[-3:]
-        if tail == '.py':
-            if not force:
-                try:
-                    mtime = int(os.stat(fullname).st_mtime)
-                    expect = struct.pack('<4sl', imp.get_magic(), mtime)
-                    cfile = fullname + (__debug__ and 'c' or 'o')
-                    with open(cfile, 'rb') as chandle:
-                        actual = chandle.read(8)
-                    if expect == actual:
-                        return success
-                except IOError:
-                    pass
-            if not quiet:
-                print 'Compiling', fullname, '...'
-            try:
-                ok = py_compile.compile(fullname, None, dfile, True)
-            except py_compile.PyCompileError,err:
-                if quiet:
-                    print 'Compiling', fullname, '...'
-                print err.msg
-                success = 0
-            except IOError, e:
-                print 'Sorry', e
-                success = 0
-            else:
-                if ok == 0:
-                    success = 0
-    return success
-
-# Based on paraview/VTK/Wrapping/Python/compile_all_vtk.py.in
-
-@_compileall_code@
-file = open('@CMAKE_CURRENT_BINARY_DIR@/python_compile_@target@_complete', 'w')
-file.write('Done')
-\")
-
-set(ENV{PYTHONPATH} \"@CTK_PYTHON_COMPILE_FILE_SCRIPT_DIR@\")
-
-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_EXECUTABLE@\" \"@compile_all_script@\"
-  RESULT_VARIABLE result_var
-  )
-if(NOT result_var STREQUAL 0)
-  message(FATAL_ERROR \"Failed to compile python scripts: ${target} \")
-endif()
-")
+    configure_file(
+      ${CTK_CMAKE_DIR}/ctk_compile_python_scripts.cmake.in
+      ${compile_all_cmake_script}
+      @ONLY
+      )
 
     add_custom_command(
       COMMAND ${CMAKE_COMMAND} -P ${compile_all_cmake_script}
-      DEPENDS Copy${target}PythonScriptFiles
+      DEPENDS Copy${target}PythonScriptFiles ${compile_all_cmake_script}
       OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/python_compile_${target}_complete"
       COMMENT "Compiling python scripts: ${target}"
       )
@@ -266,7 +168,6 @@ endif()
     add_custom_target(${target_name} ALL
       DEPENDS 
         ${CMAKE_CURRENT_BINARY_DIR}/python_compile_${target}_complete
-        ${compile_all_cmake_script}
         )
   endif()
 endfunction()

+ 10 - 5
CMake/ctkMacroGenerateMocs.cmake

@@ -1,10 +1,11 @@
 
 # QT4_GENERATE_MOCS(inputfile1 [inputfile2 ...])
 
-macro(QT4_GENERATE_MOCS)
+function(QT4_GENERATE_MOCS)
+  QT4_GET_MOC_FLAGS(_moc_flags)
   foreach(file ${ARGN})
-    set(moc_file moc_${file})
-    QT4_GENERATE_MOC(${file} ${moc_file})
+
+    get_filename_component(abs_file ${file} ABSOLUTE)
 
     get_filename_component(source_name ${file} NAME_WE)
     get_filename_component(source_ext ${file} EXT)
@@ -15,7 +16,11 @@ macro(QT4_GENERATE_MOCS)
         set(source_ext .cxx)
       endif()
     endif()
-    set_property(SOURCE ${source_name}${source_ext} APPEND PROPERTY OBJECT_DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${moc_file})
+
+    set(moc_file ${CMAKE_CURRENT_BINARY_DIR}/moc_${source_name}${source_ext})
+
+    QT4_CREATE_MOC_COMMAND(${abs_file} ${moc_file} "${_moc_flags}" "" "")
+    MACRO_ADD_FILE_DEPENDENCIES(${abs_file} ${moc_file})
   endforeach()
-endmacro()
+endfunction()
 

+ 47 - 219
CMake/ctkMacroWrapPythonQt.cmake

@@ -25,8 +25,7 @@
 #!
 #! Depends on:
 #!  PythonQt
-#!  PythonQtGenerator (Only if IS_WRAP_FULL is TRUE)
-#!  PythonInterp (See function reSearchFile)
+#!  PythonInterp
 #!
 
 #!
@@ -41,8 +40,6 @@
 #!
 #!    SOURCES ..........: List of source files that should be wrapped.
 #!
-#!    IS_WRAP_FULL .....: Indicate if a Full wrapping if desired.
-#!
 #!    HAS_DECORATOR ....: Indicate if a custom PythonQt decorator header is expected.
 #!
 
@@ -54,56 +51,12 @@
 
 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
-#!
-#! \ingroup CMakeUtilities
-function(ctkMacroWrapPythonQt_log msg)
-  if(verbose)
-    message(${msg})
-  endif()
-  file(APPEND "${CMAKE_CURRENT_BINARY_DIR}/ctkMacroWrapPythonQt_log.txt" "${msg}\n")
-endfunction()
-
-include(${CTK_CMAKE_DIR}/ctkMacroSetPaths.cmake)
-
-#!
-#! 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
-#!
-#! \ingroup CMakeUtilities
-function(ctkMacroWrapPythonQt_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}")
-
-  ctkMacroSetPaths("${python_library_path}")
-  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}\nPython exe: ${python_exe}\nPython lib path: ${python_library_path}")
-  endif()
-  set(is_matching ${output} PARENT_SCOPE)
-endfunction()
-
 #! \ingroup CMakeUtilities
 macro(ctkMacroWrapPythonQt WRAPPING_NAMESPACE TARGET SRCS_LIST_NAME SOURCES IS_WRAP_FULL HAS_DECORATOR)
 
   # Sanity check
-  if(IS_WRAP_FULL AND NOT EXISTS "${PYTHONQTGENERATOR_EXECUTABLE}")
-    message(FATAL_ERROR "PYTHONQTGENERATOR_EXECUTABLE not specified or inexistent when calling ctkMacroWrapPythonQt")
+  if(IS_WRAP_FULL)
+    message(FATAL_ERROR "IS_WRAP_FULL option is not supported anymore. See https://github.com/commontk/CTK/issues/449")
   endif()
 
   # TODO: this find package seems not to work when called form a superbuild, but the call is needed
@@ -114,20 +67,8 @@ macro(ctkMacroWrapPythonQt WRAPPING_NAMESPACE TARGET SRCS_LIST_NAME SOURCES IS_W
     message(FATAL_ERROR "PYTHON_EXECUTABLE not specified or inexistent when calling ctkMacroWrapPythonQt")
   endif()
 
-  # Extract python lib path
-  get_filename_component(PYTHON_DIR_PATH ${PYTHON_EXECUTABLE} PATH)
-  set(PYTHON_LIBRARY_PATH ${PYTHON_DIR_PATH}/../lib)
-  if(WIN32)
-    set(PYTHON_LIBRARY_PATH ${PYTHON_DIR_PATH})
-  endif()
-
-  # Clear log file
-  file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/ctkMacroWrapPythonQt_log.txt" "")
-
-  # Convert wrapping namespace to subdir
-  string(REPLACE "." "_" WRAPPING_NAMESPACE_UNDERSCORE ${WRAPPING_NAMESPACE})
-
   set(SOURCES_TO_WRAP)
+
   # For each class
   foreach(FILE ${SOURCES})
 
@@ -137,7 +78,9 @@ macro(ctkMacroWrapPythonQt WRAPPING_NAMESPACE TARGET SRCS_LIST_NAME SOURCES IS_W
       # Skip wrapping if file is NOT regular header
       if(NOT ${FILE} MATCHES "^.*\\.[hH]$")
         set(skip_wrapping TRUE)
-        ctkMacroWrapPythonQt_log("${FILE}: skipping - Not a regular header")
+        if(verbose)
+          message("${FILE}: skipping - Not a regular header")
+        endif()
       endif()
     endif()
 
@@ -145,7 +88,9 @@ macro(ctkMacroWrapPythonQt WRAPPING_NAMESPACE TARGET SRCS_LIST_NAME SOURCES IS_W
       # Skip wrapping if file is a pimpl header
       if(${FILE} MATCHES "^.*_[pP]\\.[hH]$")
         set(skip_wrapping TRUE)
-        ctkMacroWrapPythonQt_log("${FILE}: skipping - Pimpl header (*._p.h)")
+        if(verbose)
+          message("${FILE}: skipping - Pimpl header (*._p.h)")
+        endif()
       endif()
     endif()
 
@@ -157,58 +102,14 @@ macro(ctkMacroWrapPythonQt WRAPPING_NAMESPACE TARGET SRCS_LIST_NAME SOURCES IS_W
         set(skip_wrapping FALSE)
       endif()
       if(skip_wrapping)
-        ctkMacroWrapPythonQt_log("${FILE}: skipping - WRAP_EXCLUDE")
-      endif()
-    endif()
-
-    # what is the filename without the extension
-    get_filename_component(TMP_FILENAME ${FILE} NAME_WE)
-
-    # Extract classname - NOTE: We assume the filename matches the associated class
-    set(className ${TMP_FILENAME})
-
-    if(NOT skip_wrapping)
-      # Skip wrapping if IS_WRAP_FULL=FALSE and if file do NOT contain Q_OBJECT
-      if(NOT IS_WRAP_FULL)
-        file(READ ${CMAKE_CURRENT_SOURCE_DIR}/${FILE} file_content)
-        if(NOT "${file_content}" MATCHES "Q_OBJECT")
-          set(skip_wrapping TRUE)
-          ctkMacroWrapPythonQt_log("${FILE}: skipping - No Q_OBJECT macro")
+        if(verbose)
+          message("${FILE}: skipping - WRAP_EXCLUDE")
         endif()
       endif()
     endif()
 
-    if(NOT skip_wrapping)
-      # Skip wrapping if IS_WRAP_FULL=FALSE and if constructor doesn't match:
-      #    my_class()
-      #    my_class(QObject* newParent ...)
-      #    my_class(QWidget* newParent ...)
-      if(NOT IS_WRAP_FULL)
-        # Constructor with either QWidget or QObject as first parameter
-        set(regex "[^~]${className}[\\s\\n]*\\([\\s\\n]*((QObject|QWidget)[\\s\\n]*\\*[\\s\\n]*\\w+[\\s\\n]*(\\=[\\s\\n]*(0|NULL)|,.*\\=.*\\)|\\)|\\)))")
-        ctkMacroWrapPythonQt_reSearchfile(${PYTHON_EXECUTABLE} ${PYTHON_LIBRARY_PATH}
-                                          ${regex} ${CMAKE_CURRENT_SOURCE_DIR}/${FILE} is_matching)
-        if(NOT is_matching)
-          set(skip_wrapping TRUE)
-          ctkMacroWrapPythonQt_log("${FILE}: skipping - Missing expected constructor signature")
-        endif()
-      endif()
-    endif()
-
-    if(NOT skip_wrapping)
-      # Skip wrapping if object has a virtual pure method
-      # "x3b" is the unicode for semicolon
-      set(regex "virtual[\\w\\n\\s\\*\\(\\)]+\\=[\\s\\n]*(0|NULL)[\\s\\n]*\\x3b")
-      ctkMacroWrapPythonQt_reSearchfile(${PYTHON_EXECUTABLE} ${PYTHON_LIBRARY_PATH}
-                                        ${regex} ${CMAKE_CURRENT_SOURCE_DIR}/${FILE} is_matching)
-      if(is_matching)
-        set(skip_wrapping TRUE)
-        ctkMacroWrapPythonQt_log("${FILE}: skipping - Contains a virtual pure method")
-      endif()
-    endif()
-
     # if we should wrap it
-    IF (NOT skip_wrapping)
+    if(NOT skip_wrapping)
 
       # compute the input filename
       if(IS_ABSOLUTE FILE)
@@ -218,139 +119,66 @@ macro(ctkMacroWrapPythonQt WRAPPING_NAMESPACE TARGET SRCS_LIST_NAME SOURCES IS_W
       endif()
 
       list(APPEND SOURCES_TO_WRAP ${TMP_INPUT})
-
     endif()
   endforeach()
 
-  # PythonQtGenerator expects a colon ':' separated list
-  set(INCLUDE_DIRS_TO_WRAP)
-  foreach(include ${CTK_BASE_INCLUDE_DIRS})
-    set(INCLUDE_DIRS_TO_WRAP "${INCLUDE_DIRS_TO_WRAP}:${include}")
-  endforeach()
-
-  # Prepare custom_command argument
-  set(SOURCES_TO_WRAP_ARG)
-  foreach(source ${SOURCES_TO_WRAP})
-    set(SOURCES_TO_WRAP_ARG "${SOURCES_TO_WRAP_ARG}^^${source}")
-  endforeach()
+  # Convert wrapping namespace to subdir
+  string(REPLACE "." "_" WRAPPING_NAMESPACE_UNDERSCORE ${WRAPPING_NAMESPACE})
 
   # Define wrap type and wrap intermediate directory
-  set(wrap_type "Light")
   set(wrap_int_dir generated_cpp/${WRAPPING_NAMESPACE_UNDERSCORE}_${TARGET}/)
-  set(extra_files )
-  if(${IS_WRAP_FULL})
-    set(wrap_type "Full")
-    set(extra_files ${wrap_int_dir}ctkPythonQt_${TARGET}_masterinclude.h)
-  endif()
-  #message("wrap_type:${wrap_type} - wrap_int_dir:${wrap_int_dir}")
 
-  # Create intermediate output directory
-  execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/${wrap_int_dir})
+  set(wrapper_module_init_cpp_filename ${wrap_int_dir}${WRAPPING_NAMESPACE_UNDERSCORE}_${TARGET}_module_init.cpp)
 
-  # On Windows, to avoid "too long input" error, dump INCLUDE_DIRS_TO_WRAP into a file
-  if(WIN32)
-    # File containing the moc flags
-    set(include_dirs_to_wrap_filename includeDirsToWrap_${WRAPPING_NAMESPACE_UNDERSCORE}_${TARGET}.txt)
-    set(include_dirs_to_wrap_file ${CMAKE_CURRENT_BINARY_DIR}/${wrap_int_dir}${include_dirs_to_wrap_filename})
-    file(WRITE ${include_dirs_to_wrap_file} ${INCLUDE_DIRS_TO_WRAP})
-    # The arg passed to the custom command will be the file containing the list of include dirs to wrap
-    set(INCLUDE_DIRS_TO_WRAP ${include_dirs_to_wrap_file})
-  endif()
-
-  set(wrapper_init_cpp_filename ${WRAPPING_NAMESPACE_UNDERSCORE}_${TARGET}_init.cpp)
-  set(wrapper_init_cpp_file ${CMAKE_CURRENT_BINARY_DIR}/${wrap_int_dir}${wrapper_init_cpp_filename})
+  # Configure 'ctkMacroWrapPythonQtModuleInit.cpp.in' using TARGET, HAS_DECORATOR and
+  # WRAPPING_NAMESPACE_UNDERSCORE.
+  set(TARGET_CONFIG ${TARGET})
+  configure_file(
+    ${CTK_CMAKE_DIR}/ctkMacroWrapPythonQtModuleInit.cpp.in
+    ${wrapper_module_init_cpp_filename}
+    @ONLY
+    )
 
-  set(wrapper_module_init_cpp_filename ${WRAPPING_NAMESPACE_UNDERSCORE}_${TARGET}_module_init.cpp)
-  set(wrapper_module_init_cpp_file ${CMAKE_CURRENT_BINARY_DIR}/${wrap_int_dir}${wrapper_module_init_cpp_filename})
+  set(extra_args)
+  if(verbose)
+    set(extra_args --extra-verbose)
+  endif()
 
   # Custom command allow to generate ${WRAPPING_NAMESPACE_UNDERSCORE}_${TARGET}_init.cpp and
-  # associated wrappers ${WRAPPING_NAMESPACE_UNDERSCORE}_${TARGET}{0-N}.cpp
+  # associated wrappers ${WRAPPING_NAMESPACE_UNDERSCORE}_${TARGET}.cpp
+  set(wrapper_init_cpp_filename ${wrap_int_dir}${WRAPPING_NAMESPACE_UNDERSCORE}_${TARGET}_init.cpp)
+  set(wrapper_h_filename ${wrap_int_dir}${WRAPPING_NAMESPACE_UNDERSCORE}_${TARGET}.h)
   add_custom_command(
     OUTPUT
-      ${wrap_int_dir}${wrapper_init_cpp_filename}
-      ${wrap_int_dir}${wrapper_module_init_cpp_filename}
-      ${extra_files}
+      ${wrapper_init_cpp_filename}
+      ${wrapper_h_filename}
     DEPENDS
-      ${pythonqtgenerator_executable_depends}
       ${SOURCES_TO_WRAP}
-      ${CTK_CMAKE_DIR}/ctkScriptWrapPythonQt_${wrap_type}.cmake
-      ${CTK_CMAKE_DIR}/ctkMacroWrapPythonQtModuleInit.cpp.in
-    COMMAND ${CMAKE_COMMAND}
-      -DPYTHONQTGENERATOR_EXECUTABLE:FILEPATH=${PYTHONQTGENERATOR_EXECUTABLE}
-      -DPYTHON_EXECUTABLE:FILEPATH=${PYTHON_EXECUTABLE}
-      -DPYTHON_LIBRARY_PATH:PATH=${PYTHON_LIBRARY_PATH}
-      -DWRAPPING_NAMESPACE:STRING=${WRAPPING_NAMESPACE}
-      -DTARGET:STRING=${TARGET}
-      -DSOURCES:STRING=${SOURCES_TO_WRAP_ARG}
-      -DINCLUDE_DIRS:STRING=${INCLUDE_DIRS_TO_WRAP}
-      -DOUTPUT_DIR:PATH=${CMAKE_CURRENT_BINARY_DIR}
-      -DWRAP_INT_DIR:STRING=${wrap_int_dir}
-      -DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE}
-      -DHAS_DECORATOR:BOOL=${HAS_DECORATOR}
-      -P ${CTK_CMAKE_DIR}/ctkScriptWrapPythonQt_${wrap_type}.cmake
-    COMMENT "PythonQt ${wrap_type} Wrapping - Generating ${wrapper_init_cpp_filename}"
+      ${CTK_CMAKE_DIR}/ctkWrapPythonQt.py
+    COMMAND ${PYTHON_EXECUTABLE} ${CTK_CMAKE_DIR}/ctkWrapPythonQt.py
+      --target=${TARGET}
+      --namespace=${WRAPPING_NAMESPACE}
+      --output-dir=${CMAKE_CURRENT_BINARY_DIR}/${wrap_int_dir} ${extra_args}
+      ${SOURCES_TO_WRAP}
+    COMMENT "PythonQt Wrapping - Generating ${wrapper_init_cpp_filename}"
     VERBATIM
     )
 
-  # Clear variable
-  set(moc_flags)
-
-  # Grab moc flags
-  QT4_GET_MOC_FLAGS(moc_flags)
-
-  # Prepare custom_command argument
-  set(moc_flags_arg)
-  foreach(flag ${moc_flags})
-    set(moc_flags_arg "${moc_flags_arg}^^${flag}")
-  endforeach()
-
-  # On Windows, to avoid "too long input" error, dump moc flags.
-  if(WIN32)
-    # File containing the moc flags
-    set(wrapper_moc_flags_filename mocflags_${WRAPPING_NAMESPACE_UNDERSCORE}_${TARGET}_all.txt)
-    set(wrapper_master_moc_flags_file ${CMAKE_CURRENT_BINARY_DIR}/${wrap_int_dir}${wrapper_moc_flags_filename})
-    file(WRITE ${wrapper_master_moc_flags_file} ${moc_flags_arg})
-    # The arg passed to the custom command will be the file containing the list of moc flags
-    set(moc_flags_arg ${wrapper_master_moc_flags_file})
-  endif()
-
-  # File to run through moc
-  set(wrapper_master_moc_filename moc_${WRAPPING_NAMESPACE_UNDERSCORE}_${TARGET}_all.cpp)
-  set(wrapper_master_moc_file ${CMAKE_CURRENT_BINARY_DIR}/${wrap_int_dir}${wrapper_master_moc_filename})
-
-  # Custom command allowing to call moc to process the wrapper headers
-  add_custom_command(
-    OUTPUT ${wrap_int_dir}${wrapper_master_moc_filename}
-    DEPENDS
-      ${wrap_int_dir}${wrapper_init_cpp_filename}
-      ${wrap_int_dir}${wrapper_module_init_cpp_filename}
-      ${extra_files} ${CTK_CMAKE_DIR}/ctkScriptMocPythonQtWrapper.cmake
-    COMMAND ${CMAKE_COMMAND}
-      -DWRAPPING_NAMESPACE:STRING=${WRAPPING_NAMESPACE}
-      -DTARGET:STRING=${TARGET}
-      -DMOC_FLAGS:STRING=${moc_flags_arg}
-      -DWRAP_INT_DIR:STRING=${wrap_int_dir}
-      -DWRAPPER_MASTER_MOC_FILE:STRING=${wrapper_master_moc_file}
-      -DOUTPUT_DIR:PATH=${CMAKE_CURRENT_BINARY_DIR}
-      -DQT_MOC_EXECUTABLE:FILEPATH=${QT_MOC_EXECUTABLE}
-      -P ${CTK_CMAKE_DIR}/ctkScriptMocPythonQtWrapper.cmake
-    COMMENT "PythonQt ${wrap_type} Wrapping - Moc'ing ${WRAPPING_NAMESPACE_UNDERSCORE}_${TARGET} wrapper headers"
-    VERBATIM
-    )
+  QT4_WRAP_CPP(${TARGET}_MOC_CXX ${CMAKE_CURRENT_BINARY_DIR}/${wrapper_h_filename})
 
   # The following files are generated
   set_source_files_properties(
-    ${wrap_int_dir}${wrapper_init_cpp_filename}
-    ${wrap_int_dir}${wrapper_module_init_cpp_filename}
-    ${wrap_int_dir}${wrapper_master_moc_filename}
+    ${wrapper_init_cpp_filename}
+    ${wrapper_h_filename}
+    ${wrapper_module_init_cpp_filename}
     PROPERTIES GENERATED TRUE)
 
   # Create the Init File
   set(${SRCS_LIST_NAME}
     ${${SRCS_LIST_NAME}}
-    ${wrap_int_dir}${wrapper_init_cpp_filename}
-    ${wrap_int_dir}${wrapper_module_init_cpp_filename}
-    ${wrap_int_dir}${wrapper_master_moc_filename}
+    ${wrapper_init_cpp_filename}
+    ${wrapper_module_init_cpp_filename}
+    ${${TARGET}_MOC_CXX}
     )
 
   #

+ 14 - 14
CMake/ctkMacroWrapPythonQtModuleInit.cpp.in

@@ -1,14 +1,14 @@
-// Configured by cmake macro @CMAKE_CURRENT_LIST_FILENAME@
+// Configured by cmake macro @CMAKE_CURRENT_LIST_FILE@
 
 #include <PythonQt.h>
 #include <Python.h>
 
 //-----------------------------------------------------------------------------
-static PyMethodDef Py@TARGET@PythonQt_ClassMethods[] = {
+static PyMethodDef Py@TARGET_CONFIG@PythonQt_ClassMethods[] = {
 {NULL, NULL, 0, NULL}};
 
 //-----------------------------------------------------------------------------
-extern "C" { void Q_DECL_EXPORT init@TARGET@PythonQt(); }
+extern "C" { void Q_DECL_EXPORT init@TARGET_CONFIG@PythonQt(); }
 
 #ifdef __GNUC__
 // Disable warnings related to Py_DECREF() macro
@@ -50,26 +50,26 @@ void copyAttributes(PyObject* orig_module, PyObject* dest_module)
 } // end of anonymous namespace
 
 //-----------------------------------------------------------------------------
-void init@TARGET@PythonQt()
+void init@TARGET_CONFIG@PythonQt()
 {
-  static const char modulename[] = "@TARGET@PythonQt";
+  static const char modulename[] = "@TARGET_CONFIG@PythonQt";
   PyObject *m;
 
-  m = Py_InitModule((char*)modulename, Py@TARGET@PythonQt_ClassMethods);
-  extern void PythonQt_init_@WRAPPING_NAMESPACE_UNDERSCORE@_@TARGET@(PyObject*);
-  PythonQt_init_@WRAPPING_NAMESPACE_UNDERSCORE@_@TARGET@(m);
+  m = Py_InitModule((char*)modulename, Py@TARGET_CONFIG@PythonQt_ClassMethods);
+  extern void PythonQt_init_@WRAPPING_NAMESPACE_UNDERSCORE@_@TARGET_CONFIG@(PyObject*);
+  PythonQt_init_@WRAPPING_NAMESPACE_UNDERSCORE@_@TARGET_CONFIG@(m);
 
 #ifdef HAS_DECORATOR
-  extern void init@TARGET@PythonQtDecorators();
-  init@TARGET@PythonQtDecorators();
+  extern void init@TARGET_CONFIG@PythonQtDecorators();
+  init@TARGET_CONFIG@PythonQtDecorators();
 #endif
 
-  // Since invoking 'PythonQt_init_@WRAPPING_NAMESPACE_UNDERSCORE@_@TARGET@', will create
-  // the module "PythonQt.@TARGET@". Let's copy its content into the current module.
-  PythonQtObjectPtr currentModule = PyImport_ImportModule((char*)"PythonQt.@TARGET@");
+  // Since invoking 'PythonQt_init_@WRAPPING_NAMESPACE_UNDERSCORE@_@TARGET_CONFIG@', will create
+  // the module "PythonQt.@TARGET_CONFIG@". Let's copy its content into the current module.
+  PythonQtObjectPtr currentModule = PyImport_ImportModule((char*)"PythonQt.@TARGET_CONFIG@");
   if(currentModule.isNull())
     {
-    PyErr_SetString(PyExc_ImportError, (char*)"Failed to import PythonQt.@TARGET@");
+    PyErr_SetString(PyExc_ImportError, (char*)"Failed to import PythonQt.@TARGET_CONFIG@");
     return;
     }
   copyAttributes(currentModule, m);

+ 0 - 120
CMake/ctkScriptMocPythonQtWrapper.cmake

@@ -1,120 +0,0 @@
-###########################################################################
-#
-#  Library:   CTK
-#
-#  Copyright (c) Kitware Inc.
-#
-#  Licensed under the Apache License, Version 2.0 (the "License");
-#  you may not use this file except in compliance with the License.
-#  You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0.txt
-#
-#  Unless required by applicable law or agreed to in writing, software
-#  distributed under the License is distributed on an "AS IS" BASIS,
-#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-#  See the License for the specific language governing permissions and
-#  limitations under the License.
-#
-###########################################################################
-
-#
-# ctkScriptMocPythonQtWrapper
-#
-
-#
-# This script should be invoked either as a CUSTOM_COMMAND 
-# or from the command line using the following syntax:
-#
-#    cmake -DWRAPPING_NAMESPACE:STRING=org.commontk 
-#      -DTARGET:STRING=MyLib
-#      -DOUTPUT_DIR:PATH=/path
-#      -DMOC_FLAGS:STRING=-I/path/to/lib1^^-I/path/to/lib2^^-DOPT1
-#      -DWRAPPER_MASTER_MOC_FILE:FILEPATH=/path/to/file
-#      -DQT_QMAKE_EXECUTABLE:PATH=/path/to/qt/qmake
-#      -P ctkScriptMocPythonQtWrapper.cmake
-#
-#
-
-# Check for non-defined var
-foreach(var WRAPPING_NAMESPACE TARGET MOC_FLAGS WRAPPER_MASTER_MOC_FILE WRAP_INT_DIR)
-  if(NOT DEFINED ${var})
-    message(FATAL_ERROR "${var} not specified when calling ctkScriptMocPythonQtWrapper")
-  endif()
-endforeach()
-
-# Check for non-existing ${var}
-foreach(var OUTPUT_DIR QT_MOC_EXECUTABLE)
-  if(NOT EXISTS ${${var}})
-    message(FATAL_ERROR "Failed to find ${var} when calling ctkScriptWrapPythonQt")
-  endif()
-endforeach()
-
-# Convert wrapping namespace to subdir
-string(REPLACE "." "_" WRAPPING_NAMESPACE_UNDERSCORE ${WRAPPING_NAMESPACE})
-
-# Read moc flags from file
-if(WIN32)
-  if(NOT EXISTS ${MOC_FLAGS})
-    message(FATAL_ERROR "On Windows, MOC_FLAGS should be the name of the file containing the moc flags !")
-  endif()
-  file(READ ${MOC_FLAGS} MOC_FLAGS)
-endif()
-
-# Convert ^^ separated string to list
-string(REPLACE "^^" ";" MOC_FLAGS "${MOC_FLAGS}")
-
-# Clear file where all moc'ified will be appended
-file(WRITE ${WRAPPER_MASTER_MOC_FILE} "// 
-// File auto-generated by cmake macro ctkScriptMocPythonQtWrapper\n//\n")
-
-# Collect wrapper headers
-set(glob_expression ${OUTPUT_DIR}/${WRAP_INT_DIR}${WRAPPING_NAMESPACE_UNDERSCORE}_${TARGET}*.h)
-file(GLOB wrapper_headers RELATIVE ${OUTPUT_DIR}/${WRAP_INT_DIR} ${glob_expression})
-
-if(NOT wrapper_headers)
-  message(FATAL_ERROR "ctkScriptMocPythonQtWrapper - Failed to glob wrapper headers using expression:[${glob_expression}]")
-endif()
-
-# Moc'ified each one of them
-foreach(header ${wrapper_headers})
-  
-  set(moc_extra_options)
-  set(wrapper_h_file ${OUTPUT_DIR}/${WRAP_INT_DIR}/${header})
-  set(wrapper_moc_file ${OUTPUT_DIR}/${WRAP_INT_DIR}/moc_${header}.cpp)
-  
-  # Dump moc executable options into a file to avoid command line length limitations
-  # See http://qt-project.org/doc/qt-4.8/moc.html#command-line-options
-  
-  # As required when using the @ option of moc executable, process MOC_FLAGS list 
-  # to obtain a string with one flag per line
-  set(moc_flags_with_newline "")
-  foreach(flag ${MOC_FLAGS})
-    set(moc_flags_with_newline "${moc_flags_with_newline}\n${flag}")
-  endforeach()
-  
-  # Dump flags into a file
-  get_filename_component(header_we ${header} NAME_WE)
-  set(wrapper_moc_options_file ${OUTPUT_DIR}/${WRAP_INT_DIR}/${header_we}_moc_opts.txt)
-  file(WRITE ${wrapper_moc_options_file}
-"${moc_flags_with_newline}
-${moc_extra_options}")
-
-  message("${QT_MOC_EXECUTABLE} @${wrapper_moc_options_file} -o ${wrapper_moc_file} ${wrapper_h_file}")
-  # Invoke moc executable passing "@" parameter
-  execute_process(
-    COMMAND ${QT_MOC_EXECUTABLE} @${wrapper_moc_options_file} -o ${wrapper_moc_file} ${wrapper_h_file}
-    WORKING_DIRECTORY ${OUTPUT_DIR}
-    RESULT_VARIABLE RESULT_VAR
-    ERROR_VARIABLE error
-    )
-  if(RESULT_VAR)
-    message(FATAL_ERROR "Failed to moc'ified .\n${RESULT_VAR}\n${error}")
-  endif()
-  
-  # Append generated moc file to the master file
-  file(READ ${wrapper_moc_file} file_content)
-  file(APPEND ${WRAPPER_MASTER_MOC_FILE} "${file_content}")
-
-endforeach()
-

+ 0 - 153
CMake/ctkScriptWrapPythonQt_Full.cmake

@@ -1,153 +0,0 @@
-###########################################################################
-#
-#  Library:   CTK
-#
-#  Copyright (c) Kitware Inc.
-#
-#  Licensed under the Apache License, Version 2.0 (the "License");
-#  you may not use this file except in compliance with the License.
-#  You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0.txt
-#
-#  Unless required by applicable law or agreed to in writing, software
-#  distributed under the License is distributed on an "AS IS" BASIS,
-#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-#  See the License for the specific language governing permissions and
-#  limitations under the License.
-#
-###########################################################################
-
-#
-# ctkScriptWrapPythonQt_Full
-#
-
-#
-# Depends on:
-#  CTK/CMake/ctkMacroWrapPythonQt.cmake
-#
-
-#
-# This script should be invoked either as a CUSTOM_COMMAND
-# or from the command line using the following syntax:
-#
-#    cmake -DWRAPPING_NAMESPACE:STRING=org.commontk -DTARGET:STRING=MyLib
-#          -DSOURCES:STRING="file1^^file2" -DINCLUDE_DIRS:STRING=/path1:/path2
-#          -DWRAP_INT_DIR:STRING=subir/subir/
-#          -DPYTHONQTGENERATOR_EXECUTABLE:FILEPATH=/path/to/exec
-#          -DOUTPUT_DIR:PATH=/path  -DQT_QMAKE_EXECUTABLE:PATH=/path/to/qt/qmake
-#          -DHAS_DECORATOR:BOOL=True
-#          -P ctkScriptWrapPythonQt_Full.cmake
-#
-
-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
-foreach(var SOURCES TARGET INCLUDE_DIRS WRAP_INT_DIR WRAPPING_NAMESPACE HAS_DECORATOR)
-  if(NOT DEFINED ${var})
-    message(FATAL_ERROR "${var} not specified when calling ctkScriptWrapPythonQt")
-  endif()
-endforeach()
-
-# Check for non-existing ${var}
-foreach(var PYTHONQTGENERATOR_EXECUTABLE QT_QMAKE_EXECUTABLE OUTPUT_DIR)
-  if(NOT EXISTS ${${var}})
-    message(FATAL_ERROR "Failed to find ${var} when calling ctkScriptWrapPythonQt")
-  endif()
-endforeach()
-
-# Convert wrapping namespace to subdir
-string(REPLACE "." "_" WRAPPING_NAMESPACE_UNDERSCORE ${WRAPPING_NAMESPACE})
-
-# Convert ^^ separated string to list
-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}")
-
-  set(objectTypes "${objectTypes}\n  <object-type name=\"${className}\"/>")
-
-endforeach()
-
-# Write master include file
-  file(WRITE ${OUTPUT_DIR}/${WRAP_INT_DIR}ctkPythonQt_${TARGET}_masterinclude.h "
-#ifndef __ctkPythonQt_${TARGET}_masterinclude_h
-#define __ctkPythonQt_${TARGET}_masterinclude_h
-${includes}
-#endif
-")
-
-# Write Typesystem file
-file(WRITE ${OUTPUT_DIR}/${WRAP_INT_DIR}typesystem_${TARGET}.xml "
-<typesystem package=\"${WRAPPING_NAMESPACE}.${TARGET}\">
-  ${objectTypes}
-</typesystem>
-")
-
-# Extract PYTHONQTGENERATOR_DIR
-get_filename_component(PYTHONQTGENERATOR_DIR ${PYTHONQTGENERATOR_EXECUTABLE} PATH)
-#message(PYTHONQTGENERATOR_DIR:${PYTHONQTGENERATOR_DIR})
-
-# Write Build file
-file(WRITE ${OUTPUT_DIR}/${WRAP_INT_DIR}build_${TARGET}.txt "
-<!-- File auto-generated by cmake macro ctkScriptWrapPythonQt_Full -->
-
-<typesystem>
-  <load-typesystem name=\"${PYTHONQTGENERATOR_DIR}/typesystem_core.xml\" generate=\"no\" />
-  <load-typesystem name=\"${PYTHONQTGENERATOR_DIR}/typesystem_gui.xml\" generate=\"no\" />
-  <load-typesystem name=\"${OUTPUT_DIR}/${WRAP_INT_DIR}/typesystem_${TARGET}.xml\" generate=\"yes\" />
-</typesystem>
-")
-
-# Read include dirs from file
-if(WIN32)
-  if(NOT EXISTS ${INCLUDE_DIRS})
-    message(FATAL_ERROR "On Windows, INCLUDE_DIRS should be the name of the file containing the include directories !")
-  endif()
-  file(READ ${INCLUDE_DIRS} INCLUDE_DIRS)
-endif()
-
-# Compute QTDIR
-get_filename_component(QTDIR ${QT_QMAKE_EXECUTABLE}/../../ REALPATH)
-set(ENV{QTDIR} ${QTDIR})
-
-execute_process(
-  COMMAND ${PYTHONQTGENERATOR_EXECUTABLE} --debug-level=sparse --include-paths=${INCLUDE_DIRS} --output-directory=${OUTPUT_DIR} ${OUTPUT_DIR}/${WRAP_INT_DIR}ctkPythonQt_${TARGET}_masterinclude.h ${OUTPUT_DIR}/${WRAP_INT_DIR}build_${TARGET}.txt
-  WORKING_DIRECTORY ${PYTHONQTGENERATOR_DIR}
-  RESULT_VARIABLE result
-  #OUTPUT_VARIABLE output
-  ERROR_VARIABLE error
-  OUTPUT_QUIET
-  )
-#message(${error})
-if(result)
-  message(FATAL_ERROR "Failed to generate ${WRAPPING_NAMESPACE_UNDERSCORE}_${TARGET}_init.cpp\n${error}")
-endif()
-
-# Configure 'ctkMacroWrapPythonQtModuleInit.cpp.in' replacing TARGET and
-# WRAPPING_NAMESPACE_UNDERSCORE.
-configure_file(
-  ${CMAKE_CURRENT_LIST_DIR}/ctkMacroWrapPythonQtModuleInit.cpp.in
-  ${OUTPUT_DIR}/${WRAP_INT_DIR}${WRAPPING_NAMESPACE_UNDERSCORE}_${TARGET}_module_init.cpp
-  )
-
-# Since PythonQtGenerator or 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
-    ${OUTPUT_DIR}/${WRAP_INT_DIR}ctkPythonQt_${TARGET}_masterinclude.h
-  )

+ 0 - 267
CMake/ctkScriptWrapPythonQt_Light.cmake

@@ -1,267 +0,0 @@
-###########################################################################
-#
-#  Library:   CTK
-#
-#  Copyright (c) Kitware Inc.
-#
-#  Licensed under the Apache License, Version 2.0 (the "License");
-#  you may not use this file except in compliance with the License.
-#  You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0.txt
-#
-#  Unless required by applicable law or agreed to in writing, software
-#  distributed under the License is distributed on an "AS IS" BASIS,
-#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-#  See the License for the specific language governing permissions and
-#  limitations under the License.
-#
-###########################################################################
-
-#
-# ctkScriptWrapPythonQt_Light
-#
-
-#
-# Depends on:
-#  CTK/CMake/ctkMacroWrapPythonQt.cmake
-#
-
-#
-# This script should be invoked either as a CUSTOM_COMMAND
-# or from the command line using the following syntax:
-#
-#    cmake -DWRAPPING_NAMESPACE:STRING=org.commontk -DTARGET:STRING=MyLib
-#          -DSOURCES:STRING="file1^^file2" -DINCLUDE_DIRS:STRING=/path1:/path2
-#          -DWRAP_INT_DIR:STRING=subir/subir/
-#          -DOUTPUT_DIR:PATH=/path  -DQT_QMAKE_EXECUTABLE:PATH=/path/to/qt/qmake
-#          -DPYTHON_EXECUTABLE:FILEPATH=/path/to/python
-#          -DPYTHON_LIBRARY_PATH:PATH=/path/to/pythonlib
-#          -DHAS_DECORATOR:BOOL=True
-#          -P ctkScriptWrapPythonQt_Light.cmake
-#
-
-#
-# LOG FILE:
-#   File ctkScriptWrapPythonQt_Light_log.txt will be created in the current directory.
-#   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
-foreach(var WRAPPING_NAMESPACE TARGET SOURCES INCLUDE_DIRS WRAP_INT_DIR HAS_DECORATOR)
-  if(NOT DEFINED ${var})
-    message(FATAL_ERROR "${var} not specified when calling ctkScriptWrapPythonQt")
-  endif()
-endforeach()
-
-# Check for non-existing ${var}
-foreach(var QT_QMAKE_EXECUTABLE OUTPUT_DIR PYTHON_EXECUTABLE PYTHON_LIBRARY_PATH)
-  if(NOT EXISTS ${${var}})
-    message(FATAL_ERROR "Failed to find ${var}=\"${${var}}\" when calling ctkScriptWrapPythonQt")
-  endif()
-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
-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; }
-};
-")
-
-  else() # Case parentClassName is empty
-
-    message(WARNING "ctkScriptWrapPythonQt_Light - Problem wrapping ${FILE}")
-
-  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}
-}
-")
-
-# Configure 'ctkMacroWrapPythonQtModuleInit.cpp.in' replacing TARGET and
-# WRAPPING_NAMESPACE_UNDERSCORE.
-configure_file(
-  ${CMAKE_CURRENT_LIST_DIR}/ctkMacroWrapPythonQtModuleInit.cpp.in
-  ${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
-  )
-

+ 228 - 0
CMake/ctkWrapPythonQt.py

@@ -0,0 +1,228 @@
+
+import errno
+import os
+import re
+from string import Template
+
+PYTHONQT_WRAPPER_WITH_PARENT = Template("""
+//-----------------------------------------------------------------------------
+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; }
+};
+""")
+
+PYTHONQT_WRAPPER_WITHOUT_PARENT = Template("""
+//-----------------------------------------------------------------------------
+class PythonQtWrapper_${className} : public QObject
+{
+Q_OBJECT
+public:
+public Q_SLOTS:
+  ${className}* new_${className}()
+    {
+    return new ${className}();
+    }
+  void delete_${className}(${className}* obj) { delete obj; }
+};
+""")
+
+def _mkdir_p(path):
+    """See """
+    try:
+        os.makedirs(path)
+    except OSError as exc:
+        if exc.errno == errno.EEXIST and os.path.isdir(path):
+            pass
+        else: raise
+
+def ctk_wrap_pythonqt(target, namespace, output_dir, input_files, extra_verbose):
+    if extra_verbose:
+        print("target: %s" % target)
+        print("namespace: %s" % namespace)
+        print("output_dir: %s" % output_dir)
+        print("input_files: %s" % input_files)
+    
+    _mkdir_p(output_dir)
+    
+    includes = []
+    pythonqtWrappers = []
+    registerclasses = []
+    namespace = namespace.replace('.', '_')
+    
+    for input_file in input_files:
+        filename = os.path.basename(input_file)
+        if extra_verbose:
+            print("Wrapping %s" % filename)
+       
+        # what is the filename without the extension
+        filename_we = os.path.splitext(filename)[0]
+        
+        includes.append('#include "%s.h"' % filename_we)
+
+        # Extract classname - NOTE: We assume the filename matches the associated class
+        className = filename_we
+        if extra_verbose:
+            print("\tclassName:%s" % className)
+
+        # Extract parent classname
+        parentClassName = None
+
+        # Read input files
+        with open(input_file) as f:
+            content = f.read()
+            
+            # Skip wrapping if file do NOT contain Q_OBJECT
+            if 'Q_OBJECT' not in content:
+                if extra_verbose:
+                    print("\tskipping - No Q_OBJECT macro")
+                continue
+
+            # Skip wrapping if constructor doesn't match:
+            #    my_class()
+            #    my_class(QObject* newParent ...)
+            #    my_class(QWidget* newParent ...)
+            # Constructor with either QWidget or QObject as first parameter
+            regex = r"[^~]%s[\s\n]*\([\s\n]*((QObject|QWidget)[\s\n]*\*[\s\n]*\w+[\s\n]*(\=[\s\n]*(0|NULL)|,.*\=.*\)|\)|\)))" % className
+            res = re.search(regex, content, re.MULTILINE)
+            if res is None:
+                if extra_verbose:
+                    print("\tskipping - Missing expected constructor signature")
+                continue
+     
+            # Skip wrapping if object has a virtual pure method
+            # "x3b" is the unicode for semicolon
+            regex = r"virtual[\w\n\s\*\(\)]+\=[\s\n]*(0|NULL)[\s\n]*\x3b"
+            res = re.search(regex, content, re.MULTILINE)
+            if res is not None:
+                if extra_verbose:
+                    print("skipping - Contains a virtual pure method")
+                continue
+
+            if parentClassName is None:
+                # Does constructor signature is of the form: myclass()
+                regex = r"[^~]%s[\s\n]*\([\s\n]*\)" % className
+                res = re.search(regex, content, re.MULTILINE)
+           
+                if res is not None:
+                    parentClassName = ""
+                    if extra_verbose:
+                        print("\tconstructor of the form: %s()" % className)
+
+            if parentClassName is None:
+                # Does constructor signature is of the form: myclass(QObject * parent ...)
+                regex = r"%s[\s\n]*\([\s\n]*QObject[\s\n]*\*[\s\n]*\w+[\s\n]*(\=[\s\n]*(0|NULL)|,.*\=.*\)|\))" % className
+                res = re.search(regex, content, re.MULTILINE)
+                if res is not None:
+                    parentClassName = "QObject"
+                    if extra_verbose:
+                        print("\tconstructor of the form: %s(QObject * parent ... )" % className)
+
+            if parentClassName is None:
+                # Does constructor signature is of the form: myclass(QWidget * parent ...)
+                regex = r"%s[\s\n]*\([\s\n]*QWidget[\s\n]*\*[\s\n]*\w+[\s\n]*(\=[\s\n]*(0|NULL)|,.*\=.*\)|\))" % className
+                res = re.search(regex, content, re.MULTILINE)
+                if res is not None:
+                    parentClassName = "QWidget"
+                    if extra_verbose:
+                        print("\tconstructor of the form: %s(QWidget * parent ... )" % className)
+                        
+        # Generate PythonQtWrapper class
+        if parentClassName == "QObject" or parentClassName == "QWidget":
+            pythonqtWrappers.append(
+                PYTHONQT_WRAPPER_WITH_PARENT.substitute(className = className, parentClassName = parentClassName))
+            
+        elif parentClassName == "":
+            pythonqtWrappers.append(PYTHONQT_WRAPPER_WITHOUT_PARENT.substitute(className = className))
+
+        else: # Case parentClassName is None
+            raise Exception("Problem wrapping %s" % input_file)
+        
+        # Generate code allowing to register the class metaobject and its associated "light" wrapper
+        registerclasses.append(
+        Template("""
+  PythonQt::self()->registerClass(
+  &${className}::staticMetaObject, "${target}",
+  PythonQtCreateObject<PythonQtWrapper_${className}>);
+  """).substitute(className = className, target = target))
+
+    output_header = output_dir + "/" + namespace + "_" + target + ".h"
+    if extra_verbose:
+        print("output_header: %s" % output_header)
+    # Write master include file
+    with open(output_header, "w") as f:
+        f.write(Template(
+"""
+//
+// File auto-generated by ctkWrapPythonQt.py
+//
+
+#ifndef __${namespace}_${target}_h
+#define __${namespace}_${target}_h
+
+#include <QWidget>
+${includes}
+${pythonqtWrappers}
+#endif
+""").substitute(namespace = namespace, target = target, includes = '\n'.join(includes), pythonqtWrappers = '\n'.join(pythonqtWrappers)))
+
+    output_cpp = output_dir + "/" + namespace + "_" + target + "_init.cpp"
+    if extra_verbose:
+        print("output_cpp: %s" % output_cpp)
+    with open(output_cpp , "w") as f:
+        # Write wrapper header
+        f.write(Template(
+"""
+//
+// File auto-generated by ctkWrapPythonQt.py
+//
+
+#include <PythonQt.h>
+#include "${namespace}_${target}.h"
+
+void PythonQt_init_${namespace}_${target}(PyObject* module)
+{
+  Q_UNUSED(module);
+  ${registerclasses}
+}
+""").substitute(namespace = namespace, target = target, registerclasses = '\n'.join(registerclasses)))
+
+if __name__ == '__main__':
+    from optparse import OptionParser
+    usage = "usage: %prog [options] <output_file> <input_file> [<input_file1> [...]]"
+    parser = OptionParser(usage=usage)
+    parser.add_option("-t", "--target",
+                      dest="target", action="store", type="string",
+                      help="Name of the associated library")
+    parser.add_option("-n", "--namespace",
+                      dest="namespace", action="store", type="string",
+                      help="Wrapping namespace")
+    parser.add_option("--output-dir",
+                      dest="output_dir", action="store", type="string",
+                      help="Output directory")
+    parser.add_option("-v", "--verbose",
+                      dest="verbose", action="store_true",
+                      help="Print verbose information")
+    parser.add_option("--extra-verbose",
+                      dest="extra_verbose", action="store_true",
+                      help="Print extra verbose information")
+
+    (options, args) = parser.parse_args()
+
+    #if len(args) < 2:
+    #    parser.error("arguments '%s' are required !" % '<output_file> <input_file>')
+
+    if options.extra_verbose:
+        options.verbose = True
+
+    ctk_wrap_pythonqt(options.target, options.namespace, options.output_dir, args, options.extra_verbose)
+      
+    if options.verbose:
+        print("Wrapped %d files" % len(args))

+ 97 - 0
CMake/ctk_compile_python_scripts.cmake.in

@@ -0,0 +1,97 @@
+
+# Generate compile_@target@_python_scripts.py
+file(WRITE "@compile_all_script@" "
+#
+# Generated by ctkMacroCompilePythonScript CMake macro
+#
+
+#
+# Copied function 'compileall.compile_file' introduced in python 2.7 so that code compiled
+# using python 2.6 works.
+#
+# This version of the function has been copied from:
+#   https://github.com/jonashaag/cpython/blob/ce5e5df0c9d8098da05dee26e12ffe2aa331889e/Lib/compileall.py#L61-111
+#
+
+import os
+import sys
+import py_compile
+import struct
+import imp
+
+def ctk_compile_file(fullname, ddir=None, force=0, rx=None, quiet=0):
+    \"\"\"Byte-compile one file.
+
+    Arguments (only fullname is required):
+
+    fullname:  the file to byte-compile
+    ddir:      if given, the directory name compiled in to the
+               byte-code file.
+    force:     if 1, force compilation, even if timestamps are up-to-date
+    quiet:     if 1, be quiet during compilation
+    \"\"\"
+    success = 1
+    name = os.path.basename(fullname)
+    if ddir is not None:
+        dfile = os.path.join(ddir, name)
+    else:
+        dfile = None
+    if rx is not None:
+        mo = rx.search(fullname)
+        if mo:
+            return success
+    if os.path.isfile(fullname):
+        head, tail = name[:-3], name[-3:]
+        if tail == '.py':
+            if not force:
+                try:
+                    mtime = int(os.stat(fullname).st_mtime)
+                    expect = struct.pack('<4sl', imp.get_magic(), mtime)
+                    cfile = fullname + (__debug__ and 'c' or 'o')
+                    with open(cfile, 'rb') as chandle:
+                        actual = chandle.read(8)
+                    if expect == actual:
+                        return success
+                except IOError:
+                    pass
+            if not quiet:
+                print 'Compiling', fullname, '...'
+            try:
+                ok = py_compile.compile(fullname, None, dfile, True)
+            except py_compile.PyCompileError,err:
+                if quiet:
+                    print 'Compiling', fullname, '...'
+                print err.msg
+                success = 0
+            except IOError, e:
+                print 'Sorry', e
+                success = 0
+            else:
+                if ok == 0:
+                    success = 0
+    return success
+
+# Based on paraview/VTK/Wrapping/Python/compile_all_vtk.py.in
+
+@_compileall_code@
+file = open('@CMAKE_CURRENT_BINARY_DIR@/python_compile_@target@_complete', 'w')
+file.write('Done')
+")
+
+set(ENV{PYTHONPATH} "@CTK_PYTHON_COMPILE_FILE_SCRIPT_DIR@")
+
+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_EXECUTABLE@" "@compile_all_script@"
+  RESULT_VARIABLE result_var
+  )
+if(NOT result_var STREQUAL 0)
+  message(FATAL_ERROR "Failed to compile python scripts: @target@ ")
+endif()

+ 0 - 59
CMakeExternals/PythonQtGenerator.cmake

@@ -1,59 +0,0 @@
-#
-# PythonQtGenerator
-#
-
-set(proj PythonQtGenerator)
-
-# Sanity checks
-if(DEFINED PYTHONQTGENERATOR_EXECUTABLE AND NOT EXISTS ${PYTHONQTGENERATOR_EXECUTABLE})
-  message(FATAL_ERROR "PYTHONQTGENERATOR_EXECUTABLE variable is defined but corresponds to non-existing executable")
-endif()
-
-set(${proj}_DEPENDENCIES PythonQt)
-
-ExternalProject_Include_Dependencies(${proj}
-  PROJECT_VAR proj
-  DEPENDS_VAR ${proj}_DEPENDENCIES
-  EP_ARGS_VAR ${proj}_EXTERNAL_PROJECT_ARGS
-  USE_SYSTEM_VAR ${CMAKE_PROJECT_NAME}_USE_SYSTEM_${proj}
-  )
-
-if(${CMAKE_PROJECT_NAME}_USE_SYSTEM_${proj})
-  message(FATAL_ERROR "Enabling ${CMAKE_PROJECT_NAME}_USE_SYSTEM_${proj} is not supported !")
-endif()
-
-if(NOT DEFINED PYTHONQTGENERATOR_EXECUTABLE)
-
-  #
-  # PythonQtGenerator is the tool allowing to generate the PythonQt decorators using
-  # typesystem xml files. If called without any option, it will generate the bindings for Qt.
-  #
-  # See http://www.pyside.org/docs/apiextractor/typesystem.html
-  # See http://doc.trolltech.com/qtjambi-4.5.2_01/com/trolltech/qt/qtjambi-typesystem.html
-  # See http://qt.gitorious.org/qt-labs/qtscriptgenerator
-  #
-
-  ExternalProject_Add(${proj}
-    ${${proj}_EXTERNAL_PROJECT_ARGS}
-    SOURCE_DIR ${CMAKE_BINARY_DIR}/PythonQt/generator
-    BINARY_DIR ${proj}-build
-    PREFIX ${proj}${ep_suffix}
-    DOWNLOAD_COMMAND ""
-    INSTALL_COMMAND ""
-    CMAKE_CACHE_ARGS
-      ${ep_common_cache_args}
-      -DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE}
-    DEPENDS
-      ${${proj}_DEPENDENCIES} # To make sure the generator code is checked out, let's depend on PythonQt
-    )
-
-  set(PYTHONQTGENERATOR_EXECUTABLE ${CMAKE_BINARY_DIR}/PythonQtGenerator-build/PythonQtGenerator)
-
-else()
-  ExternalProject_Add_Empty(${proj} DEPENDS ${${proj}_DEPENDENCIES})
-endif()
-
-mark_as_superbuild(
-  VARS PYTHONQTGENERATOR_EXECUTABLE:FILEPATH
-  LABELS "FIND_PACKAGE"
-  )

+ 3 - 12
CMakeLists.txt

@@ -229,6 +229,7 @@ endforeach()
 foreach(file
   Libs/ctkExport.h.in
   CMake/ctkLinkerAsNeededFlagCheck.cmake
+  CMake/ctk_compile_python_scripts.cmake.in
   )
   install(FILES ${file} DESTINATION ${CTK_INSTALL_CMAKE_DIR} COMPONENT Development)
 endforeach()
@@ -815,17 +816,11 @@ ctkMacroValidateBuildOptions("${CTK_BINARY_DIR}" "${DGraph_EXECUTABLE}" "${targe
 
 #-----------------------------------------------------------------------------
 # CTK Python wrapping
-# Enable CTK_LIB_Scripting/Python/Core if either CTK_ENABLE_Python_Wrapping OR CTK_WRAP_PYTHONQT_FULL
+# Enable CTK_LIB_Scripting/Python/Core if CTK_ENABLE_Python_Wrapping is ON
 #
 set(CTK_WRAP_PYTHONQT_LIGHT ${CTK_ENABLE_Python_Wrapping})
-option(CTK_WRAP_PYTHONQT_FULL "Experimental - Wrap CTK classes using Qt meta-object system into Python language" OFF)
-mark_as_advanced(CTK_WRAP_PYTHONQT_FULL)
-mark_as_superbuild(CTK_WRAP_PYTHONQT_FULL)
-if(CTK_WRAP_PYTHONQT_FULL AND CTK_WRAP_PYTHONQT_LIGHT)
-  message(FATAL_ERROR "CTK_ENABLE_Python_Wrapping AND CTK_WRAP_PYTHONQT_FULL options are mutually exclusive. Please enable only one !")
-endif()
 
-set(logical_expr CTK_WRAP_PYTHONQT_LIGHT OR CTK_WRAP_PYTHONQT_FULL)
+set(logical_expr CTK_WRAP_PYTHONQT_LIGHT)
 if((${logical_expr}) AND NOT CTK_LIB_Scripting/Python/Core)
   set(CTK_LIB_Scripting/Python/Core ON CACHE BOOL "Build the Python Core library" FORCE)
   set(enabling_msg)
@@ -924,10 +919,6 @@ if(CTK_USE_QTTESTING)
   list(APPEND CTK_DEPENDENCIES QtTesting)
 endif()
 
-if(CTK_WRAP_PYTHONQT_FULL)
-  list(APPEND CTK_DEPENDENCIES PythonQtGenerator)
-endif()
-
 #-----------------------------------------------------------------------------
 # Check out the ExternalProjectsContrib repository
 if(CTK_USE_CONTRIBUTED_PLUGINS)

+ 1 - 1
Libs/CommandLineModules/Backend/FunctionPointer/CMakeLists.txt

@@ -53,7 +53,7 @@ ctkMacroBuildLib(
 
 target_link_libraries(${PROJECT_NAME} ${QT_LIBRARIES})
 
-if(CTK_WRAP_PYTHONQT_FULL OR CTK_WRAP_PYTHONQT_LIGHT)
+if(CTK_WRAP_PYTHONQT_LIGHT)
   ctkMacroBuildLibWrapper(
     TARGET ${PROJECT_NAME}
     SRCS ${KIT_SRCS}

+ 1 - 1
Libs/CommandLineModules/Backend/LocalProcess/CMakeLists.txt

@@ -52,7 +52,7 @@ ctkMacroBuildLib(
 
 target_link_libraries(${PROJECT_NAME} ${QT_LIBRARIES})
 
-if(CTK_WRAP_PYTHONQT_FULL OR CTK_WRAP_PYTHONQT_LIGHT)
+if(CTK_WRAP_PYTHONQT_LIGHT)
   ctkMacroBuildLibWrapper(
     TARGET ${PROJECT_NAME}
     SRCS ${KIT_SRCS}

+ 1 - 1
Libs/CommandLineModules/Backend/XMLChecker/CMakeLists.txt

@@ -48,7 +48,7 @@ ctkMacroBuildLib(
 
 target_link_libraries(${PROJECT_NAME} ${QT_LIBRARIES})
 
-if(CTK_WRAP_PYTHONQT_FULL OR CTK_WRAP_PYTHONQT_LIGHT)
+if(CTK_WRAP_PYTHONQT_LIGHT)
   ctkMacroBuildLibWrapper(
     TARGET ${PROJECT_NAME}
     SRCS ${KIT_SRCS}

+ 1 - 1
Libs/CommandLineModules/Core/CMakeLists.txt

@@ -96,7 +96,7 @@ ctkMacroBuildLib(
 
 target_link_libraries(${PROJECT_NAME} ${QT_LIBRARIES})
 
-if(CTK_WRAP_PYTHONQT_FULL OR CTK_WRAP_PYTHONQT_LIGHT)
+if(CTK_WRAP_PYTHONQT_LIGHT)
   ctkMacroBuildLibWrapper(
     TARGET ${PROJECT_NAME}
     SRCS ${KIT_SRCS}

+ 1 - 1
Libs/CommandLineModules/Frontend/QtGui/CMakeLists.txt

@@ -60,7 +60,7 @@ ctkMacroBuildLib(
 
 target_link_libraries(${PROJECT_NAME} ${QT_LIBRARIES})
 
-if(CTK_WRAP_PYTHONQT_FULL OR CTK_WRAP_PYTHONQT_LIGHT)
+if(CTK_WRAP_PYTHONQT_LIGHT)
   ctkMacroBuildLibWrapper(
     TARGET ${PROJECT_NAME}
     SRCS ${KIT_SRCS}

+ 1 - 1
Libs/CommandLineModules/Frontend/QtWebKit/CMakeLists.txt

@@ -53,7 +53,7 @@ ctkMacroBuildLib(
 
 target_link_libraries(${PROJECT_NAME} ${QT_LIBRARIES})
 
-if(CTK_WRAP_PYTHONQT_FULL OR CTK_WRAP_PYTHONQT_LIGHT)
+if(CTK_WRAP_PYTHONQT_LIGHT)
   ctkMacroBuildLibWrapper(
     TARGET ${PROJECT_NAME}
     SRCS ${KIT_SRCS}

+ 1 - 1
Libs/Core/CMakeLists.txt

@@ -144,7 +144,7 @@ elseif(WIN32 AND NOT MINGW)
   target_link_libraries(${PROJECT_NAME} dbghelp)
 endif()
 
-if(CTK_WRAP_PYTHONQT_FULL OR CTK_WRAP_PYTHONQT_LIGHT)
+if(CTK_WRAP_PYTHONQT_LIGHT)
   ctkMacroBuildLibWrapper(
     TARGET ${PROJECT_NAME}
     SRCS ${KIT_SRCS}

+ 1 - 1
Libs/DICOM/Core/CMakeLists.txt

@@ -145,7 +145,7 @@ if(DEFINED DCMTK_HAVE_CONFIG_H_OPTIONAL AND NOT DCMTK_HAVE_CONFIG_H_OPTIONAL)
 endif()
 
 
-if(CTK_WRAP_PYTHONQT_FULL OR CTK_WRAP_PYTHONQT_LIGHT)
+if(CTK_WRAP_PYTHONQT_LIGHT)
   ctkMacroBuildLibWrapper(
     TARGET ${PROJECT_NAME}
     SRCS ${KIT_SRCS}

+ 1 - 1
Libs/DICOM/Widgets/CMakeLists.txt

@@ -95,7 +95,7 @@ ctkMacroBuildLib(
   LIBRARY_TYPE ${CTK_LIBRARY_MODE}
   )
 
-if(CTK_WRAP_PYTHONQT_FULL OR CTK_WRAP_PYTHONQT_LIGHT)
+if(CTK_WRAP_PYTHONQT_LIGHT)
   ctkMacroBuildLibWrapper(
     TARGET ${PROJECT_NAME}
     SRCS ${KIT_SRCS}

+ 1 - 1
Libs/ImageProcessing/ITK/Core/CMakeLists.txt

@@ -45,7 +45,7 @@ ctkMacroBuildLib(
   LIBRARY_TYPE ${CTK_LIBRARY_MODE}
   )
 
-if(CTK_WRAP_PYTHONQT_FULL OR CTK_WRAP_PYTHONQT_LIGHT)
+if(CTK_WRAP_PYTHONQT_LIGHT)
   ctkMacroBuildLibWrapper(
     TARGET ${PROJECT_NAME}
     SRCS ${KIT_SRCS}

+ 1 - 1
Libs/PluginFramework/CMakeLists.txt

@@ -152,7 +152,7 @@ ctkMacroBuildLib(
   LIBRARY_TYPE ${CTK_LIBRARY_MODE}
   )
 
-if(CTK_WRAP_PYTHONQT_FULL OR CTK_WRAP_PYTHONQT_LIGHT)
+if(CTK_WRAP_PYTHONQT_LIGHT)
   ctkMacroBuildLibWrapper(
     TARGET ${PROJECT_NAME}
     SRCS ${KIT_SRCS}

+ 1 - 1
Libs/QtTesting/CMakeLists.txt

@@ -177,7 +177,7 @@ ctkMacroBuildLib(
   LIBRARY_TYPE ${CTK_LIBRARY_MODE}
   )
 
-if(CTK_WRAP_PYTHONQT_FULL OR CTK_WRAP_PYTHONQT_LIGHT)
+if(CTK_WRAP_PYTHONQT_LIGHT)
   ctkMacroBuildLibWrapper(
     TARGET ${PROJECT_NAME}
     SRCS ${KIT_SRCS}

+ 1 - 1
Libs/Scripting/Python/Core/Python/CMakeLists.txt

@@ -8,7 +8,7 @@ set(KIT_PYTHON_SCRIPTS
 # the comma separated list of package to load
 set(CTK_PYTHON_WRAPPED_LIBRARIES)
 
-if(CTK_WRAP_PYTHONQT_LIGHT OR CTK_WRAP_PYTHONQT_FULL)
+if(CTK_WRAP_PYTHONQT_LIGHT)
 
   foreach(lib_name ${CTK_LIBS})
     if(${CTK_LIB_${lib_name}})

+ 1 - 1
Libs/Scripting/Python/Widgets/CMakeLists.txt

@@ -42,7 +42,7 @@ ctkMacroBuildLib(
   LIBRARY_TYPE ${CTK_LIBRARY_MODE}
   )
 
-if(CTK_WRAP_PYTHONQT_FULL OR CTK_WRAP_PYTHONQT_LIGHT)
+if(CTK_WRAP_PYTHONQT_LIGHT)
   ctkMacroBuildLibWrapper(
     TARGET ${PROJECT_NAME}
     SRCS ${KIT_SRCS}

+ 1 - 1
Libs/Visualization/VTK/Core/CMakeLists.txt

@@ -113,7 +113,7 @@ ctkMacroBuildLib(
   LIBRARY_TYPE ${CTK_LIBRARY_MODE}
   )
 
-if(CTK_WRAP_PYTHONQT_FULL OR CTK_WRAP_PYTHONQT_LIGHT)
+if(CTK_WRAP_PYTHONQT_LIGHT)
   ctkMacroBuildLibWrapper(
     TARGET ${PROJECT_NAME}
     SRCS ${KIT_SRCS}

+ 1 - 1
Libs/Visualization/VTK/Widgets/CMakeLists.txt

@@ -160,7 +160,7 @@ ctkMacroBuildLib(
   LIBRARY_TYPE ${CTK_LIBRARY_MODE}
   )
 
-if(CTK_WRAP_PYTHONQT_FULL OR CTK_WRAP_PYTHONQT_LIGHT)
+if(CTK_WRAP_PYTHONQT_LIGHT)
   ctkMacroBuildLibWrapper(
     TARGET ${PROJECT_NAME}
     SRCS ${KIT_SRCS}

+ 1 - 1
Libs/Visualization/XIP/CMakeLists.txt

@@ -41,7 +41,7 @@ ctkMacroBuildLib(
   LIBRARY_TYPE ${CTK_LIBRARY_MODE}
   )
 
-if(CTK_WRAP_PYTHONQT_FULL OR CTK_WRAP_PYTHONQT_LIGHT)
+if(CTK_WRAP_PYTHONQT_LIGHT)
   ctkMacroBuildLibWrapper(
     TARGET ${PROJECT_NAME}
     SRCS ${KIT_SRCS}

+ 1 - 1
Libs/Widgets/CMakeLists.txt

@@ -415,7 +415,7 @@ ctkMacroBuildLib(
   LIBRARY_TYPE ${CTK_LIBRARY_MODE}
   )
 
-if(CTK_WRAP_PYTHONQT_FULL OR CTK_WRAP_PYTHONQT_LIGHT)
+if(CTK_WRAP_PYTHONQT_LIGHT)
   ctkMacroBuildLibWrapper(
     TARGET ${PROJECT_NAME}
     SRCS ${KIT_SRCS}