SCons: Colorize warnings/errors during generation

This commit is contained in:
Thaddeus Crews 2024-04-26 12:35:07 -05:00
parent 6118592c6d
commit e0e8ce1fc0
No known key found for this signature in database
GPG Key ID: 62181B86FE9E5D84
20 changed files with 415 additions and 335 deletions

View File

@ -15,6 +15,17 @@ from collections import OrderedDict
from importlib.util import spec_from_file_location, module_from_spec from importlib.util import spec_from_file_location, module_from_spec
from SCons import __version__ as scons_raw_version from SCons import __version__ as scons_raw_version
# Enable ANSI escape code support on Windows 10 and later (for colored console output).
# <https://github.com/python/cpython/issues/73245>
if sys.platform == "win32":
from ctypes import windll, c_int, byref
stdout_handle = windll.kernel32.GetStdHandle(c_int(-11))
mode = c_int(0)
windll.kernel32.GetConsoleMode(c_int(stdout_handle), byref(mode))
mode = c_int(mode.value | 4)
windll.kernel32.SetConsoleMode(c_int(stdout_handle), mode)
# Explicitly resolve the helper modules, this is done to avoid clash with # Explicitly resolve the helper modules, this is done to avoid clash with
# modules of the same name that might be randomly added (e.g. someone adding # modules of the same name that might be randomly added (e.g. someone adding
# an `editor.py` file at the root of the module creates a clash with the editor # an `editor.py` file at the root of the module creates a clash with the editor
@ -57,6 +68,7 @@ import methods
import glsl_builders import glsl_builders
import gles3_builders import gles3_builders
import scu_builders import scu_builders
from methods import print_warning, print_error
from platform_methods import architectures, architecture_aliases, generate_export_icons from platform_methods import architectures, architecture_aliases, generate_export_icons
if ARGUMENTS.get("target", "editor") == "editor": if ARGUMENTS.get("target", "editor") == "editor":
@ -311,38 +323,41 @@ if selected_platform == "":
selected_platform = "windows" selected_platform = "windows"
if selected_platform != "": if selected_platform != "":
print("Automatically detected platform: " + selected_platform) print(f"Automatically detected platform: {selected_platform}")
if selected_platform == "osx": if selected_platform == "osx":
# Deprecated alias kept for compatibility. # Deprecated alias kept for compatibility.
print('Platform "osx" has been renamed to "macos" in Godot 4. Building for platform "macos".') print_warning('Platform "osx" has been renamed to "macos" in Godot 4. Building for platform "macos".')
selected_platform = "macos" selected_platform = "macos"
if selected_platform == "iphone": if selected_platform == "iphone":
# Deprecated alias kept for compatibility. # Deprecated alias kept for compatibility.
print('Platform "iphone" has been renamed to "ios" in Godot 4. Building for platform "ios".') print_warning('Platform "iphone" has been renamed to "ios" in Godot 4. Building for platform "ios".')
selected_platform = "ios" selected_platform = "ios"
if selected_platform in ["linux", "bsd", "x11"]: if selected_platform in ["linux", "bsd", "x11"]:
if selected_platform == "x11": if selected_platform == "x11":
# Deprecated alias kept for compatibility. # Deprecated alias kept for compatibility.
print('Platform "x11" has been renamed to "linuxbsd" in Godot 4. Building for platform "linuxbsd".') print_warning('Platform "x11" has been renamed to "linuxbsd" in Godot 4. Building for platform "linuxbsd".')
# Alias for convenience. # Alias for convenience.
selected_platform = "linuxbsd" selected_platform = "linuxbsd"
if selected_platform == "javascript": if selected_platform == "javascript":
# Deprecated alias kept for compatibility. # Deprecated alias kept for compatibility.
print('Platform "javascript" has been renamed to "web" in Godot 4. Building for platform "web".') print_warning('Platform "javascript" has been renamed to "web" in Godot 4. Building for platform "web".')
selected_platform = "web" selected_platform = "web"
if selected_platform not in platform_list: if selected_platform not in platform_list:
if selected_platform == "": text = "The following platforms are available:\n\t{}\n".format("\n\t".join(platform_list))
print("Could not detect platform automatically.") text += "Please run SCons again and select a valid platform: platform=<string>."
elif selected_platform != "list":
print(f'Invalid target platform "{selected_platform}".') if selected_platform == "list":
print(text)
elif selected_platform == "":
print_error("Could not detect platform automatically.\n" + text)
else:
print_error(f'Invalid target platform "{selected_platform}".\n' + text)
print("The following platforms are available:\n\t{}\n".format("\n\t".join(platform_list)))
print("Please run SCons again and select a valid platform: platform=<string>.")
Exit(0 if selected_platform == "list" else 255) Exit(0 if selected_platform == "list" else 255)
# Make sure to update this to the found, valid platform as it's used through the buildsystem as the reference. # Make sure to update this to the found, valid platform as it's used through the buildsystem as the reference.
@ -368,7 +383,7 @@ if env["custom_modules"]:
try: try:
module_search_paths.append(methods.convert_custom_modules_path(p)) module_search_paths.append(methods.convert_custom_modules_path(p))
except ValueError as e: except ValueError as e:
print(e) print_error(e)
Exit(255) Exit(255)
for path in module_search_paths: for path in module_search_paths:
@ -507,7 +522,7 @@ env.SetOption("num_jobs", altered_num_jobs)
if env.GetOption("num_jobs") == altered_num_jobs: if env.GetOption("num_jobs") == altered_num_jobs:
cpu_count = os.cpu_count() cpu_count = os.cpu_count()
if cpu_count is None: if cpu_count is None:
print("Couldn't auto-detect CPU count to configure build parallelism. Specify it with the -j argument.") print_warning("Couldn't auto-detect CPU count to configure build parallelism. Specify it with the -j argument.")
else: else:
safer_cpu_count = cpu_count if cpu_count <= 4 else cpu_count - 1 safer_cpu_count = cpu_count if cpu_count <= 4 else cpu_count - 1
print( print(
@ -531,7 +546,7 @@ env.Append(LINKFLAGS=env.get("linkflags", "").split())
# Feature build profile # Feature build profile
disabled_classes = [] disabled_classes = []
if env["build_profile"] != "": if env["build_profile"] != "":
print("Using feature build profile: " + env["build_profile"]) print('Using feature build profile: "{}"'.format(env["build_profile"]))
import json import json
try: try:
@ -543,7 +558,7 @@ if env["build_profile"] != "":
for c in dbo: for c in dbo:
env[c] = dbo[c] env[c] = dbo[c]
except: except:
print("Error opening feature build profile: " + env["build_profile"]) print_error('Failed to open feature build profile: "{}"'.format(env["build_profile"]))
Exit(255) Exit(255)
methods.write_disabled_classes(disabled_classes) methods.write_disabled_classes(disabled_classes)
@ -605,14 +620,14 @@ cc_version_metadata1 = cc_version["metadata1"] or ""
if methods.using_gcc(env): if methods.using_gcc(env):
if cc_version_major == -1: if cc_version_major == -1:
print( print_warning(
"Couldn't detect compiler version, skipping version checks. " "Couldn't detect compiler version, skipping version checks. "
"Build may fail if the compiler doesn't support C++17 fully." "Build may fail if the compiler doesn't support C++17 fully."
) )
# GCC 8 before 8.4 has a regression in the support of guaranteed copy elision # GCC 8 before 8.4 has a regression in the support of guaranteed copy elision
# which causes a build failure: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86521 # which causes a build failure: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86521
elif cc_version_major == 8 and cc_version_minor < 4: elif cc_version_major == 8 and cc_version_minor < 4:
print( print_error(
"Detected GCC 8 version < 8.4, which is not supported due to a " "Detected GCC 8 version < 8.4, which is not supported due to a "
"regression in its C++17 guaranteed copy elision support. Use a " "regression in its C++17 guaranteed copy elision support. Use a "
'newer GCC version, or Clang 6 or later by passing "use_llvm=yes" ' 'newer GCC version, or Clang 6 or later by passing "use_llvm=yes" '
@ -620,7 +635,7 @@ if methods.using_gcc(env):
) )
Exit(255) Exit(255)
elif cc_version_major < 7: elif cc_version_major < 7:
print( print_error(
"Detected GCC version older than 7, which does not fully support " "Detected GCC version older than 7, which does not fully support "
"C++17. Supported versions are GCC 7, 9 and later. Use a newer GCC " "C++17. Supported versions are GCC 7, 9 and later. Use a newer GCC "
'version, or Clang 6 or later by passing "use_llvm=yes" to the ' 'version, or Clang 6 or later by passing "use_llvm=yes" to the '
@ -628,7 +643,7 @@ if methods.using_gcc(env):
) )
Exit(255) Exit(255)
elif cc_version_metadata1 == "win32": elif cc_version_metadata1 == "win32":
print( print_error(
"Detected mingw version is not using posix threads. Only posix " "Detected mingw version is not using posix threads. Only posix "
"version of mingw is supported. " "version of mingw is supported. "
'Use "update-alternatives --config x86_64-w64-mingw32-g++" ' 'Use "update-alternatives --config x86_64-w64-mingw32-g++" '
@ -636,11 +651,11 @@ if methods.using_gcc(env):
) )
Exit(255) Exit(255)
if env["debug_paths_relative"] and cc_version_major < 8: if env["debug_paths_relative"] and cc_version_major < 8:
print("GCC < 8 doesn't support -ffile-prefix-map, disabling `debug_paths_relative` option.") print_warning("GCC < 8 doesn't support -ffile-prefix-map, disabling `debug_paths_relative` option.")
env["debug_paths_relative"] = False env["debug_paths_relative"] = False
elif methods.using_clang(env): elif methods.using_clang(env):
if cc_version_major == -1: if cc_version_major == -1:
print( print_warning(
"Couldn't detect compiler version, skipping version checks. " "Couldn't detect compiler version, skipping version checks. "
"Build may fail if the compiler doesn't support C++17 fully." "Build may fail if the compiler doesn't support C++17 fully."
) )
@ -649,28 +664,30 @@ elif methods.using_clang(env):
elif env["platform"] == "macos" or env["platform"] == "ios": elif env["platform"] == "macos" or env["platform"] == "ios":
vanilla = methods.is_vanilla_clang(env) vanilla = methods.is_vanilla_clang(env)
if vanilla and cc_version_major < 6: if vanilla and cc_version_major < 6:
print( print_warning(
"Detected Clang version older than 6, which does not fully support " "Detected Clang version older than 6, which does not fully support "
"C++17. Supported versions are Clang 6 and later." "C++17. Supported versions are Clang 6 and later."
) )
Exit(255) Exit(255)
elif not vanilla and cc_version_major < 10: elif not vanilla and cc_version_major < 10:
print( print_error(
"Detected Apple Clang version older than 10, which does not fully " "Detected Apple Clang version older than 10, which does not fully "
"support C++17. Supported versions are Apple Clang 10 and later." "support C++17. Supported versions are Apple Clang 10 and later."
) )
Exit(255) Exit(255)
if env["debug_paths_relative"] and not vanilla and cc_version_major < 12: if env["debug_paths_relative"] and not vanilla and cc_version_major < 12:
print("Apple Clang < 12 doesn't support -ffile-prefix-map, disabling `debug_paths_relative` option.") print_warning(
"Apple Clang < 12 doesn't support -ffile-prefix-map, disabling `debug_paths_relative` option."
)
env["debug_paths_relative"] = False env["debug_paths_relative"] = False
elif cc_version_major < 6: elif cc_version_major < 6:
print( print_error(
"Detected Clang version older than 6, which does not fully support " "Detected Clang version older than 6, which does not fully support "
"C++17. Supported versions are Clang 6 and later." "C++17. Supported versions are Clang 6 and later."
) )
Exit(255) Exit(255)
if env["debug_paths_relative"] and cc_version_major < 10: if env["debug_paths_relative"] and cc_version_major < 10:
print("Clang < 10 doesn't support -ffile-prefix-map, disabling `debug_paths_relative` option.") print_warning("Clang < 10 doesn't support -ffile-prefix-map, disabling `debug_paths_relative` option.")
env["debug_paths_relative"] = False env["debug_paths_relative"] = False
# Set optimize and debug_symbols flags. # Set optimize and debug_symbols flags.
@ -906,7 +923,7 @@ if env.editor_build:
# And check if they are met. # And check if they are met.
if not env.module_check_dependencies("editor"): if not env.module_check_dependencies("editor"):
print("Not all modules required by editor builds are enabled.") print_error("Not all modules required by editor builds are enabled.")
Exit(255) Exit(255)
methods.generate_version_header(env.module_version_string) methods.generate_version_header(env.module_version_string)
@ -932,14 +949,14 @@ env["SHOBJPREFIX"] = env["object_prefix"]
if env["disable_3d"]: if env["disable_3d"]:
if env.editor_build: if env.editor_build:
print("Build option 'disable_3d=yes' cannot be used for editor builds, only for export template builds.") print_error("Build option `disable_3d=yes` cannot be used for editor builds, only for export template builds.")
Exit(255) Exit(255)
else: else:
env.Append(CPPDEFINES=["_3D_DISABLED"]) env.Append(CPPDEFINES=["_3D_DISABLED"])
if env["disable_advanced_gui"]: if env["disable_advanced_gui"]:
if env.editor_build: if env.editor_build:
print( print_error(
"Build option 'disable_advanced_gui=yes' cannot be used for editor builds, " "Build option `disable_advanced_gui=yes` cannot be used for editor builds, "
"only for export template builds." "only for export template builds."
) )
Exit(255) Exit(255)
@ -951,7 +968,7 @@ if env["brotli"]:
env.Append(CPPDEFINES=["BROTLI_ENABLED"]) env.Append(CPPDEFINES=["BROTLI_ENABLED"])
if not env["verbose"]: if not env["verbose"]:
methods.no_verbose(sys, env) methods.no_verbose(env)
GLSL_BUILDERS = { GLSL_BUILDERS = {
"RD_GLSL": env.Builder( "RD_GLSL": env.Builder(
@ -983,7 +1000,7 @@ if env["vsproj"]:
if env["compiledb"] and env.scons_version < (4, 0, 0): if env["compiledb"] and env.scons_version < (4, 0, 0):
# Generating the compilation DB (`compile_commands.json`) requires SCons 4.0.0 or later. # Generating the compilation DB (`compile_commands.json`) requires SCons 4.0.0 or later.
print("The `compiledb=yes` option requires SCons 4.0 or later, but your version is %s." % scons_raw_version) print_error("The `compiledb=yes` option requires SCons 4.0 or later, but your version is %s." % scons_raw_version)
Exit(255) Exit(255)
if env.scons_version >= (4, 0, 0): if env.scons_version >= (4, 0, 0):
env.Tool("compilation_db") env.Tool("compilation_db")
@ -991,7 +1008,7 @@ if env.scons_version >= (4, 0, 0):
if env["ninja"]: if env["ninja"]:
if env.scons_version < (4, 2, 0): if env.scons_version < (4, 2, 0):
print("The `ninja=yes` option requires SCons 4.2 or later, but your version is %s." % scons_raw_version) print_error("The `ninja=yes` option requires SCons 4.2 or later, but your version is %s." % scons_raw_version)
Exit(255) Exit(255)
SetOption("experimental", "ninja") SetOption("experimental", "ninja")
@ -1048,9 +1065,16 @@ methods.dump(env)
def print_elapsed_time(): def print_elapsed_time():
elapsed_time_sec = round(time.time() - time_at_start, 3) elapsed_time_sec = round(time.time() - time_at_start, 2)
time_ms = round((elapsed_time_sec % 1) * 1000) time_centiseconds = round((elapsed_time_sec % 1) * 100)
print("[Time elapsed: {}.{:03}]".format(time.strftime("%H:%M:%S", time.gmtime(elapsed_time_sec)), time_ms)) print(
"{}[Time elapsed: {}.{:02}]{}".format(
methods.ANSI.GRAY,
time.strftime("%H:%M:%S", time.gmtime(elapsed_time_sec)),
time_centiseconds,
methods.ANSI.RESET,
)
)
atexit.register(print_elapsed_time) atexit.register(print_elapsed_time)

View File

@ -29,8 +29,8 @@ if "SCRIPT_AES256_ENCRYPTION_KEY" in os.environ:
ec_valid = False ec_valid = False
txt += txts txt += txts
if not ec_valid: if not ec_valid:
print("Error: Invalid AES256 encryption key, not 64 hexadecimal characters: '" + key + "'.") methods.print_error(
print( f'Invalid AES256 encryption key, not 64 hexadecimal characters: "{key}".\n'
"Unset 'SCRIPT_AES256_ENCRYPTION_KEY' in your environment " "Unset 'SCRIPT_AES256_ENCRYPTION_KEY' in your environment "
"or make sure that it contains exactly 64 hexadecimal characters." "or make sure that it contains exactly 64 hexadecimal characters."
) )

View File

@ -7,6 +7,7 @@ import subprocess
import tempfile import tempfile
import uuid import uuid
import zlib import zlib
from methods import print_warning
def make_doc_header(target, source, env): def make_doc_header(target, source, env):
@ -57,7 +58,7 @@ def make_translations_header(target, source, env, category):
msgfmt_available = shutil.which("msgfmt") is not None msgfmt_available = shutil.which("msgfmt") is not None
if not msgfmt_available: if not msgfmt_available:
print("WARNING: msgfmt is not found, using .po files instead of .mo") print_warning("msgfmt is not found, using .po files instead of .mo")
xl_names = [] xl_names = []
for i in range(len(sorted_paths)): for i in range(len(sorted_paths)):
@ -71,8 +72,8 @@ def make_translations_header(target, source, env, category):
with open(mo_path, "rb") as f: with open(mo_path, "rb") as f:
buf = f.read() buf = f.read()
except OSError as e: except OSError as e:
print( print_warning(
"WARNING: msgfmt execution failed, using .po file instead of .mo: path=%r; [%s] %s" "msgfmt execution failed, using .po file instead of .mo: path=%r; [%s] %s"
% (sorted_paths[i], e.__class__.__name__, e) % (sorted_paths[i], e.__class__.__name__, e)
) )
with open(sorted_paths[i], "rb") as f: with open(sorted_paths[i], "rb") as f:
@ -82,9 +83,8 @@ def make_translations_header(target, source, env, category):
os.remove(mo_path) os.remove(mo_path)
except OSError as e: except OSError as e:
# Do not fail the entire build if it cannot delete a temporary file. # Do not fail the entire build if it cannot delete a temporary file.
print( print_warning(
"WARNING: Could not delete temporary .mo file: path=%r; [%s] %s" "Could not delete temporary .mo file: path=%r; [%s] %s" % (mo_path, e.__class__.__name__, e)
% (mo_path, e.__class__.__name__, e)
) )
else: else:
with open(sorted_paths[i], "rb") as f: with open(sorted_paths[i], "rb") as f:

View File

@ -1,7 +1,7 @@
"""Functions used to generate source files during build time""" """Functions used to generate source files during build time"""
import os.path import os.path
from methods import print_error
from typing import Optional from typing import Optional
@ -94,11 +94,11 @@ def include_file_in_gles3_header(filename: str, header_data: GLES3HeaderStruct,
if not included_file in header_data.vertex_included_files and header_data.reading == "vertex": if not included_file in header_data.vertex_included_files and header_data.reading == "vertex":
header_data.vertex_included_files += [included_file] header_data.vertex_included_files += [included_file]
if include_file_in_gles3_header(included_file, header_data, depth + 1) is None: if include_file_in_gles3_header(included_file, header_data, depth + 1) is None:
print("Error in file '" + filename + "': #include " + includeline + "could not be found!") print_error(f'In file "{filename}": #include "{includeline}" could not be found!"')
elif not included_file in header_data.fragment_included_files and header_data.reading == "fragment": elif not included_file in header_data.fragment_included_files and header_data.reading == "fragment":
header_data.fragment_included_files += [included_file] header_data.fragment_included_files += [included_file]
if include_file_in_gles3_header(included_file, header_data, depth + 1) is None: if include_file_in_gles3_header(included_file, header_data, depth + 1) is None:
print("Error in file '" + filename + "': #include " + includeline + "could not be found!") print_error(f'In file "{filename}": #include "{includeline}" could not be found!"')
line = fs.readline() line = fs.readline()

View File

@ -1,6 +1,7 @@
"""Functions used to generate source files during build time""" """Functions used to generate source files during build time"""
import os.path import os.path
from methods import print_error
from typing import Optional, Iterable from typing import Optional, Iterable
@ -79,15 +80,15 @@ def include_file_in_rd_header(filename: str, header_data: RDHeaderStruct, depth:
if not included_file in header_data.vertex_included_files and header_data.reading == "vertex": if not included_file in header_data.vertex_included_files and header_data.reading == "vertex":
header_data.vertex_included_files += [included_file] header_data.vertex_included_files += [included_file]
if include_file_in_rd_header(included_file, header_data, depth + 1) is None: if include_file_in_rd_header(included_file, header_data, depth + 1) is None:
print("Error in file '" + filename + "': #include " + includeline + "could not be found!") print_error(f'In file "{filename}": #include "{includeline}" could not be found!"')
elif not included_file in header_data.fragment_included_files and header_data.reading == "fragment": elif not included_file in header_data.fragment_included_files and header_data.reading == "fragment":
header_data.fragment_included_files += [included_file] header_data.fragment_included_files += [included_file]
if include_file_in_rd_header(included_file, header_data, depth + 1) is None: if include_file_in_rd_header(included_file, header_data, depth + 1) is None:
print("Error in file '" + filename + "': #include " + includeline + "could not be found!") print_error(f'In file "{filename}": #include "{includeline}" could not be found!"')
elif not included_file in header_data.compute_included_files and header_data.reading == "compute": elif not included_file in header_data.compute_included_files and header_data.reading == "compute":
header_data.compute_included_files += [included_file] header_data.compute_included_files += [included_file]
if include_file_in_rd_header(included_file, header_data, depth + 1) is None: if include_file_in_rd_header(included_file, header_data, depth + 1) is None:
print("Error in file '" + filename + "': #include " + includeline + "could not be found!") print_error(f'In file "{filename}": #include "{includeline}" could not be found!"')
line = fs.readline() line = fs.readline()

View File

@ -5,6 +5,7 @@ import glob
import subprocess import subprocess
from collections import OrderedDict from collections import OrderedDict
from collections.abc import Mapping from collections.abc import Mapping
from enum import Enum
from typing import Iterator from typing import Iterator
from pathlib import Path from pathlib import Path
from os.path import normpath, basename from os.path import normpath, basename
@ -15,6 +16,10 @@ base_folder_only = os.path.basename(os.path.normpath(base_folder_path))
# Listing all the folders we have converted # Listing all the folders we have converted
# for SCU in scu_builders.py # for SCU in scu_builders.py
_scu_folders = set() _scu_folders = set()
# Colors are disabled in non-TTY environments such as pipes. This means
# that if output is redirected to a file, it won't contain color codes.
# Colors are always enabled on continuous integration.
_colorize = bool(sys.stdout.isatty() or os.environ.get("CI"))
def set_scu_folders(scu_folders): def set_scu_folders(scu_folders):
@ -22,13 +27,55 @@ def set_scu_folders(scu_folders):
_scu_folders = scu_folders _scu_folders = scu_folders
class ANSI(Enum):
"""
Enum class for adding ansi colorcodes directly into strings.
Automatically converts values to strings representing their
internal value, or an empty string in a non-colorized scope.
"""
GRAY = "\x1b[0;30m"
RED = "\x1b[0;31m"
GREEN = "\x1b[0;32m"
YELLOW = "\x1b[0;33m"
BLUE = "\x1b[0;34m"
PURPLE = "\x1b[0;35m"
CYAN = "\x1b[0;36m"
WHITE = "\x1b[0;37m"
BOLD_GRAY = "\x1b[1;90m"
BOLD_RED = "\x1b[1;91m"
BOLD_GREEN = "\x1b[1;92m"
BOLD_YELLOW = "\x1b[1;93m"
BOLD_BLUE = "\x1b[1;94m"
BOLD_PURPLE = "\x1b[1;95m"
BOLD_CYAN = "\x1b[1;96m"
BOLD_WHITE = "\x1b[1;97m"
RESET = "\x1b[0m"
def __str__(self):
global _colorize
return self.value if _colorize else ""
def print_warning(*values: object) -> None:
"""Prints a warning message with formatting."""
print(f"{ANSI.BOLD_YELLOW}WARNING:{ANSI.YELLOW}", *values, ANSI.RESET, file=sys.stderr)
def print_error(*values: object) -> None:
"""Prints an error message with formatting."""
print(f"{ANSI.BOLD_RED}ERROR:{ANSI.RED}", *values, ANSI.RESET, file=sys.stderr)
def add_source_files_orig(self, sources, files, allow_gen=False): def add_source_files_orig(self, sources, files, allow_gen=False):
# Convert string to list of absolute paths (including expanding wildcard) # Convert string to list of absolute paths (including expanding wildcard)
if isinstance(files, (str, bytes)): if isinstance(files, (str, bytes)):
# Keep SCons project-absolute path as they are (no wildcard support) # Keep SCons project-absolute path as they are (no wildcard support)
if files.startswith("#"): if files.startswith("#"):
if "*" in files: if "*" in files:
print("ERROR: Wildcards can't be expanded in SCons project-absolute path: '{}'".format(files)) print_error("Wildcards can't be expanded in SCons project-absolute path: '{}'".format(files))
return return
files = [files] files = [files]
else: else:
@ -44,7 +91,7 @@ def add_source_files_orig(self, sources, files, allow_gen=False):
for path in files: for path in files:
obj = self.Object(path) obj = self.Object(path)
if obj in sources: if obj in sources:
print('WARNING: Object "{}" already included in environment sources.'.format(obj)) print_warning('Object "{}" already included in environment sources.'.format(obj))
continue continue
sources.append(obj) sources.append(obj)
@ -517,7 +564,7 @@ def module_check_dependencies(self, module):
missing_deps.append(dep) missing_deps.append(dep)
if missing_deps != []: if missing_deps != []:
print( print_warning(
"Disabling '{}' module as the following dependencies are not satisfied: {}".format( "Disabling '{}' module as the following dependencies are not satisfied: {}".format(
module, ", ".join(missing_deps) module, ", ".join(missing_deps)
) )
@ -576,9 +623,7 @@ def use_windows_spawn_fix(self, platform=None):
_, err = proc.communicate() _, err = proc.communicate()
rv = proc.wait() rv = proc.wait()
if rv: if rv:
print("=====") print_error(err)
print(err)
print("=====")
return rv return rv
def mySpawn(sh, escape, cmd, args, env): def mySpawn(sh, escape, cmd, args, env):
@ -601,65 +646,34 @@ def use_windows_spawn_fix(self, platform=None):
self["SPAWN"] = mySpawn self["SPAWN"] = mySpawn
def no_verbose(sys, env): def no_verbose(env):
colors = {} colors = [ANSI.BLUE, ANSI.BOLD_BLUE, ANSI.RESET]
# Colors are disabled in non-TTY environments such as pipes. This means
# that if output is redirected to a file, it will not contain color codes
if sys.stdout.isatty():
colors["blue"] = "\033[0;94m"
colors["bold_blue"] = "\033[1;94m"
colors["reset"] = "\033[0m"
else:
colors["blue"] = ""
colors["bold_blue"] = ""
colors["reset"] = ""
# There is a space before "..." to ensure that source file names can be # There is a space before "..." to ensure that source file names can be
# Ctrl + clicked in the VS Code terminal. # Ctrl + clicked in the VS Code terminal.
compile_source_message = "{}Compiling {}$SOURCE{} ...{}".format( compile_source_message = "{0}Compiling {1}$SOURCE{0} ...{2}".format(*colors)
colors["blue"], colors["bold_blue"], colors["blue"], colors["reset"] java_compile_source_message = "{0}Compiling {1}$SOURCE{0} ...{2}".format(*colors)
) compile_shared_source_message = "{0}Compiling shared {1}$SOURCE{0} ...{2}".format(*colors)
java_compile_source_message = "{}Compiling {}$SOURCE{} ...{}".format( link_program_message = "{0}Linking Program {1}$TARGET{0} ...{2}".format(*colors)
colors["blue"], colors["bold_blue"], colors["blue"], colors["reset"] link_library_message = "{0}Linking Static Library {1}$TARGET{0} ...{2}".format(*colors)
) ranlib_library_message = "{0}Ranlib Library {1}$TARGET{0} ...{2}".format(*colors)
compile_shared_source_message = "{}Compiling shared {}$SOURCE{} ...{}".format( link_shared_library_message = "{0}Linking Shared Library {1}$TARGET{0} ...{2}".format(*colors)
colors["blue"], colors["bold_blue"], colors["blue"], colors["reset"] java_library_message = "{0}Creating Java Archive {1}$TARGET{0} ...{2}".format(*colors)
) compiled_resource_message = "{0}Creating Compiled Resource {1}$TARGET{0} ...{2}".format(*colors)
link_program_message = "{}Linking Program {}$TARGET{} ...{}".format( generated_file_message = "{0}Generating {1}$TARGET{0} ...{2}".format(*colors)
colors["blue"], colors["bold_blue"], colors["blue"], colors["reset"]
)
link_library_message = "{}Linking Static Library {}$TARGET{} ...{}".format(
colors["blue"], colors["bold_blue"], colors["blue"], colors["reset"]
)
ranlib_library_message = "{}Ranlib Library {}$TARGET{} ...{}".format(
colors["blue"], colors["bold_blue"], colors["blue"], colors["reset"]
)
link_shared_library_message = "{}Linking Shared Library {}$TARGET{} ...{}".format(
colors["blue"], colors["bold_blue"], colors["blue"], colors["reset"]
)
java_library_message = "{}Creating Java Archive {}$TARGET{} ...{}".format(
colors["blue"], colors["bold_blue"], colors["blue"], colors["reset"]
)
compiled_resource_message = "{}Creating Compiled Resource {}$TARGET{} ...{}".format(
colors["blue"], colors["bold_blue"], colors["blue"], colors["reset"]
)
generated_file_message = "{}Generating {}$TARGET{} ...{}".format(
colors["blue"], colors["bold_blue"], colors["blue"], colors["reset"]
)
env.Append(CXXCOMSTR=[compile_source_message]) env.Append(CXXCOMSTR=compile_source_message)
env.Append(CCCOMSTR=[compile_source_message]) env.Append(CCCOMSTR=compile_source_message)
env.Append(SHCCCOMSTR=[compile_shared_source_message]) env.Append(SHCCCOMSTR=compile_shared_source_message)
env.Append(SHCXXCOMSTR=[compile_shared_source_message]) env.Append(SHCXXCOMSTR=compile_shared_source_message)
env.Append(ARCOMSTR=[link_library_message]) env.Append(ARCOMSTR=link_library_message)
env.Append(RANLIBCOMSTR=[ranlib_library_message]) env.Append(RANLIBCOMSTR=ranlib_library_message)
env.Append(SHLINKCOMSTR=[link_shared_library_message]) env.Append(SHLINKCOMSTR=link_shared_library_message)
env.Append(LINKCOMSTR=[link_program_message]) env.Append(LINKCOMSTR=link_program_message)
env.Append(JARCOMSTR=[java_library_message]) env.Append(JARCOMSTR=java_library_message)
env.Append(JAVACCOMSTR=[java_compile_source_message]) env.Append(JAVACCOMSTR=java_compile_source_message)
env.Append(RCCOMSTR=[compiled_resource_message]) env.Append(RCCOMSTR=compiled_resource_message)
env.Append(GENCOMSTR=[generated_file_message]) env.Append(GENCOMSTR=generated_file_message)
def detect_visual_c_compiler_version(tools_env): def detect_visual_c_compiler_version(tools_env):
@ -790,7 +804,7 @@ def generate_cpp_hint_file(filename):
with open(filename, "w", encoding="utf-8", newline="\n") as fd: with open(filename, "w", encoding="utf-8", newline="\n") as fd:
fd.write("#define GDCLASS(m_class, m_inherits)\n") fd.write("#define GDCLASS(m_class, m_inherits)\n")
except OSError: except OSError:
print("Could not write cpp.hint file.") print_warning("Could not write cpp.hint file.")
def glob_recursive(pattern, node="."): def glob_recursive(pattern, node="."):
@ -881,7 +895,7 @@ def detect_darwin_sdk_path(platform, env):
if sdk_path: if sdk_path:
env[var_name] = sdk_path env[var_name] = sdk_path
except (subprocess.CalledProcessError, OSError): except (subprocess.CalledProcessError, OSError):
print("Failed to find SDK path while running xcrun --sdk {} --show-sdk-path.".format(sdk_name)) print_error("Failed to find SDK path while running xcrun --sdk {} --show-sdk-path.".format(sdk_name))
raise raise
@ -891,7 +905,7 @@ def is_vanilla_clang(env):
try: try:
version = subprocess.check_output([env.subst(env["CXX"]), "--version"]).strip().decode("utf-8") version = subprocess.check_output([env.subst(env["CXX"]), "--version"]).strip().decode("utf-8")
except (subprocess.CalledProcessError, OSError): except (subprocess.CalledProcessError, OSError):
print("Couldn't parse CXX environment variable to infer compiler version.") print_warning("Couldn't parse CXX environment variable to infer compiler version.")
return False return False
return not version.startswith("Apple") return not version.startswith("Apple")
@ -928,7 +942,7 @@ def get_compiler_version(env):
.decode("utf-8") .decode("utf-8")
) )
except (subprocess.CalledProcessError, OSError): except (subprocess.CalledProcessError, OSError):
print("Couldn't parse CXX environment variable to infer compiler version.") print_warning("Couldn't parse CXX environment variable to infer compiler version.")
return ret return ret
else: else:
# TODO: Implement for MSVC # TODO: Implement for MSVC

View File

@ -1,10 +1,20 @@
#!/usr/bin/env python #!/usr/bin/env python
import atexit import atexit
import os
import sys import sys
import methods import methods
import time import time
# Enable ANSI escape code support on Windows 10 and later (for colored console output).
# <https://github.com/python/cpython/issues/73245>
if sys.platform == "win32":
from ctypes import windll, c_int, byref
stdout_handle = windll.kernel32.GetStdHandle(c_int(-11))
mode = c_int(0)
windll.kernel32.GetConsoleMode(c_int(stdout_handle), byref(mode))
mode = c_int(mode.value | 4)
windll.kernel32.SetConsoleMode(c_int(stdout_handle), mode)
# For the reference: # For the reference:
# - CCFLAGS are compilation flags shared between C and C++ # - CCFLAGS are compilation flags shared between C and C++
# - CFLAGS are for C-specific compilation flags # - CFLAGS are for C-specific compilation flags
@ -30,7 +40,7 @@ opts.Add(BoolVariable("verbose", "Enable verbose output for the compilation", Fa
opts.Update(env) opts.Update(env)
if not env["verbose"]: if not env["verbose"]:
methods.no_verbose(sys, env) methods.no_verbose(env)
if env["platform"] == "windows" and not env["use_mingw"]: if env["platform"] == "windows" and not env["use_mingw"]:
env.AppendUnique(CCFLAGS=["/utf-8"]) # Force to use Unicode encoding. env.AppendUnique(CCFLAGS=["/utf-8"]) # Force to use Unicode encoding.
@ -764,9 +774,16 @@ Default(library)
def print_elapsed_time(): def print_elapsed_time():
elapsed_time_sec = round(time.time() - time_at_start, 3) elapsed_time_sec = round(time.time() - time_at_start, 2)
time_ms = round((elapsed_time_sec % 1) * 1000) time_centiseconds = round((elapsed_time_sec % 1) * 100)
print("[Time elapsed: {}.{:03}]".format(time.strftime("%H:%M:%S", time.gmtime(elapsed_time_sec)), time_ms)) print(
"{}[Time elapsed: {}.{:02}]{}".format(
methods.ANSI.GRAY,
time.strftime("%H:%M:%S", time.gmtime(elapsed_time_sec)),
time_centiseconds,
methods.ANSI.RESET,
)
)
atexit.register(print_elapsed_time) atexit.register(print_elapsed_time)

View File

@ -1,66 +1,73 @@
import os import os
import sys import sys
from enum import Enum
def no_verbose(sys, env):
colors = {}
# Colors are disabled in non-TTY environments such as pipes. This means # Colors are disabled in non-TTY environments such as pipes. This means
# that if output is redirected to a file, it will not contain color codes # that if output is redirected to a file, it won't contain color codes.
if sys.stdout.isatty(): # Colors are always enabled on continuous integration.
colors["blue"] = "\033[0;94m" _colorize = bool(sys.stdout.isatty() or os.environ.get("CI"))
colors["bold_blue"] = "\033[1;94m"
colors["reset"] = "\033[0m"
else: class ANSI(Enum):
colors["blue"] = "" """
colors["bold_blue"] = "" Enum class for adding ansi colorcodes directly into strings.
colors["reset"] = "" Automatically converts values to strings representing their
internal value, or an empty string in a non-colorized scope.
"""
GRAY = "\x1b[0;30m"
RED = "\x1b[0;31m"
GREEN = "\x1b[0;32m"
YELLOW = "\x1b[0;33m"
BLUE = "\x1b[0;34m"
PURPLE = "\x1b[0;35m"
CYAN = "\x1b[0;36m"
WHITE = "\x1b[0;37m"
BOLD_GRAY = "\x1b[1;90m"
BOLD_RED = "\x1b[1;91m"
BOLD_GREEN = "\x1b[1;92m"
BOLD_YELLOW = "\x1b[1;93m"
BOLD_BLUE = "\x1b[1;94m"
BOLD_PURPLE = "\x1b[1;95m"
BOLD_CYAN = "\x1b[1;96m"
BOLD_WHITE = "\x1b[1;97m"
RESET = "\x1b[0m"
def __str__(self):
global _colorize
return self.value if _colorize else ""
def no_verbose(env):
colors = [ANSI.BLUE, ANSI.BOLD_BLUE, ANSI.RESET]
# There is a space before "..." to ensure that source file names can be # There is a space before "..." to ensure that source file names can be
# Ctrl + clicked in the VS Code terminal. # Ctrl + clicked in the VS Code terminal.
compile_source_message = "{}Compiling {}$SOURCE{} ...{}".format( compile_source_message = "{0}Compiling {1}$SOURCE{0} ...{2}".format(*colors)
colors["blue"], colors["bold_blue"], colors["blue"], colors["reset"] java_compile_source_message = "{0}Compiling {1}$SOURCE{0} ...{2}".format(*colors)
) compile_shared_source_message = "{0}Compiling shared {1}$SOURCE{0} ...{2}".format(*colors)
java_compile_source_message = "{}Compiling {}$SOURCE{} ...{}".format( link_program_message = "{0}Linking Program {1}$TARGET{0} ...{2}".format(*colors)
colors["blue"], colors["bold_blue"], colors["blue"], colors["reset"] link_library_message = "{0}Linking Static Library {1}$TARGET{0} ...{2}".format(*colors)
) ranlib_library_message = "{0}Ranlib Library {1}$TARGET{0} ...{2}".format(*colors)
compile_shared_source_message = "{}Compiling shared {}$SOURCE{} ...{}".format( link_shared_library_message = "{0}Linking Shared Library {1}$TARGET{0} ...{2}".format(*colors)
colors["blue"], colors["bold_blue"], colors["blue"], colors["reset"] java_library_message = "{0}Creating Java Archive {1}$TARGET{0} ...{2}".format(*colors)
) compiled_resource_message = "{0}Creating Compiled Resource {1}$TARGET{0} ...{2}".format(*colors)
link_program_message = "{}Linking Program {}$TARGET{} ...{}".format( generated_file_message = "{0}Generating {1}$TARGET{0} ...{2}".format(*colors)
colors["blue"], colors["bold_blue"], colors["blue"], colors["reset"]
)
link_library_message = "{}Linking Static Library {}$TARGET{} ...{}".format(
colors["blue"], colors["bold_blue"], colors["blue"], colors["reset"]
)
ranlib_library_message = "{}Ranlib Library {}$TARGET{} ...{}".format(
colors["blue"], colors["bold_blue"], colors["blue"], colors["reset"]
)
link_shared_library_message = "{}Linking Shared Library {}$TARGET{} ...{}".format(
colors["blue"], colors["bold_blue"], colors["blue"], colors["reset"]
)
java_library_message = "{}Creating Java Archive {}$TARGET{} ...{}".format(
colors["blue"], colors["bold_blue"], colors["blue"], colors["reset"]
)
compiled_resource_message = "{}Creating Compiled Resource {}$TARGET{} ...{}".format(
colors["blue"], colors["bold_blue"], colors["blue"], colors["reset"]
)
generated_file_message = "{}Generating {}$TARGET{} ...{}".format(
colors["blue"], colors["bold_blue"], colors["blue"], colors["reset"]
)
env.Append(CXXCOMSTR=[compile_source_message]) env.Append(CXXCOMSTR=compile_source_message)
env.Append(CCCOMSTR=[compile_source_message]) env.Append(CCCOMSTR=compile_source_message)
env.Append(SHCCCOMSTR=[compile_shared_source_message]) env.Append(SHCCCOMSTR=compile_shared_source_message)
env.Append(SHCXXCOMSTR=[compile_shared_source_message]) env.Append(SHCXXCOMSTR=compile_shared_source_message)
env.Append(ARCOMSTR=[link_library_message]) env.Append(ARCOMSTR=link_library_message)
env.Append(RANLIBCOMSTR=[ranlib_library_message]) env.Append(RANLIBCOMSTR=ranlib_library_message)
env.Append(SHLINKCOMSTR=[link_shared_library_message]) env.Append(SHLINKCOMSTR=link_shared_library_message)
env.Append(LINKCOMSTR=[link_program_message]) env.Append(LINKCOMSTR=link_program_message)
env.Append(JARCOMSTR=[java_library_message]) env.Append(JARCOMSTR=java_library_message)
env.Append(JAVACCOMSTR=[java_compile_source_message]) env.Append(JAVACCOMSTR=java_compile_source_message)
env.Append(RCCOMSTR=[compiled_resource_message]) env.Append(RCCOMSTR=compiled_resource_message)
env.Append(GENCOMSTR=[generated_file_message]) env.Append(GENCOMSTR=generated_file_message)
def disable_warnings(self): def disable_warnings(self):

View File

@ -1,10 +1,20 @@
#!/usr/bin/env python #!/usr/bin/env python
import atexit import atexit
import os
import sys import sys
import methods import methods
import time import time
# Enable ANSI escape code support on Windows 10 and later (for colored console output).
# <https://github.com/python/cpython/issues/73245>
if sys.platform == "win32":
from ctypes import windll, c_int, byref
stdout_handle = windll.kernel32.GetStdHandle(c_int(-11))
mode = c_int(0)
windll.kernel32.GetConsoleMode(c_int(stdout_handle), byref(mode))
mode = c_int(mode.value | 4)
windll.kernel32.SetConsoleMode(c_int(stdout_handle), mode)
# For the reference: # For the reference:
# - CCFLAGS are compilation flags shared between C and C++ # - CCFLAGS are compilation flags shared between C and C++
# - CFLAGS are for C-specific compilation flags # - CFLAGS are for C-specific compilation flags
@ -28,7 +38,7 @@ opts.Add(BoolVariable("verbose", "Enable verbose output for the compilation", Fa
opts.Update(env) opts.Update(env)
if not env["verbose"]: if not env["verbose"]:
methods.no_verbose(sys, env) methods.no_verbose(env)
# ThorVG # ThorVG
if env["thorvg_enabled"] and env["freetype_enabled"]: if env["thorvg_enabled"] and env["freetype_enabled"]:
@ -311,9 +321,16 @@ Default(library)
def print_elapsed_time(): def print_elapsed_time():
elapsed_time_sec = round(time.time() - time_at_start, 3) elapsed_time_sec = round(time.time() - time_at_start, 2)
time_ms = round((elapsed_time_sec % 1) * 1000) time_centiseconds = round((elapsed_time_sec % 1) * 100)
print("[Time elapsed: {}.{:03}]".format(time.strftime("%H:%M:%S", time.gmtime(elapsed_time_sec)), time_ms)) print(
"{}[Time elapsed: {}.{:02}]{}".format(
methods.ANSI.GRAY,
time.strftime("%H:%M:%S", time.gmtime(elapsed_time_sec)),
time_centiseconds,
methods.ANSI.RESET,
)
)
atexit.register(print_elapsed_time) atexit.register(print_elapsed_time)

View File

@ -1,66 +1,73 @@
import os import os
import sys import sys
from enum import Enum
def no_verbose(sys, env):
colors = {}
# Colors are disabled in non-TTY environments such as pipes. This means # Colors are disabled in non-TTY environments such as pipes. This means
# that if output is redirected to a file, it will not contain color codes # that if output is redirected to a file, it won't contain color codes.
if sys.stdout.isatty(): # Colors are always enabled on continuous integration.
colors["blue"] = "\033[0;94m" _colorize = bool(sys.stdout.isatty() or os.environ.get("CI"))
colors["bold_blue"] = "\033[1;94m"
colors["reset"] = "\033[0m"
else: class ANSI(Enum):
colors["blue"] = "" """
colors["bold_blue"] = "" Enum class for adding ansi colorcodes directly into strings.
colors["reset"] = "" Automatically converts values to strings representing their
internal value, or an empty string in a non-colorized scope.
"""
GRAY = "\x1b[0;30m"
RED = "\x1b[0;31m"
GREEN = "\x1b[0;32m"
YELLOW = "\x1b[0;33m"
BLUE = "\x1b[0;34m"
PURPLE = "\x1b[0;35m"
CYAN = "\x1b[0;36m"
WHITE = "\x1b[0;37m"
BOLD_GRAY = "\x1b[1;90m"
BOLD_RED = "\x1b[1;91m"
BOLD_GREEN = "\x1b[1;92m"
BOLD_YELLOW = "\x1b[1;93m"
BOLD_BLUE = "\x1b[1;94m"
BOLD_PURPLE = "\x1b[1;95m"
BOLD_CYAN = "\x1b[1;96m"
BOLD_WHITE = "\x1b[1;97m"
RESET = "\x1b[0m"
def __str__(self):
global _colorize
return self.value if _colorize else ""
def no_verbose(env):
colors = [ANSI.BLUE, ANSI.BOLD_BLUE, ANSI.RESET]
# There is a space before "..." to ensure that source file names can be # There is a space before "..." to ensure that source file names can be
# Ctrl + clicked in the VS Code terminal. # Ctrl + clicked in the VS Code terminal.
compile_source_message = "{}Compiling {}$SOURCE{} ...{}".format( compile_source_message = "{0}Compiling {1}$SOURCE{0} ...{2}".format(*colors)
colors["blue"], colors["bold_blue"], colors["blue"], colors["reset"] java_compile_source_message = "{0}Compiling {1}$SOURCE{0} ...{2}".format(*colors)
) compile_shared_source_message = "{0}Compiling shared {1}$SOURCE{0} ...{2}".format(*colors)
java_compile_source_message = "{}Compiling {}$SOURCE{} ...{}".format( link_program_message = "{0}Linking Program {1}$TARGET{0} ...{2}".format(*colors)
colors["blue"], colors["bold_blue"], colors["blue"], colors["reset"] link_library_message = "{0}Linking Static Library {1}$TARGET{0} ...{2}".format(*colors)
) ranlib_library_message = "{0}Ranlib Library {1}$TARGET{0} ...{2}".format(*colors)
compile_shared_source_message = "{}Compiling shared {}$SOURCE{} ...{}".format( link_shared_library_message = "{0}Linking Shared Library {1}$TARGET{0} ...{2}".format(*colors)
colors["blue"], colors["bold_blue"], colors["blue"], colors["reset"] java_library_message = "{0}Creating Java Archive {1}$TARGET{0} ...{2}".format(*colors)
) compiled_resource_message = "{0}Creating Compiled Resource {1}$TARGET{0} ...{2}".format(*colors)
link_program_message = "{}Linking Program {}$TARGET{} ...{}".format( generated_file_message = "{0}Generating {1}$TARGET{0} ...{2}".format(*colors)
colors["blue"], colors["bold_blue"], colors["blue"], colors["reset"]
)
link_library_message = "{}Linking Static Library {}$TARGET{} ...{}".format(
colors["blue"], colors["bold_blue"], colors["blue"], colors["reset"]
)
ranlib_library_message = "{}Ranlib Library {}$TARGET{} ...{}".format(
colors["blue"], colors["bold_blue"], colors["blue"], colors["reset"]
)
link_shared_library_message = "{}Linking Shared Library {}$TARGET{} ...{}".format(
colors["blue"], colors["bold_blue"], colors["blue"], colors["reset"]
)
java_library_message = "{}Creating Java Archive {}$TARGET{} ...{}".format(
colors["blue"], colors["bold_blue"], colors["blue"], colors["reset"]
)
compiled_resource_message = "{}Creating Compiled Resource {}$TARGET{} ...{}".format(
colors["blue"], colors["bold_blue"], colors["blue"], colors["reset"]
)
generated_file_message = "{}Generating {}$TARGET{} ...{}".format(
colors["blue"], colors["bold_blue"], colors["blue"], colors["reset"]
)
env.Append(CXXCOMSTR=[compile_source_message]) env.Append(CXXCOMSTR=compile_source_message)
env.Append(CCCOMSTR=[compile_source_message]) env.Append(CCCOMSTR=compile_source_message)
env.Append(SHCCCOMSTR=[compile_shared_source_message]) env.Append(SHCCCOMSTR=compile_shared_source_message)
env.Append(SHCXXCOMSTR=[compile_shared_source_message]) env.Append(SHCXXCOMSTR=compile_shared_source_message)
env.Append(ARCOMSTR=[link_library_message]) env.Append(ARCOMSTR=link_library_message)
env.Append(RANLIBCOMSTR=[ranlib_library_message]) env.Append(RANLIBCOMSTR=ranlib_library_message)
env.Append(SHLINKCOMSTR=[link_shared_library_message]) env.Append(SHLINKCOMSTR=link_shared_library_message)
env.Append(LINKCOMSTR=[link_program_message]) env.Append(LINKCOMSTR=link_program_message)
env.Append(JARCOMSTR=[java_library_message]) env.Append(JARCOMSTR=java_library_message)
env.Append(JAVACCOMSTR=[java_compile_source_message]) env.Append(JAVACCOMSTR=java_compile_source_message)
env.Append(RCCOMSTR=[compiled_resource_message]) env.Append(RCCOMSTR=compiled_resource_message)
env.Append(GENCOMSTR=[generated_file_message]) env.Append(GENCOMSTR=generated_file_message)
def disable_warnings(self): def disable_warnings(self):

View File

@ -1,6 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
import subprocess import subprocess
from methods import print_warning
Import("env") Import("env")
@ -52,7 +53,7 @@ elif env["arch"] == "x86_32":
elif env["arch"] == "x86_64": elif env["arch"] == "x86_64":
lib_arch_dir = "x86_64" lib_arch_dir = "x86_64"
else: else:
print("WARN: Architecture not suitable for embedding into APK; keeping .so at \\bin") print_warning("Architecture not suitable for embedding into APK; keeping .so at \\bin")
if lib_arch_dir != "": if lib_arch_dir != "":
if env.dev_build: if env.dev_build:

View File

@ -2,7 +2,7 @@ import os
import sys import sys
import platform import platform
import subprocess import subprocess
from methods import print_warning, print_error
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
if TYPE_CHECKING: if TYPE_CHECKING:
@ -76,7 +76,6 @@ def get_flags():
# Check if Android NDK version is installed # Check if Android NDK version is installed
# If not, install it. # If not, install it.
def install_ndk_if_needed(env: "SConsEnvironment"): def install_ndk_if_needed(env: "SConsEnvironment"):
print("Checking for Android NDK...")
sdk_root = env["ANDROID_HOME"] sdk_root = env["ANDROID_HOME"]
if not os.path.exists(get_android_ndk_root(env)): if not os.path.exists(get_android_ndk_root(env)):
extension = ".bat" if os.name == "nt" else "" extension = ".bat" if os.name == "nt" else ""
@ -87,13 +86,11 @@ def install_ndk_if_needed(env: "SConsEnvironment"):
ndk_download_args = "ndk;" + get_ndk_version() ndk_download_args = "ndk;" + get_ndk_version()
subprocess.check_call([sdkmanager, ndk_download_args]) subprocess.check_call([sdkmanager, ndk_download_args])
else: else:
print("Cannot find " + sdkmanager) print_error(
print( f'Cannot find "{sdkmanager}". Please ensure ANDROID_HOME is correct and cmdline-tools'
"Please ensure ANDROID_HOME is correct and cmdline-tools are installed, or install NDK version " f'are installed, or install NDK version "{get_ndk_version()}" manually.'
+ get_ndk_version()
+ " manually."
) )
sys.exit() sys.exit(255)
env["ANDROID_NDK_ROOT"] = get_android_ndk_root(env) env["ANDROID_NDK_ROOT"] = get_android_ndk_root(env)
@ -101,15 +98,15 @@ def configure(env: "SConsEnvironment"):
# Validate arch. # Validate arch.
supported_arches = ["x86_32", "x86_64", "arm32", "arm64"] supported_arches = ["x86_32", "x86_64", "arm32", "arm64"]
if env["arch"] not in supported_arches: if env["arch"] not in supported_arches:
print( print_error(
'Unsupported CPU architecture "%s" for Android. Supported architectures are: %s.' 'Unsupported CPU architecture "%s" for Android. Supported architectures are: %s.'
% (env["arch"], ", ".join(supported_arches)) % (env["arch"], ", ".join(supported_arches))
) )
sys.exit() sys.exit(255)
if get_min_sdk_version(env["ndk_platform"]) < get_min_target_api(): if get_min_sdk_version(env["ndk_platform"]) < get_min_target_api():
print( print_warning(
"WARNING: minimum supported Android target api is %d. Forcing target api %d." "Minimum supported Android target api is %d. Forcing target api %d."
% (get_min_target_api(), get_min_target_api()) % (get_min_target_api(), get_min_target_api())
) )
env["ndk_platform"] = "android-" + str(get_min_target_api()) env["ndk_platform"] = "android-" + str(get_min_target_api())

View File

@ -1,6 +1,6 @@
import os import os
import sys import sys
from methods import detect_darwin_sdk_path from methods import print_error, detect_darwin_sdk_path
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
@ -60,11 +60,11 @@ def configure(env: "SConsEnvironment"):
# Validate arch. # Validate arch.
supported_arches = ["x86_64", "arm64"] supported_arches = ["x86_64", "arm64"]
if env["arch"] not in supported_arches: if env["arch"] not in supported_arches:
print( print_error(
'Unsupported CPU architecture "%s" for iOS. Supported architectures are: %s.' 'Unsupported CPU architecture "%s" for iOS. Supported architectures are: %s.'
% (env["arch"], ", ".join(supported_arches)) % (env["arch"], ", ".join(supported_arches))
) )
sys.exit() sys.exit(255)
## LTO ## LTO
@ -118,7 +118,7 @@ def configure(env: "SConsEnvironment"):
if env["arch"] == "x86_64": if env["arch"] == "x86_64":
if not env["ios_simulator"]: if not env["ios_simulator"]:
print("ERROR: Building for iOS with 'arch=x86_64' requires 'ios_simulator=yes'.") print_error("Building for iOS with 'arch=x86_64' requires 'ios_simulator=yes'.")
sys.exit(255) sys.exit(255)
env["ENV"]["MACOSX_DEPLOYMENT_TARGET"] = "10.9" env["ENV"]["MACOSX_DEPLOYMENT_TARGET"] = "10.9"

View File

@ -1,7 +1,7 @@
import os import os
import platform import platform
import sys import sys
from methods import get_compiler_version, using_gcc from methods import print_warning, print_error, get_compiler_version, using_gcc
from platform_methods import detect_arch from platform_methods import detect_arch
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
@ -20,7 +20,7 @@ def can_build():
pkgconf_error = os.system("pkg-config --version > /dev/null") pkgconf_error = os.system("pkg-config --version > /dev/null")
if pkgconf_error: if pkgconf_error:
print("Error: pkg-config not found. Aborting.") print_error("pkg-config not found. Aborting.")
return False return False
return True return True
@ -75,7 +75,7 @@ def configure(env: "SConsEnvironment"):
# Validate arch. # Validate arch.
supported_arches = ["x86_32", "x86_64", "arm32", "arm64", "rv64", "ppc32", "ppc64"] supported_arches = ["x86_32", "x86_64", "arm32", "arm64", "rv64", "ppc32", "ppc64"]
if env["arch"] not in supported_arches: if env["arch"] not in supported_arches:
print( print_error(
'Unsupported CPU architecture "%s" for Linux / *BSD. Supported architectures are: %s.' 'Unsupported CPU architecture "%s" for Linux / *BSD. Supported architectures are: %s.'
% (env["arch"], ", ".join(supported_arches)) % (env["arch"], ", ".join(supported_arches))
) )
@ -128,7 +128,9 @@ def configure(env: "SConsEnvironment"):
found_wrapper = True found_wrapper = True
break break
if not found_wrapper: if not found_wrapper:
print("Couldn't locate mold installation path. Make sure it's installed in /usr or /usr/local.") print_error(
"Couldn't locate mold installation path. Make sure it's installed in /usr or /usr/local."
)
sys.exit(255) sys.exit(255)
else: else:
env.Append(LINKFLAGS=["-fuse-ld=mold"]) env.Append(LINKFLAGS=["-fuse-ld=mold"])
@ -185,7 +187,7 @@ def configure(env: "SConsEnvironment"):
if env["lto"] != "none": if env["lto"] != "none":
if env["lto"] == "thin": if env["lto"] == "thin":
if not env["use_llvm"]: if not env["use_llvm"]:
print("ThinLTO is only compatible with LLVM, use `use_llvm=yes` or `lto=full`.") print_error("ThinLTO is only compatible with LLVM, use `use_llvm=yes` or `lto=full`.")
sys.exit(255) sys.exit(255)
env.Append(CCFLAGS=["-flto=thin"]) env.Append(CCFLAGS=["-flto=thin"])
env.Append(LINKFLAGS=["-flto=thin"]) env.Append(LINKFLAGS=["-flto=thin"])
@ -209,7 +211,7 @@ def configure(env: "SConsEnvironment"):
if env["wayland"]: if env["wayland"]:
if os.system("wayland-scanner -v 2>/dev/null") != 0: if os.system("wayland-scanner -v 2>/dev/null") != 0:
print("wayland-scanner not found. Disabling Wayland support.") print_warning("wayland-scanner not found. Disabling Wayland support.")
env["wayland"] = False env["wayland"] = False
if env["touch"]: if env["touch"]:
@ -227,7 +229,7 @@ def configure(env: "SConsEnvironment"):
env["builtin_harfbuzz"], env["builtin_harfbuzz"],
] ]
if (not all(ft_linked_deps)) and any(ft_linked_deps): # All or nothing. if (not all(ft_linked_deps)) and any(ft_linked_deps): # All or nothing.
print( print_error(
"These libraries should be either all builtin, or all system provided:\n" "These libraries should be either all builtin, or all system provided:\n"
"freetype, libpng, zlib, graphite, harfbuzz.\n" "freetype, libpng, zlib, graphite, harfbuzz.\n"
"Please specify `builtin_<name>=no` for all of them, or none." "Please specify `builtin_<name>=no` for all of them, or none."
@ -318,7 +320,7 @@ def configure(env: "SConsEnvironment"):
env.ParseConfig("pkg-config fontconfig --cflags --libs") env.ParseConfig("pkg-config fontconfig --cflags --libs")
env.Append(CPPDEFINES=["FONTCONFIG_ENABLED"]) env.Append(CPPDEFINES=["FONTCONFIG_ENABLED"])
else: else:
print("Warning: fontconfig development libraries not found. Disabling the system fonts support.") print_warning("fontconfig development libraries not found. Disabling the system fonts support.")
env["fontconfig"] = False env["fontconfig"] = False
else: else:
env.Append(CPPDEFINES=["FONTCONFIG_ENABLED"]) env.Append(CPPDEFINES=["FONTCONFIG_ENABLED"])
@ -329,7 +331,7 @@ def configure(env: "SConsEnvironment"):
env.ParseConfig("pkg-config alsa --cflags --libs") env.ParseConfig("pkg-config alsa --cflags --libs")
env.Append(CPPDEFINES=["ALSA_ENABLED", "ALSAMIDI_ENABLED"]) env.Append(CPPDEFINES=["ALSA_ENABLED", "ALSAMIDI_ENABLED"])
else: else:
print("Warning: ALSA development libraries not found. Disabling the ALSA audio driver.") print_warning("ALSA development libraries not found. Disabling the ALSA audio driver.")
env["alsa"] = False env["alsa"] = False
else: else:
env.Append(CPPDEFINES=["ALSA_ENABLED", "ALSAMIDI_ENABLED"]) env.Append(CPPDEFINES=["ALSA_ENABLED", "ALSAMIDI_ENABLED"])
@ -340,7 +342,7 @@ def configure(env: "SConsEnvironment"):
env.ParseConfig("pkg-config libpulse --cflags --libs") env.ParseConfig("pkg-config libpulse --cflags --libs")
env.Append(CPPDEFINES=["PULSEAUDIO_ENABLED"]) env.Append(CPPDEFINES=["PULSEAUDIO_ENABLED"])
else: else:
print("Warning: PulseAudio development libraries not found. Disabling the PulseAudio audio driver.") print_warning("PulseAudio development libraries not found. Disabling the PulseAudio audio driver.")
env["pulseaudio"] = False env["pulseaudio"] = False
else: else:
env.Append(CPPDEFINES=["PULSEAUDIO_ENABLED", "_REENTRANT"]) env.Append(CPPDEFINES=["PULSEAUDIO_ENABLED", "_REENTRANT"])
@ -351,7 +353,7 @@ def configure(env: "SConsEnvironment"):
env.ParseConfig("pkg-config dbus-1 --cflags --libs") env.ParseConfig("pkg-config dbus-1 --cflags --libs")
env.Append(CPPDEFINES=["DBUS_ENABLED"]) env.Append(CPPDEFINES=["DBUS_ENABLED"])
else: else:
print("Warning: D-Bus development libraries not found. Disabling screensaver prevention.") print_warning("D-Bus development libraries not found. Disabling screensaver prevention.")
env["dbus"] = False env["dbus"] = False
else: else:
env.Append(CPPDEFINES=["DBUS_ENABLED"]) env.Append(CPPDEFINES=["DBUS_ENABLED"])
@ -362,7 +364,7 @@ def configure(env: "SConsEnvironment"):
env.ParseConfig("pkg-config speech-dispatcher --cflags --libs") env.ParseConfig("pkg-config speech-dispatcher --cflags --libs")
env.Append(CPPDEFINES=["SPEECHD_ENABLED"]) env.Append(CPPDEFINES=["SPEECHD_ENABLED"])
else: else:
print("Warning: speech-dispatcher development libraries not found. Disabling text to speech support.") print_warning("speech-dispatcher development libraries not found. Disabling text to speech support.")
env["speechd"] = False env["speechd"] = False
else: else:
env.Append(CPPDEFINES=["SPEECHD_ENABLED"]) env.Append(CPPDEFINES=["SPEECHD_ENABLED"])
@ -373,11 +375,11 @@ def configure(env: "SConsEnvironment"):
env.Append(CPPDEFINES=["XKB_ENABLED"]) env.Append(CPPDEFINES=["XKB_ENABLED"])
else: else:
if env["wayland"]: if env["wayland"]:
print("Error: libxkbcommon development libraries required by Wayland not found. Aborting.") print_error("libxkbcommon development libraries required by Wayland not found. Aborting.")
sys.exit(255) sys.exit(255)
else: else:
print( print_warning(
"Warning: libxkbcommon development libraries not found. Disabling dead key composition and key label support." "libxkbcommon development libraries not found. Disabling dead key composition and key label support."
) )
else: else:
env.Append(CPPDEFINES=["XKB_ENABLED"]) env.Append(CPPDEFINES=["XKB_ENABLED"])
@ -390,7 +392,7 @@ def configure(env: "SConsEnvironment"):
env.ParseConfig("pkg-config libudev --cflags --libs") env.ParseConfig("pkg-config libudev --cflags --libs")
env.Append(CPPDEFINES=["UDEV_ENABLED"]) env.Append(CPPDEFINES=["UDEV_ENABLED"])
else: else:
print("Warning: libudev development libraries not found. Disabling controller hotplugging support.") print_warning("libudev development libraries not found. Disabling controller hotplugging support.")
env["udev"] = False env["udev"] = False
else: else:
env.Append(CPPDEFINES=["UDEV_ENABLED"]) env.Append(CPPDEFINES=["UDEV_ENABLED"])
@ -416,31 +418,31 @@ def configure(env: "SConsEnvironment"):
if env["x11"]: if env["x11"]:
if not env["use_sowrap"]: if not env["use_sowrap"]:
if os.system("pkg-config --exists x11"): if os.system("pkg-config --exists x11"):
print("Error: X11 libraries not found. Aborting.") print_error("X11 libraries not found. Aborting.")
sys.exit(255) sys.exit(255)
env.ParseConfig("pkg-config x11 --cflags --libs") env.ParseConfig("pkg-config x11 --cflags --libs")
if os.system("pkg-config --exists xcursor"): if os.system("pkg-config --exists xcursor"):
print("Error: Xcursor library not found. Aborting.") print_error("Xcursor library not found. Aborting.")
sys.exit(255) sys.exit(255)
env.ParseConfig("pkg-config xcursor --cflags --libs") env.ParseConfig("pkg-config xcursor --cflags --libs")
if os.system("pkg-config --exists xinerama"): if os.system("pkg-config --exists xinerama"):
print("Error: Xinerama library not found. Aborting.") print_error("Xinerama library not found. Aborting.")
sys.exit(255) sys.exit(255)
env.ParseConfig("pkg-config xinerama --cflags --libs") env.ParseConfig("pkg-config xinerama --cflags --libs")
if os.system("pkg-config --exists xext"): if os.system("pkg-config --exists xext"):
print("Error: Xext library not found. Aborting.") print_error("Xext library not found. Aborting.")
sys.exit(255) sys.exit(255)
env.ParseConfig("pkg-config xext --cflags --libs") env.ParseConfig("pkg-config xext --cflags --libs")
if os.system("pkg-config --exists xrandr"): if os.system("pkg-config --exists xrandr"):
print("Error: XrandR library not found. Aborting.") print_error("XrandR library not found. Aborting.")
sys.exit(255) sys.exit(255)
env.ParseConfig("pkg-config xrandr --cflags --libs") env.ParseConfig("pkg-config xrandr --cflags --libs")
if os.system("pkg-config --exists xrender"): if os.system("pkg-config --exists xrender"):
print("Error: XRender library not found. Aborting.") print_error("XRender library not found. Aborting.")
sys.exit(255) sys.exit(255)
env.ParseConfig("pkg-config xrender --cflags --libs") env.ParseConfig("pkg-config xrender --cflags --libs")
if os.system("pkg-config --exists xi"): if os.system("pkg-config --exists xi"):
print("Error: Xi library not found. Aborting.") print_error("Xi library not found. Aborting.")
sys.exit(255) sys.exit(255)
env.ParseConfig("pkg-config xi --cflags --libs") env.ParseConfig("pkg-config xi --cflags --libs")
env.Append(CPPDEFINES=["X11_ENABLED"]) env.Append(CPPDEFINES=["X11_ENABLED"])
@ -448,20 +450,20 @@ def configure(env: "SConsEnvironment"):
if env["wayland"]: if env["wayland"]:
if not env["use_sowrap"]: if not env["use_sowrap"]:
if os.system("pkg-config --exists libdecor-0"): if os.system("pkg-config --exists libdecor-0"):
print("Warning: libdecor development libraries not found. Disabling client-side decorations.") print_warning("libdecor development libraries not found. Disabling client-side decorations.")
env["libdecor"] = False env["libdecor"] = False
else: else:
env.ParseConfig("pkg-config libdecor-0 --cflags --libs") env.ParseConfig("pkg-config libdecor-0 --cflags --libs")
if os.system("pkg-config --exists wayland-client"): if os.system("pkg-config --exists wayland-client"):
print("Error: Wayland client library not found. Aborting.") print_error("Wayland client library not found. Aborting.")
sys.exit(255) sys.exit(255)
env.ParseConfig("pkg-config wayland-client --cflags --libs") env.ParseConfig("pkg-config wayland-client --cflags --libs")
if os.system("pkg-config --exists wayland-cursor"): if os.system("pkg-config --exists wayland-cursor"):
print("Error: Wayland cursor library not found. Aborting.") print_error("Wayland cursor library not found. Aborting.")
sys.exit(255) sys.exit(255)
env.ParseConfig("pkg-config wayland-cursor --cflags --libs") env.ParseConfig("pkg-config wayland-cursor --cflags --libs")
if os.system("pkg-config --exists wayland-egl"): if os.system("pkg-config --exists wayland-egl"):
print("Error: Wayland EGL library not found. Aborting.") print_error("Wayland EGL library not found. Aborting.")
sys.exit(255) sys.exit(255)
env.ParseConfig("pkg-config wayland-egl --cflags --libs") env.ParseConfig("pkg-config wayland-egl --cflags --libs")

View File

@ -1,6 +1,6 @@
import os import os
import sys import sys
from methods import detect_darwin_sdk_path, get_compiler_version, is_vanilla_clang from methods import print_error, detect_darwin_sdk_path, get_compiler_version, is_vanilla_clang
from platform_methods import detect_arch, detect_mvk from platform_methods import detect_arch, detect_mvk
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
@ -64,11 +64,11 @@ def configure(env: "SConsEnvironment"):
# Validate arch. # Validate arch.
supported_arches = ["x86_64", "arm64"] supported_arches = ["x86_64", "arm64"]
if env["arch"] not in supported_arches: if env["arch"] not in supported_arches:
print( print_error(
'Unsupported CPU architecture "%s" for macOS. Supported architectures are: %s.' 'Unsupported CPU architecture "%s" for macOS. Supported architectures are: %s.'
% (env["arch"], ", ".join(supported_arches)) % (env["arch"], ", ".join(supported_arches))
) )
sys.exit() sys.exit(255)
## Build type ## Build type
@ -254,7 +254,7 @@ def configure(env: "SConsEnvironment"):
if mvk_path != "": if mvk_path != "":
env.Append(LINKFLAGS=["-L" + mvk_path]) env.Append(LINKFLAGS=["-L" + mvk_path])
else: else:
print( print_error(
"MoltenVK SDK installation directory not found, use 'vulkan_sdk_path' SCons parameter to specify SDK path." "MoltenVK SDK installation directory not found, use 'vulkan_sdk_path' SCons parameter to specify SDK path."
) )
sys.exit(255) sys.exit(255)

View File

@ -1,5 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
from methods import print_error
Import("env") Import("env")
# The HTTP server "targets". Run with "scons p=web serve", or "scons p=web run" # The HTTP server "targets". Run with "scons p=web serve", or "scons p=web run"
@ -11,7 +13,7 @@ if "serve" in COMMAND_LINE_TARGETS or "run" in COMMAND_LINE_TARGETS:
try: try:
port = int(port) port = int(port)
except Exception: except Exception:
print("GODOT_WEB_TEST_PORT must be a valid integer") print_error("GODOT_WEB_TEST_PORT must be a valid integer")
sys.exit(255) sys.exit(255)
serve(env.Dir(env.GetTemplateZipPath()).abspath, port, "run" in COMMAND_LINE_TARGETS) serve(env.Dir(env.GetTemplateZipPath()).abspath, port, "run" in COMMAND_LINE_TARGETS)
sys.exit(0) sys.exit(0)

View File

@ -10,7 +10,7 @@ from emscripten_helpers import (
create_template_zip, create_template_zip,
get_template_zip_path, get_template_zip_path,
) )
from methods import get_compiler_version from methods import print_warning, print_error, get_compiler_version
from SCons.Util import WhereIs from SCons.Util import WhereIs
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
@ -85,16 +85,16 @@ def configure(env: "SConsEnvironment"):
# Validate arch. # Validate arch.
supported_arches = ["wasm32"] supported_arches = ["wasm32"]
if env["arch"] not in supported_arches: if env["arch"] not in supported_arches:
print( print_error(
'Unsupported CPU architecture "%s" for Web. Supported architectures are: %s.' 'Unsupported CPU architecture "%s" for Web. Supported architectures are: %s.'
% (env["arch"], ", ".join(supported_arches)) % (env["arch"], ", ".join(supported_arches))
) )
sys.exit() sys.exit(255)
try: try:
env["initial_memory"] = int(env["initial_memory"]) env["initial_memory"] = int(env["initial_memory"])
except Exception: except Exception:
print("Initial memory must be a valid integer") print_error("Initial memory must be a valid integer")
sys.exit(255) sys.exit(255)
## Build type ## Build type
@ -109,7 +109,7 @@ def configure(env: "SConsEnvironment"):
env.Append(LINKFLAGS=["-s", "ASSERTIONS=1"]) env.Append(LINKFLAGS=["-s", "ASSERTIONS=1"])
if env.editor_build and env["initial_memory"] < 64: if env.editor_build and env["initial_memory"] < 64:
print('Note: Forcing "initial_memory=64" as it is required for the web editor.') print("Note: Forcing `initial_memory=64` as it is required for the web editor.")
env["initial_memory"] = 64 env["initial_memory"] = 64
env.Append(LINKFLAGS=["-s", "INITIAL_MEMORY=%sMB" % env["initial_memory"]]) env.Append(LINKFLAGS=["-s", "INITIAL_MEMORY=%sMB" % env["initial_memory"]])
@ -227,7 +227,7 @@ def configure(env: "SConsEnvironment"):
env.Append(LINKFLAGS=["-s", "PTHREAD_POOL_SIZE=8"]) env.Append(LINKFLAGS=["-s", "PTHREAD_POOL_SIZE=8"])
env.Append(LINKFLAGS=["-s", "WASM_MEM_MAX=2048MB"]) env.Append(LINKFLAGS=["-s", "WASM_MEM_MAX=2048MB"])
elif env["proxy_to_pthread"]: elif env["proxy_to_pthread"]:
print('"threads=no" support requires "proxy_to_pthread=no", disabling proxy to pthread.') print_warning('"threads=no" support requires "proxy_to_pthread=no", disabling proxy to pthread.')
env["proxy_to_pthread"] = False env["proxy_to_pthread"] = False
if env["lto"] != "none": if env["lto"] != "none":
@ -240,11 +240,11 @@ def configure(env: "SConsEnvironment"):
if env["dlink_enabled"]: if env["dlink_enabled"]:
if env["proxy_to_pthread"]: if env["proxy_to_pthread"]:
print("GDExtension support requires proxy_to_pthread=no, disabling proxy to pthread.") print_warning("GDExtension support requires proxy_to_pthread=no, disabling proxy to pthread.")
env["proxy_to_pthread"] = False env["proxy_to_pthread"] = False
if cc_semver < (3, 1, 14): if cc_semver < (3, 1, 14):
print("GDExtension support requires emscripten >= 3.1.14, detected: %s.%s.%s" % cc_semver) print_error("GDExtension support requires emscripten >= 3.1.14, detected: %s.%s.%s" % cc_semver)
sys.exit(255) sys.exit(255)
env.Append(CCFLAGS=["-s", "SIDE_MODULE=2"]) env.Append(CCFLAGS=["-s", "SIDE_MODULE=2"])

View File

@ -2,6 +2,7 @@ import methods
import os import os
import subprocess import subprocess
import sys import sys
from methods import print_warning, print_error
from platform_methods import detect_arch from platform_methods import detect_arch
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
@ -293,16 +294,14 @@ def setup_msvc_manual(env: "SConsEnvironment"):
env_arch = detect_build_env_arch() env_arch = detect_build_env_arch()
if env["arch"] != env_arch: if env["arch"] != env_arch:
print( print_error(
""" "Arch argument (%s) is not matching Native/Cross Compile Tools Prompt/Developer Console (or Visual Studio settings) that is being used to run SCons (%s).\n"
Arch argument (%s) is not matching Native/Cross Compile Tools Prompt/Developer Console (or Visual Studio settings) that is being used to run SCons (%s). "Run SCons again without arch argument (example: scons p=windows) and SCons will attempt to detect what MSVC compiler will be executed and inform you."
Run SCons again without arch argument (example: scons p=windows) and SCons will attempt to detect what MSVC compiler will be executed and inform you.
"""
% (env["arch"], env_arch) % (env["arch"], env_arch)
) )
sys.exit(200) sys.exit(255)
print("Found MSVC, arch %s" % (env_arch)) print("Using VCVARS-determined MSVC, arch %s" % (env_arch))
def setup_msvc_auto(env: "SConsEnvironment"): def setup_msvc_auto(env: "SConsEnvironment"):
@ -338,7 +337,7 @@ def setup_msvc_auto(env: "SConsEnvironment"):
env.Tool("mssdk") # we want the MS SDK env.Tool("mssdk") # we want the MS SDK
# Note: actual compiler version can be found in env['MSVC_VERSION'], e.g. "14.1" for VS2015 # Note: actual compiler version can be found in env['MSVC_VERSION'], e.g. "14.1" for VS2015
print("Found MSVC version %s, arch %s" % (env["MSVC_VERSION"], env["arch"])) print("Using SCons-detected MSVC version %s, arch %s" % (env["MSVC_VERSION"], env["arch"]))
def setup_mingw(env: "SConsEnvironment"): def setup_mingw(env: "SConsEnvironment"):
@ -346,32 +345,24 @@ def setup_mingw(env: "SConsEnvironment"):
env_arch = detect_build_env_arch() env_arch = detect_build_env_arch()
if os.getenv("MSYSTEM") == "MSYS": if os.getenv("MSYSTEM") == "MSYS":
print( print_error(
""" "Running from base MSYS2 console/environment, use target specific environment instead (e.g., mingw32, mingw64, clang32, clang64)."
Running from base MSYS2 console/environment, use target specific environment instead (e.g., mingw32, mingw64, clang32, clang64).
"""
) )
sys.exit(201) sys.exit(255)
if env_arch != "" and env["arch"] != env_arch: if env_arch != "" and env["arch"] != env_arch:
print( print_error(
""" "Arch argument (%s) is not matching MSYS2 console/environment that is being used to run SCons (%s).\n"
Arch argument (%s) is not matching MSYS2 console/environment that is being used to run SCons (%s). "Run SCons again without arch argument (example: scons p=windows) and SCons will attempt to detect what MSYS2 compiler will be executed and inform you."
Run SCons again without arch argument (example: scons p=windows) and SCons will attempt to detect what MSYS2 compiler will be executed and inform you.
"""
% (env["arch"], env_arch) % (env["arch"], env_arch)
) )
sys.exit(202) sys.exit(255)
if not try_cmd("gcc --version", env["mingw_prefix"], env["arch"]) and not try_cmd( if not try_cmd("gcc --version", env["mingw_prefix"], env["arch"]) and not try_cmd(
"clang --version", env["mingw_prefix"], env["arch"] "clang --version", env["mingw_prefix"], env["arch"]
): ):
print( print_error("No valid compilers found, use MINGW_PREFIX environment variable to set MinGW path.")
""" sys.exit(255)
No valid compilers found, use MINGW_PREFIX environment variable to set MinGW path.
"""
)
sys.exit(202)
print("Using MinGW, arch %s" % (env["arch"])) print("Using MinGW, arch %s" % (env["arch"]))
@ -454,10 +445,10 @@ def configure_msvc(env: "SConsEnvironment", vcvars_msvc_config):
if os.getenv("WindowsSdkDir") is not None: if os.getenv("WindowsSdkDir") is not None:
env.Prepend(CPPPATH=[str(os.getenv("WindowsSdkDir")) + "/Include"]) env.Prepend(CPPPATH=[str(os.getenv("WindowsSdkDir")) + "/Include"])
else: else:
print("Missing environment variable: WindowsSdkDir") print_warning("Missing environment variable: WindowsSdkDir")
if int(env["target_win_version"], 16) < 0x0601: if int(env["target_win_version"], 16) < 0x0601:
print("`target_win_version` should be 0x0601 or higher (Windows 7).") print_error("`target_win_version` should be 0x0601 or higher (Windows 7).")
sys.exit(255) sys.exit(255)
env.AppendUnique( env.AppendUnique(
@ -515,10 +506,10 @@ def configure_msvc(env: "SConsEnvironment", vcvars_msvc_config):
if env["d3d12"]: if env["d3d12"]:
# Check whether we have d3d12 dependencies installed. # Check whether we have d3d12 dependencies installed.
if not os.path.exists(env["mesa_libs"]): if not os.path.exists(env["mesa_libs"]):
print("The Direct3D 12 rendering driver requires dependencies to be installed.") print_error(
print(r"You can install them by running `python misc\scripts\install_d3d12_sdk_windows.py`.") "The Direct3D 12 rendering driver requires dependencies to be installed.\n"
print("See the documentation for more information:") "You can install them by running `python misc\\scripts\\install_d3d12_sdk_windows.py`.\n"
print( "See the documentation for more information:\n\t"
"https://docs.godotengine.org/en/latest/contributing/development/compiling/compiling_for_windows.html" "https://docs.godotengine.org/en/latest/contributing/development/compiling/compiling_for_windows.html"
) )
sys.exit(255) sys.exit(255)
@ -563,7 +554,7 @@ def configure_msvc(env: "SConsEnvironment", vcvars_msvc_config):
if os.getenv("WindowsSdkDir") is not None: if os.getenv("WindowsSdkDir") is not None:
env.Append(LIBPATH=[str(os.getenv("WindowsSdkDir")) + "/Lib"]) env.Append(LIBPATH=[str(os.getenv("WindowsSdkDir")) + "/Lib"])
else: else:
print("Missing environment variable: WindowsSdkDir") print_warning("Missing environment variable: WindowsSdkDir")
## LTO ## LTO
@ -572,7 +563,7 @@ def configure_msvc(env: "SConsEnvironment", vcvars_msvc_config):
if env["lto"] != "none": if env["lto"] != "none":
if env["lto"] == "thin": if env["lto"] == "thin":
print("ThinLTO is only compatible with LLVM, use `use_llvm=yes` or `lto=full`.") print_error("ThinLTO is only compatible with LLVM, use `use_llvm=yes` or `lto=full`.")
sys.exit(255) sys.exit(255)
env.AppendUnique(CCFLAGS=["/GL"]) env.AppendUnique(CCFLAGS=["/GL"])
env.AppendUnique(ARFLAGS=["/LTCG"]) env.AppendUnique(ARFLAGS=["/LTCG"])
@ -690,7 +681,7 @@ def configure_mingw(env: "SConsEnvironment"):
## Compile flags ## Compile flags
if int(env["target_win_version"], 16) < 0x0601: if int(env["target_win_version"], 16) < 0x0601:
print("`target_win_version` should be 0x0601 or higher (Windows 7).") print_error("`target_win_version` should be 0x0601 or higher (Windows 7).")
sys.exit(255) sys.exit(255)
if not env["use_llvm"]: if not env["use_llvm"]:
@ -744,10 +735,10 @@ def configure_mingw(env: "SConsEnvironment"):
if env["d3d12"]: if env["d3d12"]:
# Check whether we have d3d12 dependencies installed. # Check whether we have d3d12 dependencies installed.
if not os.path.exists(env["mesa_libs"]): if not os.path.exists(env["mesa_libs"]):
print("The Direct3D 12 rendering driver requires dependencies to be installed.") print_error(
print(r"You can install them by running `python misc\scripts\install_d3d12_sdk_windows.py`.") "The Direct3D 12 rendering driver requires dependencies to be installed.\n"
print("See the documentation for more information:") "You can install them by running `python misc\\scripts\\install_d3d12_sdk_windows.py`.\n"
print( "See the documentation for more information:\n\t"
"https://docs.godotengine.org/en/latest/contributing/development/compiling/compiling_for_windows.html" "https://docs.godotengine.org/en/latest/contributing/development/compiling/compiling_for_windows.html"
) )
sys.exit(255) sys.exit(255)
@ -794,11 +785,11 @@ def configure(env: "SConsEnvironment"):
# Validate arch. # Validate arch.
supported_arches = ["x86_32", "x86_64", "arm32", "arm64"] supported_arches = ["x86_32", "x86_64", "arm32", "arm64"]
if env["arch"] not in supported_arches: if env["arch"] not in supported_arches:
print( print_error(
'Unsupported CPU architecture "%s" for Windows. Supported architectures are: %s.' 'Unsupported CPU architecture "%s" for Windows. Supported architectures are: %s.'
% (env["arch"], ", ".join(supported_arches)) % (env["arch"], ", ".join(supported_arches))
) )
sys.exit() sys.exit(255)
# At this point the env has been set up with basic tools/compilers. # At this point the env has been set up with basic tools/compilers.
env.Prepend(CPPPATH=["#platform/windows"]) env.Prepend(CPPPATH=["#platform/windows"])

View File

@ -39,8 +39,7 @@ def detect_arch():
# Catches x86, i386, i486, i586, i686, etc. # Catches x86, i386, i486, i586, i686, etc.
return "x86_32" return "x86_32"
else: else:
print("Unsupported CPU architecture: " + host_machine) methods.print_warning(f'Unsupported CPU architecture: "{host_machine}". Falling back to x86_64.')
print("Falling back to x86_64.")
return "x86_64" return "x86_64"

View File

@ -3,6 +3,7 @@
import glob, os import glob, os
import math import math
from methods import print_error
from pathlib import Path from pathlib import Path
from os.path import normpath, basename from os.path import normpath, basename
@ -38,7 +39,7 @@ def find_files_in_folder(folder, sub_folder, include_list, extension, sought_exc
abs_folder = base_folder_path + folder + "/" + sub_folder abs_folder = base_folder_path + folder + "/" + sub_folder
if not os.path.isdir(abs_folder): if not os.path.isdir(abs_folder):
print("SCU: ERROR: %s not found." % abs_folder) print_error(f'SCU: "{abs_folder}" not found.')
return include_list, found_exceptions return include_list, found_exceptions
os.chdir(abs_folder) os.chdir(abs_folder)
@ -70,7 +71,7 @@ def write_output_file(file_count, include_list, start_line, end_line, output_fol
# create # create
os.mkdir(output_folder) os.mkdir(output_folder)
if not os.path.isdir(output_folder): if not os.path.isdir(output_folder):
print("SCU: ERROR: %s could not be created." % output_folder) print_error(f'SCU: "{output_folder}" could not be created.')
return return
if _verbose: if _verbose:
print("SCU: Creating folder: %s" % output_folder) print("SCU: Creating folder: %s" % output_folder)
@ -104,7 +105,7 @@ def write_output_file(file_count, include_list, start_line, end_line, output_fol
def write_exception_output_file(file_count, exception_string, output_folder, output_filename_prefix, extension): def write_exception_output_file(file_count, exception_string, output_folder, output_filename_prefix, extension):
output_folder = os.path.abspath(output_folder) output_folder = os.path.abspath(output_folder)
if not os.path.isdir(output_folder): if not os.path.isdir(output_folder):
print("SCU: ERROR: %s does not exist." % output_folder) print_error(f"SCU: {output_folder} does not exist.")
return return
file_text = exception_string + "\n" file_text = exception_string + "\n"