Switch SVN to Git submodules using Git-LFS

This change makes it so build system and update utilities for Blender builds
are using pre-compiled libraries and other resources attached as Git modules
instead of using checkout of SVN repositories in the parent folder.

The directory layout:
```
  * release/datafiles/
    * assets/        -> blender-assets.git
      * publish/
      * ...
      * README.txt
  * lib/
    * darwin_x64/    -> lib-darwin_x64.git
    * darwin_arm64/  -> lib-darwin_arm64.git
    * linux_x64/     -> lib-linux_x64.git
    * windows_x64/   -> lib-windows_x64.git
  * tests/
    * data/         -> blender-test-data.git
```

The changes about configuring the actual Git sub-modules are not included
into this patch, as those require repository to actually exist before it
can be used.

The assets submodule is enabled by default, and the rest of them are
disabled. This means that if someone runs `git submodule update --init`
they will not get heavy libraries. The platform-specific and tests
related submodules are enabled when using `make update` or `make test`.

All the submodules are tracked: this means that when new commits are
done to the submodule, the blender.git repository is to be updated to
point them to the new hash. This causes some extra manual work, but it
allows to more easily update Blender and its dependencies to known good
state when performing operations like bisect.

Ref #108978

Pull Request: https://projects.blender.org/blender/blender/pulls/117946
This commit is contained in:
Sergey Sharybin 2024-02-22 13:50:55 +01:00 committed by Sergey Sharybin
parent 0007c7a6b2
commit 3dc832a904
31 changed files with 378 additions and 361 deletions

1
.gitignore vendored

@ -56,6 +56,7 @@ waveletNoiseTile.bin
# External repositories. # External repositories.
/scripts/addons/ /scripts/addons/
/scripts/addons_contrib/ /scripts/addons_contrib/
/tests/benchmarks/
# Ignore old submodules directories. # Ignore old submodules directories.
# Eventually need to get rid of those, but for the first time of transition # Eventually need to get rid of those, but for the first time of transition

29
.gitmodules vendored Normal file

@ -0,0 +1,29 @@
[submodule "lib/linux_x64"]
update = none
path = lib/linux_x64
url = https://projects.blender.org/blender/lib-linux_x64.git
branch = blender-v4.1-release
[submodule "lib/macos_arm64"]
update = none
path = lib/macos_arm64
url = https://projects.blender.org/blender/lib-macos_arm64.git
branch = blender-v4.1-release
[submodule "lib/macos_x64"]
update = none
path = lib/macos_x64
url = https://projects.blender.org/blender/lib-macos_x64.git
branch = blender-v4.1-release
[submodule "lib/windows_x64"]
update = none
path = lib/windows_x64
url = https://projects.blender.org/blender/lib-windows_x64.git
branch = blender-v4.1-release
[submodule "release/datafiles/assets"]
path = release/datafiles/assets
url = https://projects.blender.org/blender/blender-assets.git
branch = blender-v4.1-release
[submodule "tests/data"]
update = none
path = tests/data
url = https://projects.blender.org/blender/blender-test-data.git
branch = blender-v4.1-release

@ -49,18 +49,17 @@ endif()
if(NOT DEFINED LIBDIR) if(NOT DEFINED LIBDIR)
if("${CMAKE_OSX_ARCHITECTURES}" STREQUAL "x86_64") if("${CMAKE_OSX_ARCHITECTURES}" STREQUAL "x86_64")
set(LIBDIR ${CMAKE_SOURCE_DIR}/../lib/darwin) set(LIBDIR ${CMAKE_SOURCE_DIR}/lib/macos_x64)
else() else()
set(LIBDIR ${CMAKE_SOURCE_DIR}/../lib/darwin_${CMAKE_OSX_ARCHITECTURES}) set(LIBDIR ${CMAKE_SOURCE_DIR}/lib/macos_${CMAKE_OSX_ARCHITECTURES})
endif()
else()
if(FIRST_RUN)
message(STATUS "Using pre-compiled LIBDIR: ${LIBDIR}")
endif() endif()
endif() endif()
if(NOT EXISTS "${LIBDIR}/") if(NOT EXISTS "${LIBDIR}/.git")
message(FATAL_ERROR "Mac OSX requires pre-compiled libs at: '${LIBDIR}'") message(FATAL_ERROR "Mac OSX requires pre-compiled libs at: '${LIBDIR}'")
endif() endif()
if(FIRST_RUN)
message(STATUS "Using pre-compiled LIBDIR: ${LIBDIR}")
endif()
# Avoid searching for headers since this would otherwise override our lib # Avoid searching for headers since this would otherwise override our lib
# directory as well as PYTHON_ROOT_DIR. # directory as well as PYTHON_ROOT_DIR.

@ -16,13 +16,13 @@ else()
set(LIBDIR_NATIVE_ABI ${CMAKE_SOURCE_DIR}/../lib/${LIBDIR_NAME}) set(LIBDIR_NATIVE_ABI ${CMAKE_SOURCE_DIR}/../lib/${LIBDIR_NAME})
# Path to precompiled libraries with known glibc 2.28 ABI. # Path to precompiled libraries with known glibc 2.28 ABI.
set(LIBDIR_GLIBC228_ABI ${CMAKE_SOURCE_DIR}/../lib/linux_x86_64_glibc_228) set(LIBDIR_GLIBC228_ABI ${CMAKE_SOURCE_DIR}/lib/linux_x64)
# Choose the best suitable libraries. # Choose the best suitable libraries.
if(EXISTS ${LIBDIR_NATIVE_ABI}) if(EXISTS ${LIBDIR_NATIVE_ABI})
set(LIBDIR ${LIBDIR_NATIVE_ABI}) set(LIBDIR ${LIBDIR_NATIVE_ABI})
set(WITH_LIBC_MALLOC_HOOK_WORKAROUND TRUE) set(WITH_LIBC_MALLOC_HOOK_WORKAROUND TRUE)
elseif(EXISTS ${LIBDIR_GLIBC228_ABI}) elseif(EXISTS "${LIBDIR_GLIBC228_ABI}/.git")
set(LIBDIR ${LIBDIR_GLIBC228_ABI}) set(LIBDIR ${LIBDIR_GLIBC228_ABI})
if(WITH_MEM_JEMALLOC) if(WITH_MEM_JEMALLOC)
# jemalloc provides malloc hooks. # jemalloc provides malloc hooks.

