199 lines
7.3 KiB
Python
199 lines
7.3 KiB
Python
#!/usr/bin/env python3
|
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
|
# SPDX-FileCopyrightText: 2011-2024 Blender Authors
|
|
# <pep8 compliant>
|
|
|
|
import argparse
|
|
import os
|
|
import pathlib
|
|
import re
|
|
import subprocess
|
|
|
|
import worker.utils
|
|
|
|
|
|
class CodeBuilder(worker.utils.Builder):
|
|
def __init__(self, args: argparse.Namespace):
|
|
super().__init__(args, "blender", "blender")
|
|
self.needs_full_clean = args.needs_full_clean
|
|
self.needs_gpu_binaries = args.needs_gpu_binaries
|
|
self.needs_gpu_tests = args.needs_gpu_tests
|
|
self.needs_ninja = True
|
|
self.python_module = args.python_module
|
|
self.build_configuration = args.build_configuration
|
|
|
|
track_path: pathlib.Path = self.track_path
|
|
|
|
if self.platform in {"darwin", "windows"}:
|
|
if len(args.architecture):
|
|
self.architecture = args.architecture
|
|
|
|
if self.platform == "darwin":
|
|
self.build_dir = (
|
|
track_path / f"build_{self.architecture}_{self.build_configuration}"
|
|
)
|
|
else:
|
|
self.build_dir = track_path / f"build_{self.build_configuration}"
|
|
|
|
self.blender_dir = track_path / "blender.git"
|
|
self.install_dir = track_path / f"install_{self.build_configuration}"
|
|
self.package_dir = track_path / "build_package"
|
|
self.build_doc_path = track_path / "build_doc_api"
|
|
|
|
def clean(self):
|
|
worker.utils.remove_dir(self.install_dir)
|
|
worker.utils.remove_dir(self.package_dir)
|
|
worker.utils.remove_dir(self.build_doc_path)
|
|
|
|
# Call command with in compiler environment.
|
|
def call(
|
|
self, cmd: worker.utils.CmdSequence, env: worker.utils.Cmdenvironment = None
|
|
) -> int:
|
|
cmd_prefix: worker.utils.CmdList = []
|
|
|
|
if self.platform == "darwin":
|
|
# On macOS, override Xcode version if requested.
|
|
pipeline_config = self.pipeline_config()
|
|
xcode = pipeline_config.get("xcode", None)
|
|
xcode_version = xcode.get("version", None) if xcode else None
|
|
|
|
if xcode_version:
|
|
developer_dir = (
|
|
f"/Applications/Xcode-{xcode_version}.app/Contents/Developer"
|
|
)
|
|
else:
|
|
developer_dir = "/Applications/Xcode.app/Contents/Developer"
|
|
|
|
if (
|
|
self.service_env_id == "LOCAL"
|
|
and not pathlib.Path(developer_dir).exists()
|
|
):
|
|
worker.utils.warning(
|
|
f"Skip using non-existent {developer_dir} in LOCAL service environment"
|
|
)
|
|
else:
|
|
cmd_prefix = ["xcrun"]
|
|
env = dict(env) if env else os.environ.copy()
|
|
env["DEVELOPER_DIR"] = developer_dir
|
|
|
|
elif worker.utils.is_tool("scl"):
|
|
pipeline_config = self.pipeline_config()
|
|
gcc_version = pipeline_config["gcc"]["version"]
|
|
gcc_major_version = gcc_version.split(".")[0]
|
|
|
|
# On Rocky
|
|
if os.path.exists("/etc/rocky-release"):
|
|
# Stub to override configured GCC version, remove when blender build config is fixed
|
|
gcc_major_version = "11"
|
|
cmd_prefix = ["scl", "enable", f"gcc-toolset-{gcc_major_version}", "--"]
|
|
|
|
return worker.utils.call(cmd_prefix + list(cmd), env=env)
|
|
|
|
def pipeline_config(self) -> dict:
|
|
config_file_path = (
|
|
self.code_path / "build_files" / "config" / "pipeline_config.json"
|
|
)
|
|
if not config_file_path.exists():
|
|
config_file_path = config_file_path.with_suffix(".yaml")
|
|
if not config_file_path.exists():
|
|
raise Exception(f"Config file [{config_file_path}] not found, aborting")
|
|
|
|
with open(config_file_path, "r") as read_file:
|
|
if config_file_path.suffix == ".json":
|
|
import json
|
|
|
|
pipeline_config = json.load(read_file)
|
|
else:
|
|
import yaml
|
|
|
|
pipeline_config = yaml.load(read_file, Loader=yaml.SafeLoader)
|
|
|
|
return pipeline_config["buildbot"]
|
|
|
|
def blender_command_path(self) -> pathlib.Path:
|
|
if self.platform == "darwin":
|
|
return self.install_dir / "Blender.app" / "Contents" / "macOS" / "Blender"
|
|
elif self.platform == "windows":
|
|
return self.install_dir / "blender.exe"
|
|
else:
|
|
return self.install_dir / "blender"
|
|
|
|
def setup_build_environment(self) -> None:
|
|
if self.platform != "windows":
|
|
return
|
|
|
|
# CMake goes first to avoid using chocolaty cpack command.
|
|
worker.utils.info("Setting CMake path")
|
|
os.environ["PATH"] = (
|
|
"C:\\Program Files\\CMake\\bin" + os.pathsep + os.environ["PATH"]
|
|
)
|
|
|
|
worker.utils.info("Setting VC Tools env variables")
|
|
windows_build_version = "10.0.19041.0"
|
|
os.environ["PATH"] = (
|
|
f"C:\\Program Files (x86)\\Windows Kits\\10\\bin\\{windows_build_version}\\x64"
|
|
+ os.pathsep
|
|
+ os.environ["PATH"]
|
|
)
|
|
os.environ["PATH"] = (
|
|
"C:\\Program Files (x86)\\WiX Toolset v3.11\\bin"
|
|
+ os.pathsep
|
|
+ os.environ["PATH"]
|
|
)
|
|
|
|
if self.architecture == "arm64":
|
|
vs_build_tool_path = pathlib.Path(
|
|
"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\VC\\Auxiliary\\Build\\vcvarsarm64.bat"
|
|
)
|
|
vs_tool_install_dir_suffix = "\\bin\\Hostarm64\\arm64"
|
|
else:
|
|
vs_build_tool_path = pathlib.Path(
|
|
"C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community\\VC\\Auxiliary\\Build\\vcvars64.bat"
|
|
)
|
|
vs_tool_install_dir_suffix = "\\bin\\Hostx64\\x64"
|
|
|
|
vcvars_output = subprocess.check_output(
|
|
[vs_build_tool_path, "&&", "set"], shell=True
|
|
)
|
|
vcvars_text = vcvars_output.decode("utf-8", "ignore")
|
|
|
|
for line in vcvars_text.splitlines():
|
|
match = re.match(r"(.*?)=(.*)", line)
|
|
if match:
|
|
key = match.group(1)
|
|
value = match.group(2)
|
|
|
|
if key not in os.environ:
|
|
if key not in ["PROMPT", "Path"]:
|
|
worker.utils.info(f"Adding key {key}={value}")
|
|
os.environ[key] = value
|
|
|
|
os.environ["PATH"] = (
|
|
os.environ["VCToolsInstallDir"]
|
|
+ vs_tool_install_dir_suffix
|
|
+ os.pathsep
|
|
+ os.environ["PATH"]
|
|
)
|
|
|
|
|
|
def create_argument_parser(steps: worker.utils.BuilderSteps) -> argparse.ArgumentParser:
|
|
parser = worker.utils.create_argument_parser(steps=steps)
|
|
parser.add_argument("--needs-full-clean", action="store_true", required=False)
|
|
parser.add_argument("--needs-gpu-binaries", action="store_true", required=False)
|
|
parser.add_argument("--needs-gpu-tests", action="store_true", required=False)
|
|
parser.add_argument("--python-module", action="store_true", required=False)
|
|
parser.add_argument(
|
|
"--build-configuration",
|
|
default="release",
|
|
type=str,
|
|
choices=["release", "asserts", "sanitizer", "debug"],
|
|
required=False,
|
|
)
|
|
parser.add_argument(
|
|
"--architecture",
|
|
default="",
|
|
type=str,
|
|
choices=["arm64", "x86_64", "amd64"],
|
|
required=False,
|
|
)
|
|
return parser
|