瀏覽代碼

Compile python scripts explicitly instead of compiling an entire folder

Given the fact multiple compile targets can be associated with the same
destination directory, compiling each script explicitly will prevent two
compile targets build in parallel from compiling the same folder.
Jean-Christophe Fillion-Robin 12 年之前
父節點
當前提交
5800b08f53
共有 1 個文件被更改,包括 83 次插入20 次删除
  1. 83 20
      CMake/ctkMacroCompilePythonScript.cmake

+ 83 - 20
CMake/ctkMacroCompilePythonScript.cmake

@@ -59,28 +59,21 @@ macro(ctkMacroCompilePythonScript)
     endif()
 
     set(src "${MY_SOURCE_DIR}/${file}")
-    set(tgt "${MY_DESTINATION_DIR}/${file}")
+    set(tgt_file ${file})
     if(IS_ABSOLUTE ${file})
       set(src ${file})
       file(RELATIVE_PATH tgt_file ${CMAKE_CURRENT_BINARY_DIR} ${file})
-      set(tgt "${MY_DESTINATION_DIR}/${tgt_file}")
     endif()
-    
     set_property(GLOBAL APPEND PROPERTY
-      _CTK_${target}_PYTHON_SCRIPTS "${src}|${tgt}")
+      _CTK_${target}_PYTHON_SCRIPTS "${src}|${tgt_file}|${MY_DESTINATION_DIR}")
   endforeach()
-  
-  
-  set_property(GLOBAL APPEND PROPERTY
-      _CTK_${target}_PYTHON_DESTINATION_DIRS "${MY_DESTINATION_DIR}")
       
   if(DEFINED MY_RESOURCES)
     set(resource_input_files)
     foreach(file ${MY_RESOURCES})
       set(src "${CMAKE_CURRENT_SOURCE_DIR}/${file}")
-      set(tgt "${MY_DESTINATION_DIR}/${file}")
       set_property(GLOBAL APPEND PROPERTY
-      _CTK_${target}_PYTHON_RESOURCES "${src}|${tgt}")
+      _CTK_${target}_PYTHON_RESOURCES "${src}|${file}|${MY_DESTINATION_DIR}")
     endforeach()
   endif()
 
@@ -111,12 +104,13 @@ function(_ctk_add_copy_python_files_target target type)
     foreach(entry IN LISTS entries)
       string(REPLACE "|" ";" tuple "${entry}")
       list(GET tuple 0 src)
-      list(GET tuple 1 tgt)
-      get_filename_component(file ${src} NAME)
+      list(GET tuple 1 tgt_file)
+      list(GET tuple 2 dest_dir)
+      set(tgt ${dest_dir}/${tgt_file})
       add_custom_command(DEPENDS ${src}
                          COMMAND ${CMAKE_COMMAND} -E copy ${src} ${tgt}
                          OUTPUT ${tgt}
-                         COMMENT "Copying python ${type}: ${file}")
+                         COMMENT "Copying python ${type}: ${tgt_file}")
       list(APPEND input_files ${src})
       list(APPEND copied_files ${tgt})
     endforeach()
@@ -136,15 +130,19 @@ function(_ctk_add_compile_python_directories_target target)
   if(NOT TARGET ${target_name}) 
     # Byte compile the Python files.
     set(compile_all_script "${CMAKE_CURRENT_BINARY_DIR}/compile_${target}_python_scripts.py")
-    
+
     set(_compileall_code )
-    get_property(destination_dirs GLOBAL PROPERTY _CTK_${target}_PYTHON_DESTINATION_DIRS)
-    list(REMOVE_DUPLICATES destination_dirs)
-    foreach(destination_dir IN LISTS destination_dirs)
-      set(_compileall_code "${_compileall_code}\ncompileall.compile_dir('${destination_dir}')")
+    get_property(entries GLOBAL PROPERTY _CTK_${target}_PYTHON_SCRIPTS)
+    list(REMOVE_DUPLICATES entries)
+    foreach(entry IN LISTS entries)
+      string(REPLACE "|" ";" tuple "${entry}")
+      list(GET tuple 1 tgt_file)
+      list(GET tuple 2 dest_dir)
+      set(tgt ${dest_dir}/${tgt_file})
+      set(_compileall_code "${_compileall_code}\nctk_compile_file('${tgt}', force=1)")
     endforeach()
   
-    message(STATUS "Generate [${target_name}] compileall script: ${compile_all_script}")
+    message(STATUS "Generate [${target_name}] py_compile script: ${compile_all_script}")
     # Generate compile_${target}_python_scripts.py
     file(WRITE ${compile_all_script} "
 #
@@ -153,7 +151,72 @@ function(_ctk_add_compile_python_directories_target target)
 
 # Based on paraview/VTK/Wrapping/Python/compile_all_vtk.py.in
 
-import compileall
+import os
+import sys
+import py_compile
+import struct
+import imp
+
+#
+# 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
+#
+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
+
+
 @_compileall_code@
 file = open('@CMAKE_CURRENT_BINARY_DIR@/python_compile_@target@_complete', 'w')
 file.write('Done')