File size: 9,442 Bytes
41f85e5 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 | # Copyright 2025 The Khronos Group Inc.
# Copyright 2023 Shukant Pal
# SPDX-License-Identifier: Apache-2.0
option( KTX_PY_USE_VENV
"Use a Python virtual environment. Needed for externally managed python installations."
OFF
)
find_package (Python3 COMPONENTS Interpreter)
set(SOURCE_DIR ${CMAKE_SOURCE_DIR}/interface/python_binding)
file(GLOB pyktx_py_src ${SOURCE_DIR}/pyktx/*.py)
list(TRANSFORM pyktx_py_src REPLACE "${SOURCE_DIR}/pyktx/" "${KTX_BUILD_DIR}/interface/python_binding/docs/pyktx." OUTPUT_VARIABLE pyktx_py_rst_filenames)
list(TRANSFORM pyktx_py_rst_filenames REPLACE ".py$" ".rst" OUTPUT_VARIABLE pyktx_py_rst)
set(PYTHON_EXECUTABLE_SYSTEM ${Python3_EXECUTABLE})
if(DEFINED PYTHON AND NOT ${PYTHON} STREQUAL "")
set(PYTHON_EXECUTABLE_SYSTEM ${PYTHON})
message(STATUS "Override PYTHON with ${PYTHON}")
endif()
if (LINUX AND NOT Python3_FOUND)
set(PYTHON_EXECUTABLE_SYSTEM python)
message(STATUS "CMake failed to find python3. Will continue assuming it's on PATH")
endif()
if(KTX_PY_USE_VENV)
set(PYTHON_VENV_DIR "${KTX_BUILD_DIR}/interface/python_binding")
set(PYTHON_EXECUTABLE ${PYTHON_VENV_DIR}/bin/python3)
message(STATUS "Using virtual environment for Python")
else()
set(PYTHON_EXECUTABLE ${PYTHON_EXECUTABLE_SYSTEM})
endif()
# Convert Windows path to CMake path
cmake_path(SET PYTHON_PATH ${PYTHON_EXECUTABLE})
set(LIBKTX_LIB_DIR ${KTX_BUILD_DIR}/$<CONFIG>)
if(KTX_PY_USE_VENV)
add_custom_target( py-venv ALL
COMMENT
"Set up virtual environment for Python"
)
add_custom_command(
TARGET py-venv
PRE_BUILD
COMMAND
${PYTHON_EXECUTABLE_SYSTEM} -m venv ${PYTHON_VENV_DIR}
COMMENT
"Create virtual environment for Python"
)
endif()
add_custom_target( pyktx-deps ALL
COMMENT
"Python deps"
)
if(KTX_PY_USE_VENV)
add_dependencies(pyktx-deps py-venv)
endif()
add_custom_command(
TARGET pyktx-deps
PRE_BUILD
COMMAND
${PYTHON_EXECUTABLE} -m pip install --no-warn-script-location -r ${SOURCE_DIR}/requirements.txt
COMMENT
"Install dependencies for pyktx build"
)
add_custom_target( pyktx ALL
DEPENDS
ktx
${pyktx_py_src}
pyktx/ktx_texture.h
pyktx/ktx_texture1.h
pyktx/ktx_texture2.h
pyktx/ktx_texture.c
pyktx/ktx_texture1.c
pyktx/ktx_texture2.c
WORKING_DIRECTORY
${SOURCE_DIR}
COMMENT
"Python distributions"
)
add_dependencies(pyktx pyktx-deps)
add_custom_command(
TARGET pyktx
PRE_BUILD
COMMAND
${PYTHON_EXECUTABLE} clean.py
COMMENT
"Clean up pyktx build artifacts"
WORKING_DIRECTORY
${SOURCE_DIR}
)
# Normalize version number as the python toolchain does. Tweaks are reduced
# to a, b or rc immediately following the patch number. We do because names
# of the BYPRODUCTS in the following custom_command need to match the
# names with normalized version numbers the python tools would produce.
function(normalize_version _var fullver)
string(REPLACE -alpha a normalized ${fullver})
string(REPLACE -beta b normalized ${normalized})
set(${_var} "${normalized}" PARENT_SCOPE)
endfunction()
normalize_version(KTX_VERSION_NORMALIZED ${KTX_VERSION_FULL})
set(DIST_DIR ${KTX_BUILD_DIR}/interface/python_binding/dist)
set(SOURCE_ARCHIVE_BASENAME ${DIST_DIR}/pyktx-${KTX_VERSION_NORMALIZED})
add_custom_command(
TARGET pyktx
POST_BUILD
BYPRODUCTS
${SOURCE_ARCHIVE_BASENAME}.tar.gz
${SOURCE_ARCHIVE_BASENAME}.zip
COMMAND
${CMAKE_COMMAND} -E env
LIBKTX_INCLUDE_DIR=${CMAKE_SOURCE_DIR}/include
LIBKTX_LIB_DIR=${LIBKTX_LIB_DIR}
LIBKTX_VERSION=${KTX_VERSION_NORMALIZED}
# The build module by default builds in an isolated environment, i.e. it
# requires a virtual env. I have not found a way via find_package to
# ensure venv support is installed. This can be turned off with
# `--no-isolation` but such builds have not been tested.
${PYTHON_EXECUTABLE} -m build --sdist --outdir ${DIST_DIR}
COMMENT
"Build pyktx source package"
WORKING_DIRECTORY
${SOURCE_DIR}
)
add_custom_command(
TARGET pyktx
POST_BUILD
COMMAND
${CMAKE_COMMAND} -E env
LIBKTX_INCLUDE_DIR=${CMAKE_SOURCE_DIR}/include
LIBKTX_LIB_DIR=${LIBKTX_LIB_DIR}
LIBKTX_VERSION=${KTX_VERSION_NORMALIZED}
# Ditto with sdist isolated environment comment.
${PYTHON_EXECUTABLE} -m build --wheel --outdir ${DIST_DIR}
COMMENT
"Build pyktx wheel"
WORKING_DIRECTORY
${SOURCE_DIR}
)
set(pyktx_egg_info
${SOURCE_DIR}/pyktx.egg-info/dependency_links.txt
${SOURCE_DIR}/pyktx.egg-info/PKG-INFO
${SOURCE_DIR}/pyktx.egg-info/requires.txt
${SOURCE_DIR}/pyktx.egg-info/SOURCES.txt
${SOURCE_DIR}/pyktx.egg-info/top_level.txt)
add_test(NAME pyktx
COMMAND
${CMAKE_COMMAND} -E env
LIBKTX_INCLUDE_DIR=${CMAKE_SOURCE_DIR}/include
LIBKTX_LIB_DIR=${LIBKTX_LIB_DIR}
KTX_RUN_TESTS=ON
DYLD_LIBRARY_PATH=${LIBKTX_LIB_DIR}:$ENV{DYLD_LIBRARY_PATH}
LD_LIBRARY_PATH=${LIBKTX_LIB_DIR}:$ENV{LD_LIBRARY_PATH}
${PYTHON_EXECUTABLE} buildscript.py
WORKING_DIRECTORY
${SOURCE_DIR}
)
if(KTX_FEATURE_DOC)
add_custom_target(pyktx.doc ALL
DEPENDS
pyktx-deps
ktx # No way to avoid this autodoc needs compiled modules.
COMMENT
"Build Python documentation"
)
add_custom_command(
TARGET pyktx.doc
POST_BUILD
BYPRODUCTS
${KTX_BUILD_DIR}/interface/python_binding/conf.py
${KTX_BUILD_DIR}/interface/python_binding/index.rst
${pyktx_py_rst}
${KTX_BUILD_DIR}/interface/python_binding/docs/pyktx.rst
${KTX_BUILD_DIR}/interface/python_binding/docs/pyktx.native.rst
${pyktx_egg_info}
COMMAND
# This appears to build binaries of the native parts in the source pyktx
# folder. Without the binaries, autodoc can't import the modules. It
# prints warnings and fails to include any content in the documentation
# for the native interfaces in the HTML files it creates.
${CMAKE_COMMAND} -E env
LIBKTX_INCLUDE_DIR=${CMAKE_SOURCE_DIR}/include
LIBKTX_LIB_DIR=${LIBKTX_LIB_DIR}
DYLD_LIBRARY_PATH=${LIBKTX_LIB_DIR}:$ENV{DYLD_LIBRARY_PATH}
LD_LIBRARY_PATH=${LIBKTX_LIB_DIR}:$ENV{LD_LIBRARY_PATH}
${PYTHON_EXECUTABLE} buildscript.py
COMMAND
${CMAKE_COMMAND} -E copy
index.rst conf.py ${KTX_BUILD_DIR}/interface/python_binding
# Currently there are no static items to be included in the Sphinx generated
# documentation. The infrastructure is here in case of future need. If
# these command are removed, also remove html_static_path from conf.py.
COMMAND
${CMAKE_COMMAND} -E make_directory
${KTX_BUILD_DIR}/interface/python_binding/_static
COMMAND
${CMAKE_COMMAND} -E copy_directory
_static ${KTX_BUILD_DIR}/interface/python_binding/_static
COMMAND
# Sphinx Apidoc extracts docstrings from the source files and builds .rst files
# in the docs directory of the python_binding section of the build directory.
# `--separate` says to put the documentation for each module on its own page.
${CMAKE_COMMAND} -E env
LIBKTX_INCLUDE_DIR=${CMAKE_SOURCE_DIR}/include
LIBKTX_LIB_DIR=${LIBKTX_LIB_DIR}
${PYTHON_EXECUTABLE} -m sphinx.ext.apidoc -o ${KTX_BUILD_DIR}/interface/python_binding/docs ./pyktx --separate
COMMAND
# Sphinx uses autodoc to generate html files from the .rst files generated above.
# These are expected to be in a docs subdirectory of the SOURCEDIR hence the
# build directory appearing in SOURCEDIR. Sphinx invokes autodoc which wants to
# import the modules hence libktx, must be built for this to fully succeed.
#
# Autodoc is configured by the copy of `conf.py` in the build directory (copied
# there by one of the COMMANDs above). `conf.py` adds the python binding
# section of the build directory to Python's `sys.path` so Autodoc can find the
# modules. However they aren't there. The `pyktx` module is the directory
# ${SOURCE_DIR}/pyktx and the .o files from compiling the native parts are
# built there by buildscript.py when invoked above. ${SOURCE_DIR} appears in
# Python's sys.path so autodoc finds them. There is nothing explicit in `conf.py`
# to do this. It appears that Sphinx or autodoc itself adds its working directory
# to `sys.path`.
${CMAKE_COMMAND} -E env
LIBKTX_INCLUDE_DIR=${CMAKE_SOURCE_DIR}/include
LIBKTX_LIB_DIR=${LIBKTX_LIB_DIR}
SPHINXBUILD=${PYTHON_PATH}\ -m\ sphinx
make SOURCEDIR="${KTX_BUILD_DIR}/interface/python_binding" BUILDDIR="${KTX_BUILD_DIR}/interface/python_binding/docs/html/pyktx" html
WORKING_DIRECTORY
${SOURCE_DIR}
)
endif()
|