@ -266,23 +266,23 @@ if(NOT DEFINED LIBDIR)
# Setup 64bit and 64bit windows systems # Setup 64bit and 64bit windows systems
if(CMAKE_CL_64) if(CMAKE_CL_64)
message(STATUS "64 bit compiler detected.") message(STATUS "64 bit compiler detected.")
set(LIBDIR_BASE "win64") set(LIBDIR_BASE "windows_x64")
else() else()
message(FATAL_ERROR "32 bit compiler detected, blender no longer provides pre-build libraries for 32 bit windows, please set the LIBDIR cmake variable to your own library folder") message(FATAL_ERROR "32 bit compiler detected, blender no longer provides pre-build libraries for 32 bit windows, please set the LIBDIR cmake variable to your own library folder")
endif() endif()
if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 19.30.30423) if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 19.30.30423)
message(STATUS "Visual Studio 2022 detected.") message(STATUS "Visual Studio 2022 detected.")
set(LIBDIR ${CMAKE_SOURCE_DIR}/../lib/${LIBDIR_BASE}_vc15) set(LIBDIR ${CMAKE_SOURCE_DIR}/lib/${LIBDIR_BASE})
elseif(MSVC_VERSION GREATER 1919) elseif(MSVC_VERSION GREATER 1919)
message(STATUS "Visual Studio 2019 detected.") message(STATUS "Visual Studio 2019 detected.")
set(LIBDIR ${CMAKE_SOURCE_DIR}/../lib/${LIBDIR_BASE}_vc15) set(LIBDIR ${CMAKE_SOURCE_DIR}/lib/${LIBDIR_BASE})
endif() endif()
else() else()
if(FIRST_RUN) if(FIRST_RUN)
message(STATUS "Using pre-compiled LIBDIR: ${LIBDIR}") message(STATUS "Using pre-compiled LIBDIR: ${LIBDIR}")
endif() endif()
endif() endif()
if(NOT EXISTS "${LIBDIR}/") if(NOT EXISTS "${LIBDIR}/.git")
message(FATAL_ERROR "\n\nWindows requires pre-compiled libs at: '${LIBDIR}'. Please run `make update` in the blender source folder to obtain them.") message(FATAL_ERROR "\n\nWindows requires pre-compiled libs at: '${LIBDIR}'. Please run `make update` in the blender source folder to obtain them.")
endif() endif()

@ -13,6 +13,7 @@ import sys
import make_utils import make_utils
from make_utils import call from make_utils import call
from pathlib import Path
# Parse arguments. # Parse arguments.
@ -21,7 +22,6 @@ def parse_arguments() -> argparse.Namespace:
parser = argparse.ArgumentParser() parser = argparse.ArgumentParser()
parser.add_argument("--ctest-command", default="ctest") parser.add_argument("--ctest-command", default="ctest")
parser.add_argument("--cmake-command", default="cmake") parser.add_argument("--cmake-command", default="cmake")
parser.add_argument("--svn-command", default="svn")
parser.add_argument("--git-command", default="git") parser.add_argument("--git-command", default="git")
parser.add_argument("--config", default="") parser.add_argument("--config", default="")
parser.add_argument("build_directory") parser.add_argument("build_directory")
@ -30,7 +30,6 @@ def parse_arguments() -> argparse.Namespace:
args = parse_arguments() args = parse_arguments()
git_command = args.git_command git_command = args.git_command
svn_command = args.svn_command
ctest_command = args.ctest_command ctest_command = args.ctest_command
cmake_command = args.cmake_command cmake_command = args.cmake_command
config = args.config config = args.config
@ -45,24 +44,18 @@ if make_utils.command_missing(git_command):
sys.exit(1) sys.exit(1)
# Test if we are building a specific release version. # Test if we are building a specific release version.
branch = make_utils.git_branch(git_command) lib_tests_dirpath = Path("tests") / "data"
tag = make_utils.git_tag(git_command)
release_version = make_utils.git_branch_release_version(branch, tag)
lib_tests_dirpath = os.path.join('..', 'lib', "tests")
if not os.path.exists(lib_tests_dirpath): if not (lib_tests_dirpath / ".git").exists():
print("Tests files not found, downloading...") print("Tests files not found, downloading...")
if make_utils.command_missing(svn_command):
sys.stderr.write("svn not found, can't checkout test files\n")
sys.exit(1)
if make_utils.command_missing(cmake_command): if make_utils.command_missing(cmake_command):
sys.stderr.write("cmake not found, can't checkout test files\n") sys.stderr.write("cmake not found, can't checkout test files\n")
sys.exit(1) sys.exit(1)
svn_url = make_utils.svn_libraries_base_url(release_version) + "/tests" # Ensure the test data files sub-module is configured and present.
call([svn_command, "checkout", svn_url, lib_tests_dirpath]) make_utils.git_enable_submodule(git_command, "tests/data")
make_utils.git_update_submodule(args.git_command, lib_tests_dirpath)
# Run cmake again to detect tests files. # Run cmake again to detect tests files.
os.chdir(build_dir) os.chdir(build_dir)

