Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrecht Van Lommel <brecht>2022-09-15 19:01:15 +0300
committerBrecht Van Lommel <brecht@blender.org>2022-09-15 19:27:03 +0300
commit9f76d0c8e6dd2570e0da1763fcadfb738add4be2 (patch)
treef25063d63c9e71671f8b13065f91844b560387db
parentf70fac6382b78ad3a4b4288372026f2f8213b918 (diff)
Python: script for packing bpy module as wheel
The buildbot will call this script to create a binary .whl file that can be easily installed through pip. This wheel will only work with the same Python version used for Blender. Other minimum system requirements are the same as regular Blender builds. Includes contributions by Campbell Barton. Differential Revision: https://developer.blender.org/D15957
-rw-r--r--build_files/cmake/platform/platform_win32.cmake4
-rwxr-xr-xbuild_files/utils/make_bpy_wheel.py167
2 files changed, 170 insertions, 1 deletions
diff --git a/build_files/cmake/platform/platform_win32.cmake b/build_files/cmake/platform/platform_win32.cmake
index 771b00a3d09..dd5d04d7c92 100644
--- a/build_files/cmake/platform/platform_win32.cmake
+++ b/build_files/cmake/platform/platform_win32.cmake
@@ -504,7 +504,9 @@ if(WITH_JACK)
endif()
if(WITH_PYTHON)
- set(PYTHON_VERSION 3.10) # CACHE STRING)
+ # Cache version for make_bpy_wheel.py to detect.
+ unset(PYTHON_VERSION CACHE)
+ set(PYTHON_VERSION "3.10" CACHE STRING "Python version")
string(REPLACE "." "" _PYTHON_VERSION_NO_DOTS ${PYTHON_VERSION})
set(PYTHON_LIBRARY ${LIBDIR}/python/${_PYTHON_VERSION_NO_DOTS}/libs/python${_PYTHON_VERSION_NO_DOTS}.lib)
diff --git a/build_files/utils/make_bpy_wheel.py b/build_files/utils/make_bpy_wheel.py
new file mode 100755
index 00000000000..e98e8570212
--- /dev/null
+++ b/build_files/utils/make_bpy_wheel.py
@@ -0,0 +1,167 @@
+#!/usr/bin/env python3
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+import argparse
+import make_utils
+import os
+import re
+import platform
+import string
+import setuptools
+import sys
+
+from typing import (
+ Generator,
+ Tuple,
+ List,
+ Optional,
+ Sequence,
+)
+
+
+# ------------------------------------------------------------------------------
+# Generic Functions
+
+def find_dominating_file(
+ path: str,
+ search: Sequence[str],
+) -> str:
+ while True:
+ for d in search:
+ if os.path.exists(os.path.join(path, d)):
+ return os.path.join(path, d)
+ path_next = os.path.normpath(os.path.join(path, ".."))
+ if path == path_next:
+ break
+ path = path_next
+ return ""
+
+
+# ------------------------------------------------------------------------------
+# CMake Cache Access
+
+def cmake_cache_var_iter(filepath_cmake_cache: str) -> Generator[Tuple[str, str, str], None, None]:
+ import re
+ re_cache = re.compile(r"([A-Za-z0-9_\-]+)?:?([A-Za-z0-9_\-]+)?=(.*)$")
+ with open(filepath_cmake_cache, "r", encoding="utf-8") as cache_file:
+ for l in cache_file:
+ match = re_cache.match(l.strip())
+ if match is not None:
+ var, type_, val = match.groups()
+ yield (var, type_ or "", val)
+
+
+def cmake_cache_var(filepath_cmake_cache: str, var: str) -> Optional[str]:
+ for var_iter, type_iter, value_iter in cmake_cache_var_iter(filepath_cmake_cache):
+ if var == var_iter:
+ return value_iter
+ return None
+
+
+def cmake_cache_var_or_exit(filepath_cmake_cache: str, var: str) -> str:
+ value = cmake_cache_var(filepath_cmake_cache, var)
+ if value is None:
+ print("Unable to find %r exiting!" % var)
+ sys.exit(1)
+ return value
+
+
+# ------------------------------------------------------------------------------
+# Main Function
+
+def main() -> None:
+
+ # Parse arguments.
+ parser = argparse.ArgumentParser(description="Make Python wheel package")
+ parser.add_argument("install_dir")
+ parser.add_argument("--build-dir", default=None)
+ parser.add_argument("--output-dir", default=None)
+ args = parser.parse_args()
+
+ install_dir = os.path.abspath(args.install_dir)
+ build_dir = os.path.abspath(args.build_dir) if args.build_dir else install_dir
+ output_dir = os.path.abspath(args.output_dir) if args.output_dir else install_dir
+
+ filepath_cmake_cache = find_dominating_file(build_dir, ("CMakeCache.txt",))
+ if not filepath_cmake_cache:
+ # Should never fail.
+ print("Unable to find CMakeCache.txt in or above %r" % (build_dir))
+ sys.exit(1)
+
+ # Get the major and minor Python version.
+ python_version = cmake_cache_var_or_exit(filepath_cmake_cache, "PYTHON_VERSION")
+ python_version_number = (
+ tuple(int("".join(c for c in digit if c in string.digits)) for digit in python_version.split(".")) +
+ # Support version without a minor version "3" (add zero).
+ tuple((0, 0, 0))
+ )
+ python_version_str = "%d.%d" % python_version_number[:2]
+
+ # Get Blender version.
+ blender_version_str = str(make_utils.parse_blender_version())
+
+ # Set platform tag following conventions.
+ if sys.platform == "darwin":
+ target = cmake_cache_var_or_exit(filepath_cmake_cache, "CMAKE_OSX_DEPLOYMENT_TARGET").split(".")
+ machine = cmake_cache_var_or_exit(filepath_cmake_cache, "CMAKE_OSX_ARCHITECTURES")
+ platform_tag = "macosx_%d_%d_%s" % (int(target[0]), int(target[1]), machine)
+ elif sys.platform == "win32":
+ platform_tag = "win_%s" % (platform.machine().lower())
+ elif sys.platform == "linux":
+ glibc = os.confstr("CS_GNU_LIBC_VERSION").split()[1].split(".")
+ platform_tag = "manylinux_%s_%s_%s" % (glibc[0], glibc[1], platform.machine().lower())
+ else:
+ print("Unsupported platform %s" % (sys.platform))
+ sys.exit(1)
+
+ os.chdir(install_dir)
+
+ # Include all files recursively.
+ def package_files(root_dir: str) -> List[str]:
+ paths = []
+ for path, dirs, files in os.walk(root_dir):
+ paths += [os.path.join("..", path, f) for f in files]
+ return paths
+
+ # Ensure this wheel is marked platform specific.
+ class BinaryDistribution(setuptools.dist.Distribution):
+ def has_ext_modules(foo):
+ return True
+
+ # Build wheel.
+ sys.argv = [sys.argv[0], "bdist_wheel"]
+
+ setuptools.setup(
+ name="bpy",
+ version=blender_version_str,
+ install_requires=["cython", "numpy", "requests", "zstandard"],
+ python_requires="==%d.%d.*" % (python_version_number[0], python_version_number[1]),
+ packages=["bpy"],
+ package_data={"": package_files("bpy")},
+ distclass=BinaryDistribution,
+ options={"bdist_wheel": {"plat_name": platform_tag}},
+
+ description="Blender as a Python module",
+ license="GPL-3.0",
+ author="Blender Foundation",
+ author_email="bf-committers@blender.org",
+ url="https://www.blender.org"
+ )
+
+ if not os.path.exists(output_dir):
+ os.makedirs(output_dir)
+
+ # Move wheel to output directory.
+ dist_dir = os.path.join(install_dir, "dist")
+ for f in os.listdir(dist_dir):
+ if f.endswith(".whl"):
+ # No apparent way to override this ABI version with setuptools, so rename.
+ sys_py = "cp%d%d" % (sys.version_info.major, sys.version_info.minor)
+ blender_py = "cp%d%d" % (python_version_number[0], python_version_number[1])
+ renamed_f = f.replace(sys_py, blender_py)
+
+ os.rename(os.path.join(dist_dir, f), os.path.join(output_dir, renamed_f))
+
+
+if __name__ == "__main__":
+ main()