ctkMacroCompilePythonScript.cmake 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. #
  2. # Based on ParaView/VTK/Utilities/vtkTclTest2Py/CMakeLists.txt and
  3. # ParaView/VTK/Wrapping/Python/CMakeLists.txt
  4. #
  5. #
  6. # By globally defining the variable CTK_COMPILE_PYTHON_SCRIPTS_GLOBAL_TARGET_NAME to a
  7. # non-empty string or by specifying the macro option 'GLOBAL_TARGET',
  8. # the following targets will be defined for the whole build system:
  9. # - Copy<GLOBAL_TARGET_NAME>PythonResourceFiles
  10. # - Copy<GLOBAL_TARGET_NAME>PythonScriptFiles
  11. # - Compile<GLOBAL_TARGET_NAME>PythonFiles
  12. #
  13. # For complex projects, this can help reducing the number of targets and
  14. # simplify the manual rebuild of copy and compile targets.
  15. #
  16. include(${CTK_CMAKE_DIR}/ctkMacroParseArguments.cmake)
  17. set(CTK_PYTHON_COMPILE_FILE_SCRIPT_DIR "${CMAKE_BINARY_DIR}/CMakeFiles")
  18. #! \ingroup CMakeAPI
  19. macro(ctkMacroCompilePythonScript)
  20. ctkMacroParseArguments(MY
  21. "TARGET_NAME;SCRIPTS;RESOURCES;SOURCE_DIR;DESTINATION_DIR;INSTALL_DIR"
  22. "NO_INSTALL_SUBDIR;GLOBAL_TARGET"
  23. ${ARGN}
  24. )
  25. # Sanity checks
  26. foreach(varname TARGET_NAME SCRIPTS DESTINATION_DIR INSTALL_DIR)
  27. if(NOT DEFINED MY_${varname})
  28. message(FATAL_ERROR "${varname} is mandatory")
  29. endif()
  30. endforeach()
  31. if(NOT DEFINED MY_SOURCE_DIR)
  32. set(MY_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
  33. endif()
  34. if("${CTK_COMPILE_PYTHON_SCRIPTS_GLOBAL_TARGET_NAME}" STREQUAL "")
  35. set(target ${MY_TARGET_NAME})
  36. else()
  37. set(MY_GLOBAL_TARGET TRUE)
  38. set(target ${CTK_COMPILE_PYTHON_SCRIPTS_GLOBAL_TARGET_NAME})
  39. endif()
  40. # Since 'add_custom_command' doesn't play nicely with path having multiple
  41. # consecutive slashes. Let's make sure there are no trailing slashes.
  42. get_filename_component(MY_SOURCE_DIR ${MY_SOURCE_DIR} REALPATH)
  43. get_filename_component(MY_DESTINATION_DIR ${MY_DESTINATION_DIR} REALPATH)
  44. set(input_python_files)
  45. foreach(file ${MY_SCRIPTS})
  46. # Append "py" extension if needed
  47. get_filename_component(file_ext ${file} EXT)
  48. if(NOT "${file_ext}" MATCHES "py")
  49. set(file "${file}.py")
  50. endif()
  51. if(NOT IS_ABSOLUTE ${file})
  52. set(src "${MY_SOURCE_DIR}/${file}")
  53. else()
  54. set(src "${file}")
  55. endif()
  56. set(tgt_file ${file})
  57. if(IS_ABSOLUTE ${file})
  58. set(src ${file})
  59. file(RELATIVE_PATH tgt_file ${CMAKE_CURRENT_BINARY_DIR} ${file})
  60. endif()
  61. set_property(GLOBAL APPEND PROPERTY
  62. _CTK_${target}_PYTHON_SCRIPTS "${src}|${tgt_file}|${MY_DESTINATION_DIR}")
  63. endforeach()
  64. if(DEFINED MY_RESOURCES)
  65. set(resource_input_files)
  66. foreach(file ${MY_RESOURCES})
  67. if(NOT IS_ABSOLUTE ${file})
  68. set(src "${MY_SOURCE_DIR}/${file}")
  69. else()
  70. set(src "${file}")
  71. endif()
  72. set_property(GLOBAL APPEND PROPERTY
  73. _CTK_${target}_PYTHON_RESOURCES "${src}|${file}|${MY_DESTINATION_DIR}")
  74. endforeach()
  75. endif()
  76. set(MY_DIRECTORY_TO_INSTALL ${MY_DESTINATION_DIR})
  77. if(MY_NO_INSTALL_SUBDIR)
  78. set(MY_DIRECTORY_TO_INSTALL ${MY_DESTINATION_DIR}/)
  79. endif()
  80. # Install python module / resources directory
  81. install(DIRECTORY "${MY_DIRECTORY_TO_INSTALL}"
  82. DESTINATION "${MY_INSTALL_DIR}" COMPONENT RuntimeLibraries
  83. USE_SOURCE_PERMISSIONS)
  84. if(NOT MY_GLOBAL_TARGET)
  85. ctkFunctionAddCompilePythonScriptTargets(${target})
  86. endif()
  87. endmacro()
  88. function(_ctk_add_copy_python_files_target target type)
  89. # 'type' is expected to be either "Resource" or "Script"
  90. set(target_name Copy${target}Python${type}Files)
  91. if(NOT TARGET ${target_name})
  92. string(TOUPPER ${type} type_upper)
  93. get_property(entries GLOBAL PROPERTY _CTK_${target}_PYTHON_${type_upper}S)
  94. set(input_files)
  95. set(copied_files)
  96. foreach(entry IN LISTS entries)
  97. string(REPLACE "|" ";" tuple "${entry}")
  98. list(GET tuple 0 src)
  99. list(GET tuple 1 tgt_file)
  100. list(GET tuple 2 dest_dir)
  101. set(tgt ${dest_dir}/${tgt_file})
  102. add_custom_command(DEPENDS ${src}
  103. COMMAND ${CMAKE_COMMAND} -E copy ${src} ${tgt}
  104. OUTPUT ${tgt}
  105. COMMENT "Copying python ${type}: ${tgt_file}")
  106. list(APPEND input_files ${src})
  107. list(APPEND copied_files ${tgt})
  108. endforeach()
  109. if(entries)
  110. add_custom_target(${target_name} ALL DEPENDS ${copied_files} ${ARGN})
  111. endif()
  112. endif()
  113. endfunction()
  114. function(_ctk_add_compile_python_directories_target target)
  115. set(target_name Compile${target}PythonFiles)
  116. if(NOT TARGET ${target_name})
  117. # Byte compile the Python files.
  118. set(compile_all_script "${CMAKE_CURRENT_BINARY_DIR}/compile_${target}_python_scripts.py")
  119. set(_compileall_code )
  120. get_property(entries GLOBAL PROPERTY _CTK_${target}_PYTHON_SCRIPTS)
  121. list(REMOVE_DUPLICATES entries)
  122. foreach(entry IN LISTS entries)
  123. string(REPLACE "|" ";" tuple "${entry}")
  124. list(GET tuple 1 tgt_file)
  125. list(GET tuple 2 dest_dir)
  126. set(tgt ${dest_dir}/${tgt_file})
  127. set(_compileall_code "${_compileall_code}\nctk_compile_file('${tgt}', force=1)")
  128. endforeach()
  129. find_package(PythonInterp REQUIRED)
  130. find_package(PythonLibs REQUIRED)
  131. # Extract python lib path
  132. get_filename_component(PYTHON_LIBRARY_PATH ${PYTHON_LIBRARY} PATH)
  133. # Configure cmake script associated with the custom command
  134. # required to properly update the library path with PYTHON_LIBRARY_PATH
  135. set(compile_all_cmake_script "${CMAKE_CURRENT_BINARY_DIR}/compile_${target}_python_scripts.cmake")
  136. configure_file(
  137. ${CTK_CMAKE_DIR}/ctk_compile_python_scripts.cmake.in
  138. ${compile_all_cmake_script}
  139. @ONLY
  140. )
  141. add_custom_command(
  142. COMMAND ${CMAKE_COMMAND} -P ${compile_all_cmake_script}
  143. DEPENDS Copy${target}PythonScriptFiles ${compile_all_cmake_script}
  144. OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/python_compile_${target}_complete"
  145. COMMENT "Compiling python scripts: ${target}"
  146. )
  147. add_custom_target(${target_name} ALL
  148. DEPENDS
  149. ${CMAKE_CURRENT_BINARY_DIR}/python_compile_${target}_complete
  150. )
  151. endif()
  152. endfunction()
  153. function(ctkFunctionAddCompilePythonScriptTargets target)
  154. _ctk_add_copy_python_files_target(${target} Script ${ARGN})
  155. _ctk_add_copy_python_files_target(${target} Resource ${ARGN})
  156. _ctk_add_compile_python_directories_target(${target})
  157. endfunction()