Browse Source

CMake: Byte-compile all .py files when building Panda

This also involves the creation a new include: Python.cmake

This file will contain utility functions for building Python
modules and installing Python packages.
Sam Edwards 7 years ago
parent
commit
2e2a8eae98
4 changed files with 99 additions and 45 deletions
  1. 2 3
      CMakeLists.txt
  2. 1 38
      cmake/macros/Interrogate.cmake
  3. 95 0
      cmake/macros/Python.cmake
  4. 1 4
      direct/CMakeLists.txt

+ 2 - 3
CMakeLists.txt

@@ -87,6 +87,7 @@ include(AddBisonTarget)     # Defines add_bison_target function
 include(AddFlexTarget)      # Defines add_flex_target function
 include(AddFlexTarget)      # Defines add_flex_target function
 include(BuildMetalib)       # Defines add_component_library AND add_metalib
 include(BuildMetalib)       # Defines add_component_library AND add_metalib
 include(CompositeSources)   # Defines composite_sources function
 include(CompositeSources)   # Defines composite_sources function
+include(Python)             # Defines add_python_target AND install_python_package
 include(Interrogate)        # Defines target_interrogate AND add_python_module
 include(Interrogate)        # Defines target_interrogate AND add_python_module
 include(RunPzip)            # Defines run_pzip function
 include(RunPzip)            # Defines run_pzip function
 include(Versioning)         # Hooks 'add_library' to apply VERSION/SOVERSION
 include(Versioning)         # Hooks 'add_library' to apply VERSION/SOVERSION
@@ -174,7 +175,5 @@ except ImportError as err:
   file(WRITE "${PROJECT_BINARY_DIR}/pandac/__init__.py" "")
   file(WRITE "${PROJECT_BINARY_DIR}/pandac/__init__.py" "")
 
 
   # Now install ourselves:
   # Now install ourselves:
-  install(
-    FILES "${PROJECT_BINARY_DIR}/pandac/__init__.py" "${PROJECT_BINARY_DIR}/pandac/PandaModules.py"
-    DESTINATION "${PYTHON_LIB_INSTALL_DIR}/pandac")
+  install_python_package("${PROJECT_BINARY_DIR}/pandac" LIB)
 endif()
 endif()

+ 1 - 38
cmake/macros/Interrogate.cmake

@@ -300,43 +300,6 @@ function(add_python_module module)
   set(ALL_INTERROGATE_MODULES "${ALL_INTERROGATE_MODULES}" CACHE INTERNAL "Internal variable")
   set(ALL_INTERROGATE_MODULES "${ALL_INTERROGATE_MODULES}" CACHE INTERNAL "Internal variable")
 endfunction(add_python_module)
 endfunction(add_python_module)
 
 
-#
-# Function: add_python_target(target [source1 [source2 ...]])
-# Build the provided source(s) as a Python extension module, linked against the
-# Python runtime library.
-#
-# Note that this also takes care of installation, unlike other target creation
-# commands in CMake.
-#
-function(add_python_target target)
-  if(NOT HAVE_PYTHON)
-    return()
-  endif()
-
-  string(REGEX REPLACE "^.*\\." "" basename "${target}")
-  set(sources ${ARGN})
-
-  add_library(${target} ${MODULE_TYPE} ${sources})
-  target_link_libraries(${target} PKG::PYTHON)
-
-  if(BUILD_SHARED_LIBS)
-    set_target_properties(${target} PROPERTIES
-      LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/panda3d"
-      OUTPUT_NAME "${basename}"
-      PREFIX ""
-      SUFFIX "${PYTHON_EXTENSION_SUFFIX}")
-
-    install(TARGETS ${target} DESTINATION "${PYTHON_ARCH_INSTALL_DIR}/panda3d")
-  else()
-    set_target_properties(${target} PROPERTIES
-      OUTPUT_NAME "${basename}"
-      PREFIX "libpython_panda3d_")
-
-    install(TARGETS ${target} DESTINATION lib)
-  endif()
-
-endfunction(add_python_target)
-
 
 
 if(INTERROGATE_PYTHON_INTERFACE AND BUILD_SHARED_LIBS)
 if(INTERROGATE_PYTHON_INTERFACE AND BUILD_SHARED_LIBS)
   # We have to create an __init__.py so that Python 2.x can recognize 'panda3d'
   # We have to create an __init__.py so that Python 2.x can recognize 'panda3d'
@@ -345,5 +308,5 @@ if(INTERROGATE_PYTHON_INTERFACE AND BUILD_SHARED_LIBS)
 
 
   # The Interrogate path needs to be installed to the architecture-dependent
   # The Interrogate path needs to be installed to the architecture-dependent
   # Python directory.
   # Python directory.
