Add Chromium-only Blender WebEngine parity work
This commit is contained in:
240
blender-5.2.0/tools/utils_ide/project_info.py
Executable file
240
blender-5.2.0/tools/utils_ide/project_info.py
Executable file
@@ -0,0 +1,240 @@
|
||||
#!/usr/bin/env python3
|
||||
# SPDX-FileCopyrightText: 2010-2023 Blender Authors
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
"""
|
||||
Module for accessing project file data for Blender.
|
||||
|
||||
Before use, call init(cmake_build_dir).
|
||||
"""
|
||||
|
||||
# TODO: Use CMAKE_EXPORT_COMPILE_COMMANDS (compile_commands.json)
|
||||
# Instead of Eclipse project format.
|
||||
|
||||
__all__ = (
|
||||
"SIMPLE_PROJECTFILE",
|
||||
"SOURCE_DIR",
|
||||
"CMAKE_DIR",
|
||||
"PROJECT_DIR",
|
||||
"source_list",
|
||||
"is_project_file",
|
||||
"is_c_header",
|
||||
"is_py",
|
||||
"cmake_advanced_info",
|
||||
"cmake_compiler_defines",
|
||||
"project_name_get",
|
||||
"init",
|
||||
)
|
||||
|
||||
from collections.abc import (
|
||||
Callable,
|
||||
Iterator,
|
||||
)
|
||||
|
||||
|
||||
import sys
|
||||
import subprocess
|
||||
import os
|
||||
from os.path import (
|
||||
abspath,
|
||||
dirname,
|
||||
exists,
|
||||
join,
|
||||
normpath,
|
||||
splitext,
|
||||
)
|
||||
|
||||
SOURCE_DIR = join(dirname(__file__), "..", "..")
|
||||
SOURCE_DIR = normpath(SOURCE_DIR)
|
||||
SOURCE_DIR = abspath(SOURCE_DIR)
|
||||
|
||||
SIMPLE_PROJECTFILE = False
|
||||
|
||||
# must initialize from 'init'
|
||||
CMAKE_DIR = ""
|
||||
PROJECT_DIR = ""
|
||||
|
||||
|
||||
def init(cmake_path: str) -> bool:
|
||||
global CMAKE_DIR, PROJECT_DIR
|
||||
|
||||
# get cmake path
|
||||
cmake_path = cmake_path or ""
|
||||
|
||||
if (not cmake_path) or (not exists(join(cmake_path, "CMakeCache.txt"))):
|
||||
cmake_path = os.getcwd()
|
||||
if not exists(join(cmake_path, "CMakeCache.txt")):
|
||||
print("CMakeCache.txt not found in %r or %r\n"
|
||||
" Pass CMake build dir as an argument, or run from that dir, aborting" %
|
||||
(cmake_path, os.getcwd()))
|
||||
return False
|
||||
|
||||
PROJECT_DIR = CMAKE_DIR = cmake_path
|
||||
return True
|
||||
|
||||
|
||||
def source_list(
|
||||
path: str,
|
||||
filename_check: Callable[[str], bool] | None = None,
|
||||
) -> Iterator[str]:
|
||||
for dirpath, dirnames, filenames in os.walk(path):
|
||||
# skip '.git'
|
||||
dirnames[:] = [d for d in dirnames if not d.startswith(".")]
|
||||
|
||||
for filename in filenames:
|
||||
filepath = join(dirpath, filename)
|
||||
if filename_check is None or filename_check(filepath):
|
||||
yield filepath
|
||||
|
||||
|
||||
# extension checking
|
||||
def is_cmake(filename: str) -> bool:
|
||||
ext = splitext(filename)[1]
|
||||
return (ext == ".cmake") or (filename.endswith("CMakeLists.txt"))
|
||||
|
||||
|
||||
def is_c_header(filename: str) -> bool:
|
||||
ext = splitext(filename)[1]
|
||||
return (ext in {".h", ".hpp", ".hxx", ".hh"})
|
||||
|
||||
|
||||
def is_py(filename: str) -> bool:
|
||||
ext = splitext(filename)[1]
|
||||
return (ext == ".py")
|
||||
|
||||
|
||||
def is_glsl(filename: str) -> bool:
|
||||
ext = splitext(filename)[1]
|
||||
return (ext == ".glsl")
|
||||
|
||||
|
||||
def is_c(filename: str) -> bool:
|
||||
ext = splitext(filename)[1]
|
||||
return (ext in {".c", ".cpp", ".cxx", ".m", ".mm", ".rc", ".cc", ".inl", ".osl"})
|
||||
|
||||
|
||||
def is_c_any(filename: str) -> bool:
|
||||
return is_c(filename) or is_c_header(filename)
|
||||
|
||||
|
||||
def is_project_file(filename: str) -> bool:
|
||||
return (is_c_any(filename) or is_cmake(filename) or is_glsl(filename))
|
||||
|
||||
|
||||
def cmake_advanced_info() -> (
|
||||
tuple[list[str], list[tuple[str, str]]] | None
|
||||
):
|
||||
""" Extract includes and defines from cmake.
|
||||
"""
|
||||
|
||||
make_exe = cmake_cache_var("CMAKE_MAKE_PROGRAM")
|
||||
if make_exe is None:
|
||||
print("Make command not found: CMAKE_MAKE_PROGRAM")
|
||||
return None
|
||||
|
||||
make_exe_basename = os.path.basename(make_exe)
|
||||
|
||||
def create_eclipse_project() -> str:
|
||||
print("CMAKE_DIR %r" % CMAKE_DIR)
|
||||
if sys.platform == "win32":
|
||||
raise Exception("Error: win32 is not supported")
|
||||
else:
|
||||
if make_exe_basename.startswith(("make", "gmake")):
|
||||
cmd = ("cmake", CMAKE_DIR, "-GEclipse CDT4 - Unix Makefiles")
|
||||
elif make_exe_basename.startswith("ninja"):
|
||||
cmd = ("cmake", CMAKE_DIR, "-GEclipse CDT4 - Ninja")
|
||||
else:
|
||||
raise Exception("Unknown make program %r" % make_exe)
|
||||
|
||||
subprocess.check_call(cmd)
|
||||
return join(CMAKE_DIR, ".cproject")
|
||||
|
||||
includes = []
|
||||
defines = []
|
||||
|
||||
project_path = create_eclipse_project()
|
||||
|
||||
if not exists(project_path):
|
||||
print("Generating Eclipse Project File Failed: %r not found" % project_path)
|
||||
return None
|
||||
|
||||
from xml.dom.minidom import parse
|
||||
tree = parse(project_path)
|
||||
|
||||
# Enable to check on nicer XML.
|
||||
use_pretty_xml = False
|
||||
if use_pretty_xml:
|
||||
with open(".cproject_pretty", 'w', encoding="utf-8") as fh:
|
||||
fh.write(tree.toprettyxml(indent=" ", newl=""))
|
||||
|
||||
ELEMENT_NODE = tree.ELEMENT_NODE
|
||||
|
||||
cproject, = tree.getElementsByTagName("cproject")
|
||||
for storage in cproject.childNodes:
|
||||
if storage.nodeType != ELEMENT_NODE:
|
||||
continue
|
||||
|
||||
if storage.attributes["moduleId"].value == "org.eclipse.cdt.core.settings":
|
||||
cconfig = storage.getElementsByTagName("cconfiguration")[0]
|
||||
for substorage in cconfig.childNodes:
|
||||
if substorage.nodeType != ELEMENT_NODE:
|
||||
continue
|
||||
|
||||
moduleId = substorage.attributes["moduleId"].value
|
||||
|
||||
if moduleId == "org.eclipse.cdt.core.pathentry":
|
||||
for path in substorage.childNodes:
|
||||
if path.nodeType != ELEMENT_NODE:
|
||||
continue
|
||||
kind = path.attributes["kind"].value
|
||||
|
||||
if kind == "mac":
|
||||
# `<pathentry kind="mac" name="PREFIX" path="" value=""/opt/blender25""/>`
|
||||
defines.append((path.attributes["name"].value, path.attributes["value"].value))
|
||||
elif kind == "inc":
|
||||
# `<pathentry include="/path/to/include" kind="inc" path="" system="true"/>`
|
||||
includes.append(path.attributes["include"].value)
|
||||
else:
|
||||
pass
|
||||
|
||||
return includes, defines
|
||||
|
||||
|
||||
def cmake_cache_var(var: str) -> str | None:
|
||||
with open(os.path.join(CMAKE_DIR, "CMakeCache.txt"), encoding='utf-8') as cache_file:
|
||||
lines = [
|
||||
line_strip for line in cache_file
|
||||
if (line_strip := line.strip())
|
||||
if not line_strip.startswith(("//", "#"))
|
||||
]
|
||||
|
||||
for line in lines:
|
||||
if line.split(":")[0] == var:
|
||||
return line.split("=", 1)[-1]
|
||||
return None
|
||||
|
||||
|
||||
def cmake_compiler_defines() -> list[str] | None:
|
||||
compiler = cmake_cache_var("CMAKE_C_COMPILER") # could do CXX too
|
||||
|
||||
if compiler is None:
|
||||
print("Couldn't find the compiler, os defines will be omitted...")
|
||||
return None
|
||||
|
||||
import tempfile
|
||||
temp_c = tempfile.mkstemp(suffix=".c")[1]
|
||||
temp_def = tempfile.mkstemp(suffix=".def")[1]
|
||||
|
||||
os.system("%s -dM -E %s > %s" % (compiler, temp_c, temp_def))
|
||||
|
||||
with open(temp_def, "r", encoding="utf-8") as temp_def_fh:
|
||||
lines = [line.strip() for line in temp_def_fh if line.strip()]
|
||||
|
||||
os.remove(temp_c)
|
||||
os.remove(temp_def)
|
||||
return lines
|
||||
|
||||
|
||||
def project_name_get() -> str | None:
|
||||
return cmake_cache_var("CMAKE_PROJECT_NAME")
|
||||
Reference in New Issue
Block a user