Python.cmake 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. # Filename: Python.cmake
  2. #
  3. # Description: This file provides support functions for building/installing
  4. # Python extension modules and/or pure-Python packages.
  5. #
  6. # Functions:
  7. # add_python_target(target [source1 [source2 ...]])
  8. # install_python_package(path [ARCH/LIB])
  9. #
  10. #
  11. # Function: add_python_target(target [EXPORT exp] [COMPONENT comp]
  12. # [source1 [source2 ...]])
  13. # Build the provided source(s) as a Python extension module, linked against the
  14. # Python runtime library.
  15. #
  16. # Note that this also takes care of installation, unlike other target creation
  17. # commands in CMake. The EXPORT and COMPONENT keywords allow passing the
  18. # corresponding options to install(), but default to "Python" otherwise.
  19. #
  20. function(add_python_target target)
  21. if(NOT HAVE_PYTHON)
  22. return()
  23. endif()
  24. string(REGEX REPLACE "^.*\\." "" basename "${target}")
  25. set(sources)
  26. set(component "Python")
  27. set(export "Python")
  28. foreach(arg ${ARGN})
  29. if(arg STREQUAL "COMPONENT")
  30. set(keyword "component")
  31. elseif(arg STREQUAL "EXPORT")
  32. set(keyword "export")
  33. elseif(keyword)
  34. set(${keyword} "${arg}")
  35. unset(keyword)
  36. else()
  37. list(APPEND sources "${arg}")
  38. endif()
  39. endforeach(arg)
  40. string(REGEX REPLACE "\\.[^.]+$" "" namespace "${target}")
  41. string(REPLACE "." "/" slash_namespace "${namespace}")
  42. add_library(${target} ${MODULE_TYPE} ${sources})
  43. target_link_libraries(${target} PKG::PYTHON)
  44. if(BUILD_SHARED_LIBS)
  45. if(CMAKE_GENERATOR STREQUAL "Xcode")
  46. # This is explained in CompilerFlags.cmake
  47. set(intdir $<CONFIG>$(EFFECTIVE_PLATFORM_NAME))
  48. else()
  49. set(intdir ${CMAKE_CFG_INTDIR})
  50. endif()
  51. set(_outdir "${PROJECT_BINARY_DIR}/${intdir}/${slash_namespace}")
  52. set_target_properties(${target} PROPERTIES
  53. LIBRARY_OUTPUT_DIRECTORY "${_outdir}"
  54. OUTPUT_NAME "${basename}"
  55. PREFIX ""
  56. SUFFIX "${PYTHON_EXTENSION_SUFFIX}")
  57. # This is explained over in CompilerFlags.cmake
  58. foreach(_config ${CMAKE_CONFIGURATION_TYPES})
  59. string(TOUPPER "${_config}" _config)
  60. set_target_properties(${target} PROPERTIES
  61. LIBRARY_OUTPUT_DIRECTORY_${_config} "${_outdir}")
  62. endforeach(_config)
  63. if(PYTHON_ARCH_INSTALL_DIR)
  64. install(TARGETS ${target} EXPORT "${export}" COMPONENT "${component}" DESTINATION "${PYTHON_ARCH_INSTALL_DIR}/${slash_namespace}")
  65. endif()
  66. else()
  67. set_target_properties(${target} PROPERTIES
  68. OUTPUT_NAME "${basename}"
  69. PREFIX "libpy.${namespace}.")
  70. install(TARGETS ${target} EXPORT "${export}" COMPONENT "${component}" DESTINATION lib)
  71. endif()
  72. endfunction(add_python_target)
  73. #
  74. # Function: install_python_package(name [SOURCE path] [ARCH/LIB] [COMPONENT component])
  75. #
  76. # Installs the Python package `name` (which may have its source at `path`).
  77. #
  78. # The package is copied to (or created in) the build directory so that the user
  79. # may import it before the install step.
  80. #
  81. # Note that this handles more than just installation; it will also invoke
  82. # Python's compileall utility to pregenerate .pyc/.pyo files. This will only
  83. # happen if the Python interpreter is found.
  84. #
  85. # The ARCH or LIB keyword may be used to specify whether this package should be
  86. # installed into Python's architecture-dependent or architecture-independent
  87. # package path. The default, if unspecified, is LIB.
  88. #
  89. # The COMPONENT keyword overrides the install component (see CMake's
  90. # documentation for more information on what this does). The default is
  91. # "Python".
  92. #
  93. function(install_python_package package_name)
  94. set(type "LIB")
  95. unset(keyword)
  96. set(component "Python")
  97. unset(src_path)
  98. foreach(arg ${ARGN})
  99. if(arg STREQUAL "ARCH")
  100. set(type "ARCH")
  101. elseif(arg STREQUAL "LIB")
  102. set(type "LIB")
  103. elseif(arg STREQUAL "COMPONENT")
  104. set(keyword "${arg}")
  105. elseif(keyword STREQUAL "COMPONENT")
  106. set(component "${arg}")
  107. unset(keyword)
  108. elseif(arg STREQUAL "SOURCE")
  109. set(keyword "${arg}")
  110. elseif(keyword STREQUAL "SOURCE")
  111. set(src_path "${arg}")
  112. unset(keyword)
  113. else()
  114. message(FATAL_ERROR "install_python_package got unexpected argument: ${ARGN}")
  115. endif()
  116. endforeach(arg)
  117. if(NOT DEFINED src_path AND type STREQUAL "ARCH" AND WIN32 AND NOT CYGWIN)
  118. # Win32 needs a special fixup so the DLLs in "bin" can be on the path;
  119. # let's set src_path to the directory containing our fixup __init__.py
  120. set(src_path "${CMAKE_SOURCE_DIR}/cmake/templates/win32_python")
  121. endif()
  122. set(path "${PROJECT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${package_name}")
  123. set(args -D "OUTPUT_DIR=${path}")
  124. if(src_path)
  125. list(APPEND args -D "SOURCE_DIR=${src_path}")
  126. endif()
  127. if(PYTHON_EXECUTABLE)
  128. list(APPEND args -D "PYTHON_EXECUTABLES=${PYTHON_EXECUTABLE}")
  129. endif()
  130. add_custom_target(${package_name} ALL
  131. COMMAND ${CMAKE_COMMAND}
  132. ${args}
  133. -P "${CMAKE_SOURCE_DIR}/cmake/scripts/CopyPython.cmake")
  134. set(dir "${PYTHON_${type}_INSTALL_DIR}")
  135. if(dir)
  136. install(DIRECTORY "${path}" DESTINATION "${dir}"
  137. COMPONENT "${component}"
  138. FILES_MATCHING REGEX "\\.py[co]?$")
  139. endif()
  140. endfunction(install_python_package)