Skip to content

Instantly share code, notes, and snippets.

@ideasman42
Created December 12, 2023 11:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ideasman42/80390355b49ff82cd6a7582a33d5484d to your computer and use it in GitHub Desktop.
Save ideasman42/80390355b49ff82cd6a7582a33d5484d to your computer and use it in GitHub Desktop.
#!/usr/bin/env python3
import os
import re
import shutil
import subprocess
SOURCE_DIR = "/src/blender"
def create_cc_wrapper(filepath: str, compiler_orig: str) -> None:
with open(filepath, 'w', encoding='utf-8') as fh:
fh.write(" \\\n".join([
"#!/bin/dash\nexec " + compiler_orig,
"$@",
"-Wno-error=deprecated-declarations",
"-Werror=incompatible-pointer-types",
"-Wvla",
"-Wno-error=clobbered",
"-Wno-error=cast-function-type",
"-Werror=discarded-array-qualifiers",
"-Werror=discarded-qualifiers",
]))
os.chmod(filepath, 0o777)
def create_cxx_wrapper(filepath, compiler_orig: str) -> None:
with open(filepath, 'w', encoding='utf-8') as fh:
fh.write(" \\\n".join([
"#!/bin/dash\nexec " + compiler_orig,
"$@",
"-Wno-error=deprecated-declarations",
"-Wno-error=terminate",
"-Wno-expansion-to-defined",
"-Wno-maybe-uninitialized",
"-fdiagnostics-color=always",
]))
os.chmod(filepath, 0o777)
def version_directory_name():
filepath = os.path.join(SOURCE_DIR, "source", "blender", "blenkernel", "BKE_blender_version.h")
line_re = re.compile(r"^#define (BLENDER_VERSION[A-Z_]*)\s+([0-9a-z]+)$")
version_info = {}
with open(filepath, encoding="utf-8") as fh:
for line in fh:
match = line_re.match(line.strip())
if not match:
continue
version_info[match.group(1)] = match.group(2)
version = int(version_info["BLENDER_VERSION"])
version_major = version // 100
version_minor = version % 100
return "{:d}.{:d}".format(version_major, version_minor)
def create_fake_install(build_dir: str) -> None:
VERSION_NAME = version_directory_name()
BUILD_VERSION_DIR = os.path.join(build_dir, "bin", VERSION_NAME)
os.makedirs(BUILD_VERSION_DIR)
SOURCE_RELEASE_DIR = os.path.join(SOURCE_DIR, "release")
for f in os.listdir(SOURCE_RELEASE_DIR):
os.symlink(
os.path.join(SOURCE_RELEASE_DIR, f),
os.path.join(BUILD_VERSION_DIR, f),
)
os.symlink(
os.path.join(os.path.join(SOURCE_DIR, "scripts")),
os.path.join(BUILD_VERSION_DIR, "scripts"),
)
def gen_build_dir(
source_dir: str,
build_dir: str,
compiler_family: str,
debug: bool,
precompiled_libs: bool,
fake_install: bool,
) -> None:
# Avoid errors `cwd`.
cwd = os.getcwd()
if os.path.exists(build_dir):
shutil.rmtree(build_dir)
os.mkdir(build_dir)
os.chdir(cwd)
del cwd
do_compiler_wrappers = debug
do_compiler_asan = debug
do_local_python = False
do_lite_config = debug
if fake_install:
create_fake_install(build_dir)
# TODO: error check missing compilers.
if compiler_family == 'GCC':
compiler_bin_c = shutil.which("gcc")
compiler_bin_cxx = shutil.which("g++")
elif compiler_family == 'CLANG':
compiler_bin_c = shutil.which("clang")
compiler_bin_cxx = shutil.which("clang++")
else:
print("Unknown compiler family", compiler_family, "aborting!")
return
if do_compiler_wrappers:
compiler_c_wrap = os.path.join(os.path.join(build_dir, "cc.wrap.sh"))
compiler_cxx_wrap = os.path.join(os.path.join(build_dir, "cxx.wrap.sh"))
create_cc_wrapper(compiler_c_wrap, compiler_bin_c)
create_cxx_wrapper(compiler_cxx_wrap, compiler_bin_cxx)
compiler_bin_c = compiler_c_wrap
compiler_bin_cxx = compiler_cxx_wrap
del compiler_c_wrap
del compiler_cxx_wrap
# TODO: error check missing compilers.
if compiler_family == 'GCC':
compiler_c_flags_debug = (
"-ggdb3",
"-fno-inline",
"-ftrivial-auto-var-init=pattern",
"-O0",
"-Wall",
"-Wunused",
"-Wextra",
# Various warnings:
"-Wabsolute-value",
"-Warray-bounds=2",
"-Warray-parameter",
"-Wduplicated-cond",
"-Wformat-overflow",
"-Wformat-truncation",
"-Wmisleading-indentation",
"-Wnull-dereference",
"-Wstringop-truncation",
"-Wsuggest-attribute=const",
"-Wsuggest-attribute=format",
"-Wsuggest-attribute=malloc",
"-Wsuggest-attribute=pure",
"-Wuninitialized",
# Various warnings (disable):
"-Wno-cast-function-type",
"-Wno-error=maybe-uninitialized",
"-Wno-error=unused-function",
"-Wno-missing-field-initializers",
"-Wno-return-local-addr",
"-Wno-sign-compare",
"-Wno-stringop-overflow",
"-Wno-stringop-overread",
# Noisy but useful at times.
# "-Wlogical-op",
# "-Wunused-macros",
# "-Wstack-usage=10000",
# "-Wduplicated-branches",
)
compiler_cxx_flags_debug = (
"-ggdb3",
"-fno-inline",
"-ftrivial-auto-var-init=pattern",
"-O0",
"-Wall",
"-Wunused",
"-Wextra",
# "-Wstack-usage=10000",
# Various warnings:
"-Warray-bounds=2",
"-Warray-parameter",
"-Wduplicated-cond",
"-Wformat-overflow",
"-Wformat-truncation",
"-Wmisleading-indentation",
"-Wnull-dereference",
"-Wstringop-truncation",
"-Wsuggest-attribute=const",
"-Wsuggest-attribute=format",
"-Wsuggest-attribute=malloc",
"-Wsuggest-attribute=pure",
"-Wuninitialized",
# Various warnings (disable):
"-Wno-cast-function-type",
"-Wno-dangling-reference",
"-Wno-error=maybe-uninitialized",
"-Wno-error=unused-function",
"-Wno-ignored-qualifiers",
"-Wno-missing-field-initializers",
"-Wno-return-local-addr",
"-Wno-sign-compare",
"-Wno-stringop-overflow",
"-Wno-stringop-overread",
"-Wchanges-meaning",
"-Wattributes",
"-Wcomma-subscript",
"-Wmain",
"-Wnarrowing",
"-Wregister",
"-Wvla",
"-Wwrite-strings",
# TODO: we might want to shadow.
# "-Wshadow",
# Noisy but useful at times.
# "-Wunused-macros",
# "-Wduplicated-branches",
)
elif compiler_family == 'CLANG':
compiler_c_flags_debug = (
"-ggdb3",
"-fno-inline",
"-ftrivial-auto-var-init=pattern",
"-O0",
"-Wall",
"-Wunused",
"-Wextra",
)
compiler_cxx_flags_debug = (
"-ggdb3",
"-fno-inline",
"-ftrivial-auto-var-init=pattern",
"-O0",
"-Wall",
"-Wunused",
"-Wextra",
# "-Wstack-usage=10000",
)
args = [
"cmake",
"-Wdev",
"-Wdeprecated",
"-B", build_dir,
"-S", SOURCE_DIR,
"-G", "Ninja" if debug else "Unix Makefiles",
*(["-C", os.path.join(SOURCE_DIR, "build_files/cmake/config/blender_lite.cmake")] if do_lite_config else []),
"-D", "CMAKE_BUILD_TYPE:STRING=" + (
"Debug" if debug else
# "RelWithDebInfo"
"Release"
),
"-D", "CMAKE_EXPORT_COMPILE_COMMANDS:BOOL=ON",
"-D", "WITH_LINKER_MOLD:BOOL=ON",
# Incompatible with "code_clean" utility.
"-D", "WITH_UNITY_BUILD:BOOL=OFF",
"-D", "WITH_COMPILER_CCACHE:BOOL=ON",
# Use my systems libraries.
"-D", "WITH_LIBS_PRECOMPILED:BOOL=" + ("ON" if precompiled_libs else "OFF"),
# Enable tests.
"-D", "WITH_GTESTS:BOOL=ON",
# Debug string overflow.
"-D", "WITH_STRSIZE_DEBUG:BOOL=ON",
# Support VALGRIND.
"-D", "WITH_MEM_VALGRIND:BOOL=" + ("ON" if debug else "OFF"),
# JEMALLOC isn't compatible with ASAN.
"-D", "WITH_MEM_JEMALLOC:BOOL=OFF",
# Compiler flags.
"-D", "CMAKE_C_FLAGS:STRING=-fdiagnostics-color=always -Werror=parentheses",
"-D", "CMAKE_CXX_FLAGS:STRING=-fdiagnostics-color=always -Werror=parentheses",
# Used by LSP programs such as CLANGD.
"-D", "CMAKE_EXPORT_COMPILE_COMMANDS:BOOL=ON",
"-D", "CMAKE_C_FLAGS_DEBUG:STRING=" + " ".join([
*compiler_c_flags_debug,
]),
"-D", "CMAKE_CXX_FLAGS_DEBUG:STRING=" + " ".join([
*compiler_cxx_flags_debug,
]),
# ASAN flags.
"-D", "COMPILER_ASAN_CFLAGS:STRING=" + " ".join([
"-Wanalyzer-allocation-size",
"-Wanalyzer-deref-before-check",
"-Wanalyzer-exposure-through-uninit-copy",
"-Wanalyzer-fd-access-mode-mismatch",
"-Wanalyzer-fd-double-close",
"-Wanalyzer-fd-leak",
"-Wanalyzer-fd-phase-mismatch",
"-Wanalyzer-fd-type-mismatch",
"-Wanalyzer-fd-use-after-close",
"-Wanalyzer-fd-use-without-check",
"-Wanalyzer-imprecise-fp-arithmetic",
"-Wanalyzer-infinite-recursion",
"-Wanalyzer-jump-through-null",
"-Wanalyzer-out-of-bounds",
"-Wanalyzer-putenv-of-auto-var",
"-Wanalyzer-tainted-assertion",
"-Wanalyzer-use-of-uninitialized-value",
"-Wanalyzer-write-to-const",
"-Wanalyzer-write-to-string-literal ",
"-fno-sanitize=alignment",
"-fsanitize-address-use-after-scope",
"-fsanitize=address",
"-fsanitize=bool",
"-fsanitize=bounds",
"-fsanitize=enum",
"-fsanitize=float-cast-overflow",
"-fsanitize=float-divide-by-zero",
"-fsanitize=leak",
"-fsanitize=nonnull-attribute",
"-fsanitize=object-size",
"-fsanitize=returns-nonnull-attribute",
"-fsanitize=signed-integer-overflow",
"-fsanitize=vla-bound",
]),
"-D", "COMPILER_ASAN_CXXFLAGS:STRING=" + " ".join([
"-Wanalyzer-allocation-size",
"-Wanalyzer-deref-before-check",
"-Wanalyzer-exposure-through-uninit-copy",
"-Wanalyzer-fd-access-mode-mismatch",
"-Wanalyzer-fd-double-close",
"-Wanalyzer-fd-leak",
"-Wanalyzer-fd-phase-mismatch",
"-Wanalyzer-fd-type-mismatch",
"-Wanalyzer-fd-use-after-close",
"-Wanalyzer-fd-use-without-check",
"-Wanalyzer-imprecise-fp-arithmetic",
"-Wanalyzer-infinite-recursion",
"-Wanalyzer-jump-through-null",
"-Wanalyzer-out-of-bounds",
"-Wanalyzer-putenv-of-auto-var",
"-Wanalyzer-tainted-assertion",
"-Wanalyzer-use-of-uninitialized-value",
"-Wanalyzer-write-to-const",
"-Wanalyzer-write-to-string-literal ",
"-fno-sanitize=alignment",
"-fsanitize-address-use-after-scope",
"-fsanitize=address",
"-fsanitize=bool",
"-fsanitize=bounds",
"-fsanitize=enum",
"-fsanitize=float-cast-overflow",
"-fsanitize=float-divide-by-zero",
"-fsanitize=leak",
"-fsanitize=nonnull-attribute",
"-fsanitize=object-size",
"-fsanitize=returns-nonnull-attribute",
"-fsanitize=signed-integer-overflow",
"-fsanitize=vla-bound",
]),
]
args.extend([
"-D", "CMAKE_C_COMPILER:STRING=" + compiler_bin_c,
"-D", "CMAKE_CXX_COMPILER=" + compiler_bin_cxx,
])
if do_compiler_asan:
args.extend([
"-D", "WITH_COMPILER_ASAN:BOOL=ON",
])
if do_local_python:
args.extend([
"-D", "PYTHON_VERSION:STRING=3.12",
"-D", "PYTHON_ROOT_DIR:FILEPATH=/opt/py312",
"-D", "WITH_PYTHON_INSTALL:BOOL=OFF",
"-D", "WITH_PYTHON_INSTALL_ZSTANDARD:BOOL=OFF",
])
else:
if not precompiled_libs:
args.extend([
"-D", "PYTHON_VERSION:STRING=3.11",
"-D", "WITH_PYTHON_INSTALL:BOOL=OFF",
"-D", "WITH_PYTHON_INSTALL_ZSTANDARD:BOOL=OFF",
])
subprocess.call(args)
def main():
import sys
if "debug" in sys.argv:
gen_build_dir(
source_dir="/src/blender",
build_dir="/src/cmake_debug",
compiler_family="GCC",
debug=True,
precompiled_libs=False,
fake_install=True,
)
if "release" in sys.argv:
gen_build_dir(
source_dir="/src/blender",
build_dir="/src/cmake_release",
compiler_family="CLANG",
debug=False,
precompiled_libs=True,
fake_install=False,
)
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment