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