@ -4,11 +4,11 @@
# SPDX-License-Identifier: GPL-2.0-or-later # SPDX-License-Identifier: GPL-2.0-or-later
""" """
"make update" for all platforms, updating svn libraries and tests and Blender "make update" for all platforms, updating Git LFS submodules for libraries and
git repository and sub-modules. tests, and Blender git repository.
For release branches, this will check out the appropriate branches of For release branches, this will check out the appropriate branches of
sub-modules and libraries. submodules and libraries.
""" """
import argparse import argparse
@ -20,168 +20,163 @@ import sys
import make_utils import make_utils
from pathlib import Path from pathlib import Path
from make_utils import call, check_output from make_utils import call, check_output
from urllib.parse import urljoin from urllib.parse import urljoin, urlsplit
from typing import ( from typing import Optional
Optional,
)
class Submodule:
path: str
branch: str
branch_fallback: str
def __init__(self, path: str, branch: str, branch_fallback: str) -> None:
self.path = path
self.branch = branch
self.branch_fallback = branch_fallback
def print_stage(text: str) -> None: def print_stage(text: str) -> None:
print("") print("")
print(text) print(text)
print("=" * len(text))
print("") print("")
# Parse arguments
def parse_arguments() -> argparse.Namespace: def parse_arguments() -> argparse.Namespace:
"""
Parse command line line arguments.
Returns parsed object from which the command line arguments can be accessed
as properties. The name of the properties matches the command line argument,
but with the leading dashed omitted and all remaining dashes replaced with
underscore.
"""
parser = argparse.ArgumentParser() parser = argparse.ArgumentParser()
parser.add_argument("--no-libraries", action="store_true") parser.add_argument("--no-libraries", action="store_true")
parser.add_argument("--no-blender", action="store_true") parser.add_argument("--no-blender", action="store_true")
parser.add_argument("--no-submodules", action="store_true") parser.add_argument("--no-submodules", action="store_true")
parser.add_argument("--use-tests", action="store_true") parser.add_argument("--use-tests", action="store_true")
parser.add_argument("--svn-command", default="svn")
parser.add_argument("--svn-branch", default=None)
parser.add_argument("--git-command", default="git") parser.add_argument("--git-command", default="git")
parser.add_argument("--use-linux-libraries", action="store_true") parser.add_argument("--use-linux-libraries", action="store_true")
parser.add_argument("--architecture", type=str, choices=("x86_64", "amd64", "arm64",)) parser.add_argument("--architecture", type=str,
choices=("x86_64", "amd64", "arm64",))
return parser.parse_args() return parser.parse_args()
def get_blender_git_root() -> str: def get_blender_git_root() -> Path:
return check_output([args.git_command, "rev-parse", "--show-toplevel"]) """
Get root directory of the current Git directory.
"""
return Path(
check_output([args.git_command, "rev-parse", "--show-toplevel"]))
# Setup for precompiled libraries and tests from svn.
def get_effective_platform(args: argparse.Namespace) -> str:
"""
Get platform of the host.
The result string is normalized to the name used by Blender releases and
library repository name prefixes: linux, macos, windows.
"""
if sys.platform == "darwin":
platform = "macos"
elif sys.platform == "win32":
platform = "windows"
else:
platform = sys.platform
assert (platform in ("linux", "macos", "windows"))
return platform
def get_effective_architecture(args: argparse.Namespace) -> str: def get_effective_architecture(args: argparse.Namespace) -> str:
"""
Get architecture of the host.
The result string is normalized to the architecture name used by the Blender
releases and library repository name suffixes: x64, arm64.
NOTE: When cross-compiling the architecture is coming from the command line
argument.
"""
architecture = args.architecture architecture = args.architecture
if architecture: if architecture:
assert isinstance(architecture, str) assert isinstance(architecture, str)
elif "ARM64" in platform.version():
# Check platform.version to detect arm64 with x86_64 python binary.
architecture = "arm64"
else:
architecture = platform.machine().lower()
# Normalize the architecture name.
if architecture == 'x86_64':
architecture = "x64"
assert (architecture in ("x64", "arm64"))
return architecture return architecture
# Check platform.version to detect arm64 with x86_64 python binary.
if "ARM64" in platform.version():
return "arm64"
return platform.machine().lower() def get_submodule_directories(args: argparse.Namespace):
"""
Get list of all configured submodule directories.
"""
blender_git_root = get_blender_git_root()
dot_modules = blender_git_root / ".gitmodules"
if not dot_modules.exists():
return ()
submodule_directories_output = check_output(
[args.git_command, "config", "--file", dot_modules, "--get-regexp", "path"])
return (Path(line.split(' ', 1)[1]) for line in submodule_directories_output.strip().splitlines())
def svn_update(args: argparse.Namespace, release_version: Optional[str]) -> None: def update_precompiled_libraries(args: argparse.Namespace) -> None:
svn_non_interactive = [args.svn_command, '--non-interactive'] """
Configure and update submodule for precompiled libraries
lib_dirpath = os.path.join(get_blender_git_root(), '..', 'lib') This function detects the current host architecture and enables
svn_url = make_utils.svn_libraries_base_url(release_version, args.svn_branch) corresponding submodule, and updates the submodule.
# Checkout precompiled libraries NOTE: When cross-compiling the architecture is coming from the command line
architecture = get_effective_architecture(args) argument.
if sys.platform == 'darwin': """
if architecture == 'arm64':
lib_platform = "darwin_arm64"
elif architecture == 'x86_64':
lib_platform = "darwin"
else:
lib_platform = None
elif sys.platform == 'win32':
# Windows checkout is usually handled by bat scripts since python3 to run
# this script is bundled as part of the precompiled libraries. However it
# is used by the buildbot.
lib_platform = "win64_vc15"
elif args.use_linux_libraries:
lib_platform = "linux_x86_64_glibc_228"
else:
# No precompiled libraries for Linux.
lib_platform = None
if lib_platform: print_stage("Configuring Precompiled Libraries")
lib_platform_dirpath = os.path.join(lib_dirpath, lib_platform)
if not os.path.exists(lib_platform_dirpath): platform = get_effective_platform(args)
print_stage("Checking out Precompiled Libraries") arch = get_effective_architecture(args)
if make_utils.command_missing(args.svn_command): print(f"Detected platform : {platform}")
sys.stderr.write("svn not found, can't checkout libraries\n") print(f"Detected architecture : {arch}")
sys.exit(1) print()
svn_url_platform = svn_url + lib_platform if sys.platform == "linux" and not args.use_linux_libraries:
call(svn_non_interactive + ["checkout", svn_url_platform, lib_platform_dirpath]) print("Skipping Linux libraries configuration")
return
if args.use_tests: submodule_dir = f"lib/{platform}_{arch}"
lib_tests = "tests"
lib_tests_dirpath = os.path.join(lib_dirpath, lib_tests)
if not os.path.exists(lib_tests_dirpath): submodule_directories = get_submodule_directories(args)
print_stage("Checking out Tests")
if make_utils.command_missing(args.svn_command): if Path(submodule_dir) not in submodule_directories:
sys.stderr.write("svn not found, can't checkout tests\n") print("Skipping libraries update: no configured submodule")
sys.exit(1) return
svn_url_tests = svn_url + lib_tests make_utils.git_enable_submodule(args.git_command, submodule_dir)
call(svn_non_interactive + ["checkout", svn_url_tests, lib_tests_dirpath]) make_utils.git_update_submodule(args.git_command, submodule_dir)
lib_assets = "assets"
lib_assets_dirpath = os.path.join(lib_dirpath, lib_assets) def update_tests_data_files(args: argparse.Namespace) -> None:
"""
if not os.path.exists(lib_assets_dirpath): Configure and update submodule with files used by regression tests
print_stage("Checking out Assets") """
if make_utils.command_missing(args.svn_command): print_stage("Configuring Tests Data Files")
sys.stderr.write("svn not found, can't checkout assets\n")
sys.exit(1) submodule_dir = "tests/data"
svn_url_assets = svn_url + lib_assets make_utils.git_enable_submodule(args.git_command, submodule_dir)
call(svn_non_interactive + ["checkout", svn_url_assets, lib_assets_dirpath]) make_utils.git_update_submodule(args.git_command, submodule_dir)
# Update precompiled libraries, assets and tests
if not os.path.isdir(lib_dirpath):
print("Library path: %r, not found, skipping" % lib_dirpath)
else:
paths_local_and_remote = []
if os.path.exists(os.path.join(lib_dirpath, ".svn")):
print_stage("Updating Precompiled Libraries, Assets and Tests (one repository)")
paths_local_and_remote.append((lib_dirpath, svn_url))
else:
print_stage("Updating Precompiled Libraries, Assets and Tests (multiple repositories)")
# Separate paths checked out.
for dirname in os.listdir(lib_dirpath):
if dirname.startswith("."):
# Temporary paths such as ".mypy_cache" will report a warning, skip hidden directories.
continue
dirpath = os.path.join(lib_dirpath, dirname)
if not (os.path.isdir(dirpath) and os.path.exists(os.path.join(dirpath, ".svn"))):
continue
paths_local_and_remote.append((dirpath, svn_url + dirname))
if paths_local_and_remote:
if make_utils.command_missing(args.svn_command):
sys.stderr.write("svn not found, can't update libraries\n")
sys.exit(1)
for dirpath, svn_url_full in paths_local_and_remote:
call(svn_non_interactive + ["cleanup", dirpath])
# Switch to appropriate branch and update.
call(svn_non_interactive + ["switch", svn_url_full, dirpath], exit_on_error=False)
call(svn_non_interactive + ["update", dirpath])
# Test if git repo can be updated.
def git_update_skip(args: argparse.Namespace, check_remote_exists: bool = True) -> str: def git_update_skip(args: argparse.Namespace, check_remote_exists: bool = True) -> str:
"""Test if git repo can be updated."""
if make_utils.command_missing(args.git_command): if make_utils.command_missing(args.git_command):
sys.stderr.write("git not found, can't update code\n") sys.stderr.write("git not found, can't update code\n")
sys.exit(1) sys.exit(1)
@ -274,23 +269,22 @@ def resolve_external_url(blender_url: str, repo_name: str) -> str:
return urljoin(blender_url + "/", "../" + repo_name) return urljoin(blender_url + "/", "../" + repo_name)
def external_script_copy_old_submodule_over(args: argparse.Namespace, directory_name: str) -> None: def external_script_copy_old_submodule_over(
blender_git_root = Path(get_blender_git_root()) args: argparse.Namespace,
scripts_dir = blender_git_root / "scripts" directory: Path,
external_dir = scripts_dir / directory_name old_submodules_dir: Path) -> None:
blender_git_root = get_blender_git_root()
external_dir = blender_git_root / directory
old_submodule_relative_dir = Path("release") / "scripts" / directory_name print(f"Moving {old_submodules_dir} to {directory} ...")
print(f"Moving {old_submodule_relative_dir} to scripts/{directory_name} ...") shutil.move(blender_git_root / old_submodules_dir, external_dir)
old_submodule_dir = blender_git_root / old_submodule_relative_dir
shutil.move(old_submodule_dir, external_dir)
# Remove old ".git" which is a file with path to a submodule bare repo inside of main # Remove old ".git" which is a file with path to a submodule bare repo inside of main
# repo .git/modules directory. # repo .git/modules directory.
(external_dir / ".git").unlink() (external_dir / ".git").unlink()
bare_repo_relative_dir = Path(".git") / "modules" / "release" / "scripts" / directory_name bare_repo_relative_dir = Path(".git") / "modules" / old_submodules_dir
print(f"Copying {bare_repo_relative_dir} to scripts/{directory_name}/.git ...") print(f"Copying {bare_repo_relative_dir} to {directory}/.git ...")
bare_repo_dir = blender_git_root / bare_repo_relative_dir bare_repo_dir = blender_git_root / bare_repo_relative_dir
shutil.copytree(bare_repo_dir, external_dir / ".git") shutil.copytree(bare_repo_dir, external_dir / ".git")
@ -298,24 +292,25 @@ def external_script_copy_old_submodule_over(args: argparse.Namespace, directory_
call((args.git_command, "config", "--file", str(git_config), "--unset", "core.worktree")) call((args.git_command, "config", "--file", str(git_config), "--unset", "core.worktree"))
def external_script_initialize_if_needed(args: argparse.Namespace, def floating_checkout_initialize_if_needed(args: argparse.Namespace,
repo_name: str, repo_name: str,
directory_name: str) -> None: directory: Path,
"""Initialize checkout of an external repository scripts directory""" old_submodules_dir: Path = None) -> None:
"""Initialize checkout of an external repository"""
blender_git_root = Path(get_blender_git_root()) blender_git_root = get_blender_git_root()
blender_dot_git = blender_git_root / ".git" blender_dot_git = blender_git_root / ".git"
scripts_dir = blender_git_root / "scripts" external_dir = blender_git_root / directory
external_dir = scripts_dir / directory_name
if external_dir.exists(): if external_dir.exists():
return return
print(f"Initializing scripts/{directory_name} ...") print(f"Initializing {directory} ...")
old_submodule_dot_git = blender_git_root / "release" / "scripts" / directory_name / ".git" if old_submodules_dir is not None:
old_submodule_dot_git = blender_git_root / old_submodules_dir / ".git"
if old_submodule_dot_git.exists() and blender_dot_git.is_dir(): if old_submodule_dot_git.exists() and blender_dot_git.is_dir():
external_script_copy_old_submodule_over(args, directory_name) external_script_copy_old_submodule_over(args, directory, old_submodules_dir)
return return
origin_name = "upstream" if use_upstream_workflow(args) else "origin" origin_name = "upstream" if use_upstream_workflow(args) else "origin"
@ -330,9 +325,9 @@ def external_script_initialize_if_needed(args: argparse.Namespace,
call((args.git_command, "clone", "--origin", origin_name, external_url, str(external_dir))) call((args.git_command, "clone", "--origin", origin_name, external_url, str(external_dir)))
def external_script_add_origin_if_needed(args: argparse.Namespace, def floating_checkout_add_origin_if_needed(args: argparse.Namespace,
repo_name: str, repo_name: str,
directory_name: str) -> None: directory: Path) -> None:
""" """
Add remote called 'origin' if there is a fork of the external repository available Add remote called 'origin' if there is a fork of the external repository available
@ -344,9 +339,8 @@ def external_script_add_origin_if_needed(args: argparse.Namespace,
cwd = os.getcwd() cwd = os.getcwd()
blender_git_root = Path(get_blender_git_root()) blender_git_root = get_blender_git_root()
scripts_dir = blender_git_root / "scripts" external_dir = blender_git_root / directory
external_dir = scripts_dir / directory_name
origin_blender_url = make_utils.git_get_remote_url(args.git_command, "origin") origin_blender_url = make_utils.git_get_remote_url(args.git_command, "origin")
origin_external_url = resolve_external_url(origin_blender_url, repo_name) origin_external_url = resolve_external_url(origin_blender_url, repo_name)
@ -361,7 +355,7 @@ def external_script_add_origin_if_needed(args: argparse.Namespace,
if not make_utils.git_is_remote_repository(args.git_command, origin_external_url): if not make_utils.git_is_remote_repository(args.git_command, origin_external_url):
return return
print(f"Adding origin remote to {directory_name} pointing to fork ...") print(f"Adding origin remote to {directory} pointing to fork ...")
# Non-obvious tricks to introduce the new remote called "origin" to the existing # Non-obvious tricks to introduce the new remote called "origin" to the existing
# submodule configuration. # submodule configuration.
@ -390,23 +384,30 @@ def external_script_add_origin_if_needed(args: argparse.Namespace,
return return
def external_scripts_update(args: argparse.Namespace, def floating_checkout_update(args: argparse.Namespace,
repo_name: str, repo_name: str,
directory_name: str, directory: Path,
branch: Optional[str]) -> str: branch: Optional[str],
old_submodules_dir: Path = None,
only_update=False) -> str:
"""Update a single external checkout with the given name in the scripts folder""" """Update a single external checkout with the given name in the scripts folder"""
external_script_initialize_if_needed(args, repo_name, directory_name) blender_git_root = get_blender_git_root()
external_script_add_origin_if_needed(args, repo_name, directory_name) external_dir = blender_git_root / directory
print(f"Updating scripts/{directory_name} ...") if only_update and not external_dir.exists():
return ""
floating_checkout_initialize_if_needed(args, repo_name, directory, old_submodules_dir)
floating_checkout_add_origin_if_needed(args, repo_name, directory)
blender_git_root = get_blender_git_root()
external_dir = blender_git_root / directory
print(f"* Updating {directory} ...")
cwd = os.getcwd() cwd = os.getcwd()
blender_git_root = Path(get_blender_git_root())
scripts_dir = blender_git_root / "scripts"
external_dir = scripts_dir / directory_name
# Update externals to appropriate given branch, falling back to main if none is given and/or # Update externals to appropriate given branch, falling back to main if none is given and/or
# found in a sub-repository. # found in a sub-repository.
branch_fallback = "main" branch_fallback = "main"
@ -419,7 +420,7 @@ def external_scripts_update(args: argparse.Namespace,
os.chdir(external_dir) os.chdir(external_dir)
msg = git_update_skip(args, check_remote_exists=False) msg = git_update_skip(args, check_remote_exists=False)
if msg: if msg:
skip_msg += directory_name + " skipped: " + msg + "\n" skip_msg += str(directory) + " skipped: " + msg + "\n"
else: else:
# Find a matching branch that exists. # Find a matching branch that exists.
for remote in ("origin", "upstream"): for remote in ("origin", "upstream"):
@ -465,6 +466,17 @@ def external_scripts_update(args: argparse.Namespace,
return skip_msg return skip_msg
def external_scripts_update(args: argparse.Namespace,
repo_name: str,
directory_name: str,
branch: Optional[str]) -> str:
return floating_checkout_update(args,
repo_name,
Path("scripts") / directory_name,
branch,
old_submodules_dir=Path("release") / "scripts" / directory_name)
def scripts_submodules_update(args: argparse.Namespace, branch: Optional[str]) -> str: def scripts_submodules_update(args: argparse.Namespace, branch: Optional[str]) -> str:
"""Update working trees of addons and addons_contrib within the scripts/ directory""" """Update working trees of addons and addons_contrib within the scripts/ directory"""
msg = "" msg = ""
@ -475,12 +487,75 @@ def scripts_submodules_update(args: argparse.Namespace, branch: Optional[str]) -
return msg return msg
def submodules_update(args: argparse.Namespace, branch: Optional[str]) -> str: def floating_libraries_update(args: argparse.Namespace, branch: Optional[str]) -> str:
"""Update submodules or other externally tracked source trees""" """Update libraries checkouts which are floating (not attached as Git submodules)"""
msg = "" msg = ""
msg += floating_checkout_update(args,
"benchmarks",
Path("tests") / "benchmarks",
branch,
only_update=True)
return msg
def add_submodule_push_url(args: argparse.Namespace):
"""
Add pushURL configuration for all locally activated submodules, pointing to SSH protocol.
"""
blender_git_root = get_blender_git_root()
modules = blender_git_root / ".git" / "modules"
submodule_directories = get_submodule_directories(args)
for submodule_path in submodule_directories:
module_path = modules / submodule_path
config = module_path / "config"
if not config.exists():
# Ignore modules which are not initialized
continue
push_url = check_output((args.git_command, "config", "--file", str(config),
"--get", "remote.origin.pushURL"), exit_on_error=False)
if push_url:
# Ignore modules which have pushURL configured.
continue
url = make_utils.git_get_config(args.git_command, "remote.origin.url", str(config))
url = "https://projects.blender.org/blender/lib-darwin_arm64.git" # XXX
if not url.startswith("https:"):
# Ignore non-URL URLs.
continue
url_parts = urlsplit(url)
push_url = f"git@{url_parts.netloc}:{url_parts.path[1:]}"
print(f"Setting pushURL to {push_url} for {submodule_path}")
make_utils.git_set_config(args.git_command, "remote.origin.pushURL", push_url, str(config))
def submodules_update(args: argparse.Namespace, branch: Optional[str]) -> str:
"""Update submodules or other externally tracked source trees"""
print_stage("Updating Submodules")
msg = ""
call((args.git_command, "lfs", "install"))
msg += scripts_submodules_update(args, branch) msg += scripts_submodules_update(args, branch)
msg += floating_libraries_update(args, branch)
print("* Updating Git submodules")
exitcode = call((args.git_command, "submodule", "update", "--init"), exit_on_error=False)
if exitcode != 0:
msg += "Error updating Git submodules\n"
add_submodule_push_url(args)
return msg return msg
@ -494,26 +569,30 @@ if __name__ == "__main__":
major = blender_version.version // 100 major = blender_version.version // 100
minor = blender_version.version % 100 minor = blender_version.version % 100
branch = f"blender-v{major}.{minor}-release" branch = f"blender-v{major}.{minor}-release"
release_version: Optional[str] = f"{major}.{minor}"
else: else:
branch = 'main' branch = 'main'
release_version = None
if not args.no_libraries: if not args.no_libraries:
svn_update(args, release_version) update_precompiled_libraries(args)
if args.use_tests:
update_tests_data_files(args)
if not args.no_blender: if not args.no_blender:
blender_skip_msg = git_update_skip(args) blender_skip_msg = git_update_skip(args)
if not blender_skip_msg: if not blender_skip_msg:
blender_skip_msg = blender_update(args) blender_skip_msg = blender_update(args)
if blender_skip_msg: if blender_skip_msg:
blender_skip_msg = "Blender repository skipped: " + blender_skip_msg + "\n" blender_skip_msg = "Blender repository skipped: " + blender_skip_msg + "\n"
if not args.no_submodules: if not args.no_submodules:
submodules_skip_msg = submodules_update(args, branch) submodules_skip_msg = submodules_update(args, branch)
# Report any skipped repositories at the end, so it's not as easy to miss. # Report any skipped repositories at the end, so it's not as easy to miss.
skip_msg = blender_skip_msg + submodules_skip_msg skip_msg = blender_skip_msg + submodules_skip_msg
if skip_msg: if skip_msg:
print_stage(skip_msg.strip()) print()
print(skip_msg.strip())
print()
# For failed submodule update we throw an error, since not having correct # For failed submodule update we throw an error, since not having correct
# submodules can make Blender throw errors. # submodules can make Blender throw errors.

@ -11,9 +11,7 @@ import re
import shutil import shutil
import subprocess import subprocess
import sys import sys
import os
from pathlib import Path from pathlib import Path
from urllib.parse import urljoin
from typing import ( from typing import (
Sequence, Sequence,
@ -48,7 +46,7 @@ def check_output(cmd: Sequence[str], exit_on_error: bool = True) -> str:
output = subprocess.check_output(cmd, stderr=subprocess.STDOUT, universal_newlines=True) output = subprocess.check_output(cmd, stderr=subprocess.STDOUT, universal_newlines=True)
except subprocess.CalledProcessError as e: except subprocess.CalledProcessError as e:
if exit_on_error: if exit_on_error:
sys.stderr.write(" ".join(cmd)) sys.stderr.write(" ".join(cmd) + "\n")
sys.stderr.write(e.output + "\n") sys.stderr.write(e.output + "\n")
sys.exit(e.returncode) sys.exit(e.returncode)
output = "" output = ""
@ -87,25 +85,6 @@ def git_remote_exist(git_command: str, remote_name: str) -> bool:
return remote_url != remote_name return remote_url != remote_name
def git_get_resolved_submodule_url(git_command: str, blender_url: str, submodule_path: str) -> str:
git_root = check_output([git_command, "rev-parse", "--show-toplevel"])
dot_gitmodules = os.path.join(git_root, ".gitmodules")
submodule_key_prefix = f"submodule.{submodule_path}"
submodule_key_url = f"{submodule_key_prefix}.url"
gitmodule_url = git_get_config(
git_command, submodule_key_url, file=dot_gitmodules)
# A bit of a trickery to construct final URL.
# Only works for the relative submodule URLs.
#
# Note that unless the LHS URL ends up with a slash urljoin treats the last component as a
# file.
assert gitmodule_url.startswith('..')
return urljoin(blender_url + "/", gitmodule_url)
def git_is_remote_repository(git_command: str, repo: str) -> bool: def git_is_remote_repository(git_command: str, repo: str) -> bool:
"""Returns true if the given repository is a valid/clonable git repo""" """Returns true if the given repository is a valid/clonable git repo"""
exit_code = call((git_command, "ls-remote", repo, "HEAD"), exit_on_error=False, silent=True) exit_code = call((git_command, "ls-remote", repo, "HEAD"), exit_on_error=False, silent=True)
@ -113,7 +92,8 @@ def git_is_remote_repository(git_command: str, repo: str) -> bool:
def git_branch(git_command: str) -> str: def git_branch(git_command: str) -> str:
# Get current branch name. """Get current branch name."""
try: try:
branch = subprocess.check_output([git_command, "rev-parse", "--abbrev-ref", "HEAD"]) branch = subprocess.check_output([git_command, "rev-parse", "--abbrev-ref", "HEAD"])
except subprocess.CalledProcessError as e: except subprocess.CalledProcessError as e:
@ -137,43 +117,31 @@ def git_set_config(git_command: str, key: str, value: str, file: Optional[str] =
return check_output([git_command, "config", key, value]) return check_output([git_command, "config", key, value])
def git_tag(git_command: str) -> Optional[str]: def git_enable_submodule(git_command: str, submodule_dir: str):
# Get current tag name. """Enable submodule denoted by its directory within the repository"""
try:
tag = subprocess.check_output([git_command, "describe", "--exact-match"], stderr=subprocess.STDOUT)
except subprocess.CalledProcessError as e:
return None
return tag.strip().decode('utf8') command = (git_command,
"config",
"--local",
f"submodule.{submodule_dir}.update", "checkout")
call(command, exit_on_error=True, silent=False)
def git_branch_release_version(branch: str, tag: Optional[str]) -> Optional[str]: def git_update_submodule(git_command: str, submodule_dir: str):
re_match = re.search("^blender-v(.*)-release$", branch) """
release_version = None Update the given submodule.
if re_match:
release_version = re_match.group(1)
elif tag:
re_match = re.search(r"^v([0-9]*\.[0-9]*).*", tag)
if re_match:
release_version = re_match.group(1)
return release_version
The submodule is denoted by its path within the repository.
This function will initialize the submodule if it has not been initialized.
"""
def svn_libraries_base_url(release_version: Optional[str], branch: Optional[str] = None) -> str: call((git_command, "submodule", "update", "--init", submodule_dir))
if release_version:
svn_branch = "tags/blender-" + release_version + "-release"
elif branch:
svn_branch = "branches/" + branch
else:
svn_branch = "trunk"
return "https://svn.blender.org/svnroot/bf-blender/" + svn_branch + "/lib/"
def command_missing(command: str) -> bool: def command_missing(command: str) -> bool:
# Support running with Python 2 for macOS # Support running with Python 2 for macOS
if sys.version_info >= (3, 0): if sys.version_info >= (3, 0):
return shutil.which(command) is None return shutil.which(command) is None
else:
return False return False

@ -1,37 +1,30 @@
if "%BUILD_VS_YEAR%"=="2019" set BUILD_VS_LIBDIRPOST=vc15 set BUILD_VS_LIBDIR="lib\windows_x64"
if "%BUILD_VS_YEAR%"=="2022" set BUILD_VS_LIBDIRPOST=vc15
set BUILD_VS_SVNDIR=win64_%BUILD_VS_LIBDIRPOST%
set BUILD_VS_LIBDIR="%BLENDER_DIR%..\lib\%BUILD_VS_SVNDIR%"
if NOT "%verbose%" == "" ( if NOT "%verbose%" == "" (
echo Library Directory = "%BUILD_VS_LIBDIR%" echo Library Directory = "%BUILD_VS_LIBDIR%"
) )
if NOT EXIST %BUILD_VS_LIBDIR% ( if NOT EXIST "%BUILD_VS_LIBDIR%\.git" (
rem libs not found, but svn is on the system rem libs not found, but git is on the system
if not "%SVN%"=="" ( if not "%GIT%"=="" (
echo. echo.
echo The required external libraries in %BUILD_VS_LIBDIR% are missing echo The required external libraries in %BUILD_VS_LIBDIR% are missing
echo. echo.
set /p GetLibs= "Would you like to download them? (y/n)" set /p GetLibs= "Would you like to download them? (y/n)"
if /I "!GetLibs!"=="Y" ( if /I "!GetLibs!"=="Y" (
echo. echo.
echo Downloading %BUILD_VS_SVNDIR% libraries, please wait. echo Downloading %BUILD_VS_LIBDIR% libraries, please wait.
echo. echo.
:RETRY :RETRY
"%SVN%" checkout https://svn.blender.org/svnroot/bf-blender/trunk/lib/%BUILD_VS_SVNDIR% %BUILD_VS_LIBDIR% "%GIT%" -C "%BLENDER_DIR%" config --local "submodule.%BUILD_VS_LIBDIR%.update" "checkout"
"%GIT%" -C "%BLENDER_DIR%" submodule update --init "%BUILD_VS_LIBDIR%"
if errorlevel 1 ( if errorlevel 1 (
set /p LibRetry= "Error during download, retry? y/n" set /p LibRetry= "Error during download, retry? y/n"
if /I "!LibRetry!"=="Y" ( if /I "!LibRetry!"=="Y" (
cd %BUILD_VS_LIBDIR%
"%SVN%" cleanup
cd %BLENDER_DIR%
goto RETRY goto RETRY
) )
echo. echo.
echo Error: Download of external libraries failed. echo Error: Download of external libraries failed.
echo This is needed for building, please manually run 'svn cleanup' and 'svn update' in echo Until this is resolved you CANNOT make a successful blender build.
echo %BUILD_VS_LIBDIR% , until this is resolved you CANNOT make a successful blender build
echo. echo.
exit /b 1 exit /b 1
) )
@ -39,11 +32,11 @@ if NOT EXIST %BUILD_VS_LIBDIR% (
) )
) else ( ) else (
if NOT EXIST %PYTHON% ( if NOT EXIST %PYTHON% (
if not "%SVN%"=="" ( if not "%GIT%"=="" (
echo. echo.
echo Python not found in external libraries, updating to latest version echo Python not found in external libraries, updating to latest version
echo. echo.
"%SVN%" update %BUILD_VS_LIBDIR% "%GIT%" -C "%BLENDER_DIR%" submodule update "%BUILD_VS_LIBDIR%"
) )
) )
) )
@ -53,8 +46,8 @@ if NOT EXIST %BUILD_VS_LIBDIR% (
echo Error: Required libraries not found at "%BUILD_VS_LIBDIR%" echo Error: Required libraries not found at "%BUILD_VS_LIBDIR%"
echo This is needed for building, aborting! echo This is needed for building, aborting!
echo. echo.
if "%SVN%"=="" ( if "%GIT%"=="" (
echo This is most likely caused by svn.exe not being available. echo This is most likely caused by git.exe not being available.
) )
exit /b 1 exit /b 1
) )

@ -1,5 +1,4 @@
REM find all dependencies and set the corresponding environment variables. REM find all dependencies and set the corresponding environment variables.
for %%X in (svn.exe) do (set SVN=%%~$PATH:X)
for %%X in (cmake.exe) do (set CMAKE=%%~$PATH:X) for %%X in (cmake.exe) do (set CMAKE=%%~$PATH:X)
for %%X in (ctest.exe) do (set CTEST=%%~$PATH:X) for %%X in (ctest.exe) do (set CTEST=%%~$PATH:X)
for %%X in (git.exe) do (set GIT=%%~$PATH:X) for %%X in (git.exe) do (set GIT=%%~$PATH:X)
@ -7,19 +6,19 @@ REM For python, default on 310 but if that does not exist also check
REM the 311, 312 and finally 39 folders to see if those are there, it checks REM the 311, 312 and finally 39 folders to see if those are there, it checks
REM this far ahead to ensure good lib folder compatibility in the future REM this far ahead to ensure good lib folder compatibility in the future
REM it falls back to 3.9 just incase it is a very old lib folder. REM it falls back to 3.9 just incase it is a very old lib folder.
set PYTHON=%BLENDER_DIR%\..\lib\win64_vc15\python\310\bin\python.exe set PYTHON=%BLENDER_DIR%\lib\windows_x64\python\310\bin\python.exe
if EXIST %PYTHON% ( if EXIST %PYTHON% (
goto detect_python_done goto detect_python_done
) )
set PYTHON=%BLENDER_DIR%\..\lib\win64_vc15\python\311\bin\python.exe set PYTHON=%BLENDER_DIR%\lib\windows_x64\python\311\bin\python.exe
if EXIST %PYTHON% ( if EXIST %PYTHON% (
goto detect_python_done goto detect_python_done
) )
set PYTHON=%BLENDER_DIR%\..\lib\win64_vc15\python\312\bin\python.exe set PYTHON=%BLENDER_DIR%\lib\windows_x64\python\312\bin\python.exe
if EXIST %PYTHON% ( if EXIST %PYTHON% (
goto detect_python_done goto detect_python_done
) )
set PYTHON=%BLENDER_DIR%\..\lib\win64_vc15\python\39\bin\python.exe set PYTHON=%BLENDER_DIR%\lib\windows_x64\python\39\bin\python.exe
if EXIST %PYTHON% ( if EXIST %PYTHON% (
goto detect_python_done goto detect_python_done
) )
@ -31,7 +30,6 @@ if NOT EXIST %PYTHON% (
:detect_python_done :detect_python_done
if NOT "%verbose%" == "" ( if NOT "%verbose%" == "" (
echo svn : "%SVN%"
echo cmake : "%CMAKE%" echo cmake : "%CMAKE%"
echo ctest : "%CTEST%" echo ctest : "%CTEST%"
echo git : "%GIT%" echo git : "%GIT%"

@ -1,5 +1,5 @@
if EXIST %BLENDER_DIR%\..\lib\win64_vc15\llvm\bin\clang-format.exe ( if EXIST %BLENDER_DIR%\lib\windows_x64\llvm\bin\clang-format.exe (
set CF_PATH=..\lib\win64_vc15\llvm\bin set CF_PATH=lib\windows_x64\llvm\bin
goto detect_done goto detect_done
) )

@ -0,0 +1,16 @@
set BUILD_VS_LIBDIR="lib\windows_x64"
:RETRY
"%GIT%" -C "%BLENDER_DIR%" config --local "submodule.%BUILD_VS_LIBDIR%.update" "checkout"
"%GIT%" -C "%BLENDER_DIR%" submodule update --init "%BUILD_VS_LIBDIR%"
if errorlevel 1 (
set /p LibRetry= "Error during update, retry? y/n"
if /I "!LibRetry!"=="Y" (
goto RETRY
)
echo.
echo Error: Download of external libraries failed.
echo Until this is resolved you CANNOT make a successful blender build.
echo.
exit /b 1
)

@ -110,9 +110,6 @@ if NOT "%1" == "" (
) else if "%1" == "doc_py" ( ) else if "%1" == "doc_py" (
set DOC_PY=1 set DOC_PY=1
goto EOF goto EOF
) else if "%1" == "svnfix" (
set SVN_FIX=1
goto EOF
) else ( ) else (
echo Command "%1" unknown, aborting! echo Command "%1" unknown, aborting!
goto ERR goto ERR

@ -4,9 +4,7 @@ set BUILD_CMAKE_ARGS=
set BUILD_ARCH= set BUILD_ARCH=
set BUILD_VS_VER= set BUILD_VS_VER=
set BUILD_VS_YEAR= set BUILD_VS_YEAR=
set BUILD_VS_LIBDIRPOST=
set BUILD_VS_LIBDIR= set BUILD_VS_LIBDIR=
set BUILD_VS_SVNDIR=
set KEY_NAME= set KEY_NAME=
set MSBUILD_PLATFORM= set MSBUILD_PLATFORM=
set MUST_CLEAN= set MUST_CLEAN=

@ -8,13 +8,10 @@ for /f "delims=" %%i in ('"%GIT%" rev-parse HEAD') do echo Branch_hash=%%i
cd "%BLENDER_DIR%/scripts/addons" cd "%BLENDER_DIR%/scripts/addons"
for /f "delims=" %%i in ('"%GIT%" rev-parse --abbrev-ref HEAD') do echo Addons_Branch_name=%%i for /f "delims=" %%i in ('"%GIT%" rev-parse --abbrev-ref HEAD') do echo Addons_Branch_name=%%i
for /f "delims=" %%i in ('"%GIT%" rev-parse HEAD') do echo Addons_Branch_hash=%%i for /f "delims=" %%i in ('"%GIT%" rev-parse HEAD') do echo Addons_Branch_hash=%%i
if "%SVN%" == "" (
echo SVN not found, cannot library information. cd "%BLENDER_DIR%/lib/windows_x64"
goto EOF for /f "delims=" %%i in ('"%GIT%" rev-parse --abbrev-ref HEAD') do echo Libs_Branch_name=%%i
) for /f "delims=" %%i in ('"%GIT%" rev-parse HEAD') do echo Libs_Branch_hash=%%i
set BUILD_VS_LIBDIR=%BLENDER_DIR%..\lib\win64_vc15
for /f "delims=" %%i in ('"%SVN%" info --show-item=url --no-newline %BUILD_VS_LIBDIR% ') do echo Libs_URL=%%i
for /f "delims=" %%i in ('"%SVN%" info --show-item=revision --no-newline %BUILD_VS_LIBDIR% ') do echo Libs_Revision=%%i
for /f "delims=" %%i in ('"%SVN%" info --show-item=last-changed-date --no-newline %BUILD_VS_LIBDIR% ') do echo Libs_LastChange=%%i
cd "%BLENDER_DIR%" cd "%BLENDER_DIR%"
:EOF :EOF

@ -1,25 +0,0 @@
if "%BUILD_VS_YEAR%"=="2019" set BUILD_VS_LIBDIRPOST=vc15
if "%BUILD_VS_YEAR%"=="2022" set BUILD_VS_LIBDIRPOST=vc15
set BUILD_VS_SVNDIR=win64_%BUILD_VS_LIBDIRPOST%
set BUILD_VS_LIBDIR="%BLENDER_DIR%..\lib\%BUILD_VS_SVNDIR%"
echo Starting cleanup in %BUILD_VS_LIBDIR%.
cd %BUILD_VS_LIBDIR%
:RETRY
"%SVN%" cleanup
"%SVN%" update
if errorlevel 1 (
set /p LibRetry= "Error during update, retry? y/n"
if /I "!LibRetry!"=="Y" (
goto RETRY
)
echo.
echo Error: Download of external libraries failed.
echo This is needed for building, please manually run 'svn cleanup' and 'svn update' in
echo %BUILD_VS_LIBDIR% , until this is resolved you CANNOT make a successful blender build
echo.
exit /b 1
)
echo Cleanup complete

@ -1,24 +0,0 @@
if "%BUILD_VS_YEAR%"=="2019" set BUILD_VS_LIBDIRPOST=vc15
if "%BUILD_VS_YEAR%"=="2022" set BUILD_VS_LIBDIRPOST=vc15
set BUILD_VS_SVNDIR=win64_%BUILD_VS_LIBDIRPOST%
set BUILD_VS_LIBDIR="%BLENDER_DIR%..\lib\%BUILD_VS_SVNDIR%"
cd %BUILD_VS_LIBDIR%
:RETRY
"%SVN%" update
if errorlevel 1 (
set /p LibRetry= "Error during update, retry? y/n"
if /I "!LibRetry!"=="Y" (
"%SVN%" cleanup
goto RETRY
)
echo.
echo Error: Download of external libraries failed.
echo This is needed for building, please manually run 'svn cleanup' and 'svn update' in
echo %BUILD_VS_LIBDIR% , until this is resolved you CANNOT make a successful blender build
echo.
exit /b 1
)
cd %BLENDER_DIR%

@ -8,6 +8,6 @@ exit /b 1
:detect_python_done :detect_python_done
REM Use -B to avoid writing __pycache__ in lib directory and causing update conflicts. REM Use -B to avoid writing __pycache__ in lib directory and causing update conflicts.
%PYTHON% -B %BLENDER_DIR%\build_files\utils\make_test.py --git-command "%GIT%" --svn-command "%SVN%" --cmake-command="%CMAKE%" --ctest-command="%CTEST%" --config="%BUILD_TYPE%" %BUILD_DIR% %PYTHON% -B %BLENDER_DIR%\build_files\utils\make_test.py --git-command "%GIT%" --cmake-command="%CMAKE%" --ctest-command="%CTEST%" --config="%BUILD_TYPE%" %BUILD_DIR%
:EOF :EOF

@ -5,6 +5,6 @@ if NOT EXIST %PYTHON% (
:detect_python_done :detect_python_done
REM Use -B to avoid writing __pycache__ in lib directory and causing update conflicts. REM Use -B to avoid writing __pycache__ in lib directory and causing update conflicts.
%PYTHON% -B %BLENDER_DIR%\build_files\utils\make_update.py --git-command "%GIT%" --svn-command "%SVN%" %BUILD_UPDATE_ARGS% %PYTHON% -B %BLENDER_DIR%\build_files\utils\make_update.py --git-command "%GIT%" %BUILD_UPDATE_ARGS%
:EOF :EOF

1
lib/linux_x64 Submodule

@ -0,0 +1 @@
Subproject commit 591fce4abaa409b31482e515c6d1b95143f58114

1
lib/macos_arm64 Submodule

@ -0,0 +1 @@
Subproject commit 0b09ac9de1557c296cb483355fc9528db707dbd4

1
lib/macos_x64 Submodule

@ -0,0 +1 @@
Subproject commit 9af47e501151474c23afa1a6f5a8b1a419a122ba

1
lib/windows_x64 Submodule

@ -0,0 +1 @@
Subproject commit 58cb225fe4643c4879fb274078e5477c50c0429c

@ -56,11 +56,6 @@ if "%BUILD_VS_YEAR%" == "" (
) )
) )
if "%SVN_FIX%" == "1" (
call "%BLENDER_DIR%\build_files\windows\svn_fix.cmd"
goto EOF
)
if "%BUILD_UPDATE%" == "1" ( if "%BUILD_UPDATE%" == "1" (
REM First see if the SVN libs are there and check them out if they are not. REM First see if the SVN libs are there and check them out if they are not.
call "%BLENDER_DIR%\build_files\windows\check_libraries.cmd" call "%BLENDER_DIR%\build_files\windows\check_libraries.cmd"
@ -70,7 +65,7 @@ if "%BUILD_UPDATE%" == "1" (
REM running tends to be problematic. The python script that update_sources REM running tends to be problematic. The python script that update_sources
REM calls later on may still try to switch branches and run into trouble, REM calls later on may still try to switch branches and run into trouble,
REM but for *most* people this will side step the problem. REM but for *most* people this will side step the problem.
call "%BLENDER_DIR%\build_files\windows\svn_update.cmd" call "%BLENDER_DIR%\build_files\windows\lib_update.cmd"
) )
REM Finally call the python script shared between all platforms that updates git REM Finally call the python script shared between all platforms that updates git
REM and does any other SVN work like update the tests or branch switches REM and does any other SVN work like update the tests or branch switches

@ -0,0 +1 @@
Subproject commit a5b6ba8fe49679a8b1105c3e80b3e190a97942c0

@ -1672,10 +1672,6 @@ install(
set(ASSET_BUNDLE_DIR ${CMAKE_SOURCE_DIR}/release/datafiles/assets/publish/) set(ASSET_BUNDLE_DIR ${CMAKE_SOURCE_DIR}/release/datafiles/assets/publish/)
if(NOT EXISTS "${ASSET_BUNDLE_DIR}")
set(ASSET_BUNDLE_DIR ${CMAKE_SOURCE_DIR}/../lib/assets/publish/)
endif()
if(EXISTS "${ASSET_BUNDLE_DIR}") if(EXISTS "${ASSET_BUNDLE_DIR}")
install( install(
DIRECTORY ${ASSET_BUNDLE_DIR} DIRECTORY ${ASSET_BUNDLE_DIR}

1
tests/data Submodule

@ -0,0 +1 @@
Subproject commit 44b6f5d4d180edb700db848be9208efe6f59c9a2

@ -26,7 +26,7 @@ class TestEnvironment:
self.build_dir = base_dir / 'build' self.build_dir = base_dir / 'build'
self.install_dir = self.build_dir / "bin" self.install_dir = self.build_dir / "bin"
self.lib_dir = base_dir / 'lib' self.lib_dir = base_dir / 'lib'
self.benchmarks_dir = self.blender_git_dir.parent / 'lib' / 'benchmarks' self.benchmarks_dir = self.blender_git_dir / 'tests' / 'benchmarks'
self.git_executable = 'git' self.git_executable = 'git'
self.cmake_executable = 'cmake' self.cmake_executable = 'cmake'
self.cmake_options = ['-DWITH_INTERNATIONAL=OFF', '-DWITH_BUILDINFO=OFF'] self.cmake_options = ['-DWITH_INTERNATIONAL=OFF', '-DWITH_BUILDINFO=OFF']

@ -8,7 +8,7 @@
# and don't give deterministic results # and don't give deterministic results
set(USE_EXPERIMENTAL_TESTS FALSE) set(USE_EXPERIMENTAL_TESTS FALSE)
set(TEST_SRC_DIR ${CMAKE_SOURCE_DIR}/../lib/tests) set(TEST_SRC_DIR ${CMAKE_SOURCE_DIR}/tests/data)
set(TEST_PYTHON_DIR ${CMAKE_SOURCE_DIR}/tests/python) set(TEST_PYTHON_DIR ${CMAKE_SOURCE_DIR}/tests/python)
set(TEST_OUT_DIR ${CMAKE_BINARY_DIR}/tests) set(TEST_OUT_DIR ${CMAKE_BINARY_DIR}/tests)

@ -10,7 +10,7 @@
# and don't give deterministic results # and don't give deterministic results
set(USE_EXPERIMENTAL_TESTS FALSE) set(USE_EXPERIMENTAL_TESTS FALSE)
set(TEST_SRC_DIR ${CMAKE_SOURCE_DIR}/../lib/tests) set(TEST_SRC_DIR ${CMAKE_SOURCE_DIR}/tests/data)
set(TEST_OUT_DIR ${CMAKE_BINARY_DIR}/tests) set(TEST_OUT_DIR ${CMAKE_BINARY_DIR}/tests)
# ugh, any better way to do this on testing only? # ugh, any better way to do this on testing only?

@ -1,3 +1,4 @@
tests/python/view_layer/CMakeLists.txt
# SPDX-FileCopyrightText: 2017-2023 Blender Authors # SPDX-FileCopyrightText: 2017-2023 Blender Authors
# #
# SPDX-License-Identifier: GPL-2.0-or-later # SPDX-License-Identifier: GPL-2.0-or-later
@ -6,7 +7,7 @@
# Use '--write-blend=/tmp/test.blend' to view output # Use '--write-blend=/tmp/test.blend' to view output
set(TEST_SRC_DIR ${CMAKE_SOURCE_DIR}/../lib/tests) set(TEST_SRC_DIR ${CMAKE_SOURCE_DIR}/tests/data)
set(TEST_OUT_DIR ${CMAKE_BINARY_DIR}/tests) set(TEST_OUT_DIR ${CMAKE_BINARY_DIR}/tests)
# ugh, any better way to do this on testing only? # ugh, any better way to do this on testing only?