-  install(FILES "${PROJECT_BINARY_DIR}/panda3d/__init__.py" DESTINATION "${PYTHON_ARCH_INSTALL_DIR}/panda3d")
+  install_python_package("${PROJECT_BINARY_DIR}/panda3d")
 endif()
 endif()

+ 95 - 0
cmake/macros/Python.cmake

@@ -0,0 +1,95 @@
+# Filename: Python.cmake
+#
+# Description: This file provides support functions for building/installing
+#   Python extension modules and/or pure-Python packages.
+#
+# Functions:
+#   add_python_target(target [source1 [source2 ...]])
+#   install_python_package(path [ARCH/LIB])
+#
+
+#
+# Function: add_python_target(target [source1 [source2 ...]])
+# Build the provided source(s) as a Python extension module, linked against the
+# Python runtime library.
+#
+# Note that this also takes care of installation, unlike other target creation
+# commands in CMake.
+#
+function(add_python_target target)
+  if(NOT HAVE_PYTHON)
+    return()
+  endif()
+
+  string(REGEX REPLACE "^.*\\." "" basename "${target}")
+  set(sources ${ARGN})
+
+  add_library(${target} ${MODULE_TYPE} ${sources})
+  target_link_libraries(${target} PKG::PYTHON)
+
+  if(BUILD_SHARED_LIBS)
+    set_target_properties(${target} PROPERTIES
+      LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/panda3d"
+      OUTPUT_NAME "${basename}"
+      PREFIX ""
+      SUFFIX "${PYTHON_EXTENSION_SUFFIX}")
+
+    install(TARGETS ${target} DESTINATION "${PYTHON_ARCH_INSTALL_DIR}/panda3d")
+  else()
+    set_target_properties(${target} PROPERTIES
+      OUTPUT_NAME "${basename}"
+      PREFIX "libpython_panda3d_")
+
+    install(TARGETS ${target} DESTINATION lib)
+  endif()
+
+endfunction(add_python_target)
+
+#
+# Function: install_python_package(path [ARCH/LIB])
+#
+# Installs the Python package which was built at `path`.
+#
+# Note that this handles more than just installation; it will also invoke
+# Python's compileall utility to pregenerate .pyc/.pyo files.  This will only
+# happen if the Python interpreter is found.
+#
+# The ARCH or LIB keyword may be used to specify whether this package should be
+# installed into Python's architecture-dependent or architecture-independent
+# package path.  The default, if unspecified, is LIB.
+#
+function(install_python_package path)
+  if(ARGN STREQUAL "ARCH")
+    set(type "ARCH")
+  elseif(ARGN STREQUAL "LIB")
+    set(type "LIB")
+  elseif(ARGN STREQUAL "")
+    set(type "LIB")
+  else()
+    message(FATAL_ERROR "install_python_package got unexpected argument: ${ARGN}")
+  endif()
+
+  get_filename_component(package_name "${path}" NAME)
+  set(custom_target "bytecompile_${package_name}")
+
+  file(RELATIVE_PATH relpath "${PROJECT_BINARY_DIR}" "${path}")
+
+  if(PYTHON_EXECUTABLE)
+    add_custom_target(${custom_target} ALL)
+    add_custom_command(
+      TARGET ${custom_target}
+      WORKING_DIRECTORY "${PROJECT_BINARY_DIR}"
+      COMMAND "${PYTHON_EXECUTABLE}" -m compileall -q "${relpath}")
+    add_custom_command(
+      TARGET ${custom_target}
+      WORKING_DIRECTORY "${PROJECT_BINARY_DIR}"
+      COMMAND "${PYTHON_EXECUTABLE}" -OO -m compileall -q "${relpath}")
+  endif()
+
+  set(dir ${PYTHON_${type}_INSTALL_DIR})
+  if(dir)
+    install(DIRECTORY "${path}" DESTINATION "${dir}"
+      FILES_MATCHING REGEX "\\.py[co]?$")
+  endif()
+
+endfunction(install_python_package)

+ 1 - 4
direct/CMakeLists.txt

@@ -51,8 +51,5 @@ if(HAVE_PYTHON)
   file(WRITE "${PROJECT_BINARY_DIR}/direct/__init__.py" "")
   file(WRITE "${PROJECT_BINARY_DIR}/direct/__init__.py" "")
 
 
   # Install all files
   # Install all files
-  install(
-    DIRECTORY "${PROJECT_BINARY_DIR}/direct"
-    DESTINATION "${PYTHON_LIB_INSTALL_DIR}"
-    FILES_MATCHING REGEX "\\.py[co]?$")
+  install_python_package("${PROJECT_BINARY_DIR}/direct" LIB)
 endif()
 endif()