SCons: Disable C++ exception handling
Upon investigating the extremely slow MSVC build times in #80513, I noticed that while Godot policy is to never use exceptions, we weren't enforcing it with compiler flags, and thus still included exception handling code and stack unwinding. This is wasteful on multiple aspects: - Binary size: Around 20% binary size reduction with exceptions disabled for both MSVC and GCC binaries. - Compile time: * More than 50% build time reduction with MSVC. * 10% to 25% build time reduction with GCC + LTO. - Performance: Possibly, needs to be benchmarked. Since users may want to re-enable exceptions in their own thirdparty code or the libraries they compile with Godot, this behavior can be toggled with the `disable_exceptions` SCons option, which defaults to true.
This commit is contained in:
parent
21ab700f2d
commit
55550da68b
8 changed files with 31 additions and 24 deletions
13
SConstruct
13
SConstruct
|
@ -131,6 +131,7 @@ opts.Add(EnumVariable("lto", "Link-time optimization (production builds)", "none
|
|||
opts.Add(BoolVariable("deprecated", "Enable deprecated features", True))
|
||||
opts.Add(BoolVariable("minizip", "Enable ZIP archive support using minizip", True))
|
||||
opts.Add(BoolVariable("xaudio2", "Enable the XAudio2 audio driver", False))
|
||||
opts.Add(BoolVariable("disable_exceptions", "Force disabling exception handling code", True))
|
||||
opts.Add("custom_modules", "A list of comma-separated directory paths containing custom modules to build.", "")
|
||||
opts.Add(BoolVariable("custom_modules_recursive", "Detect custom modules recursively for each specified path.", True))
|
||||
|
||||
|
@ -480,6 +481,16 @@ if selected_platform in platform_list:
|
|||
print(" Please adjust your scripts accordingly.")
|
||||
Exit(255)
|
||||
|
||||
# Disable exception handling. Godot doesn't use exceptions anywhere, and this
|
||||
# saves around 20% of binary size and very significant build time (GH-80513).
|
||||
if env["disable_exceptions"]:
|
||||
if env.msvc:
|
||||
env.Append(CPPDEFINES=[("_HAS_EXCEPTIONS", 0)])
|
||||
else:
|
||||
env.Append(CCFLAGS=["-fno-exceptions"])
|
||||
elif env.msvc:
|
||||
env.Append(CCFLAGS=["/EHsc"])
|
||||
|
||||
# Configure compiler warnings
|
||||
if env.msvc: # MSVC
|
||||
# Truncations, narrowing conversions, signed/unsigned comparisons...
|
||||
|
@ -492,8 +503,6 @@ if selected_platform in platform_list:
|
|||
env.Append(CCFLAGS=["/W2"] + disable_nonessential_warnings)
|
||||
else: # 'no'
|
||||
env.Append(CCFLAGS=["/w"])
|
||||
# Set exception handling model to avoid warnings caused by Windows system headers.
|
||||
env.Append(CCFLAGS=["/EHsc"])
|
||||
|
||||
if env["werror"]:
|
||||
env.Append(CCFLAGS=["/WX"])
|
||||
|
|
|
@ -73,7 +73,7 @@ static bool _is_built_in_script(Script *p_script) {
|
|||
|
||||
class EditorScriptCodeCompletionCache : public ScriptCodeCompletionCache {
|
||||
struct Cache {
|
||||
uint64_t time_loaded;
|
||||
uint64_t time_loaded = 0;
|
||||
RES cache;
|
||||
};
|
||||
|
||||
|
|
|
@ -109,6 +109,15 @@ env_oidn.AppendUnique(CPPDEFINES=["NDEBUG"]) # No assert() even in debug builds
|
|||
|
||||
env_thirdparty = env_oidn.Clone()
|
||||
env_thirdparty.disable_warnings()
|
||||
|
||||
if env["disable_exceptions"]:
|
||||
# OIDN hard-requires exceptions, so we re-enable them here.
|
||||
if env.msvc and ("_HAS_EXCEPTIONS", 0) in env_thirdparty["CPPDEFINES"]:
|
||||
env_thirdparty["CPPDEFINES"].remove(("_HAS_EXCEPTIONS", 0))
|
||||
env_thirdparty.AppendUnique(CCFLAGS=["/EHsc"])
|
||||
elif not env.msvc and "-fno-exceptions" in env_thirdparty["CCFLAGS"]:
|
||||
env_thirdparty["CCFLAGS"].remove("-fno-exceptions")
|
||||
|
||||
env_thirdparty.add_source_files(thirdparty_obj, thirdparty_sources)
|
||||
env.modules_sources += thirdparty_obj
|
||||
|
||||
|
|
|
@ -329,8 +329,8 @@ Video::Video(uint64_t id, const ElementPtr element, const Document &doc, const s
|
|||
|
||||
if (Content && !Content->Tokens().empty()) {
|
||||
//this field is omitted when the embedded texture is already loaded, let's ignore if it's not found
|
||||
try {
|
||||
const Token *token = GetRequiredToken(Content, 0);
|
||||
const Token *token = GetRequiredToken(Content, 0);
|
||||
if (token) {
|
||||
const char *data = token->begin();
|
||||
if (!token->IsBinary()) {
|
||||
if (*data != '"') {
|
||||
|
@ -341,6 +341,7 @@ Video::Video(uint64_t id, const ElementPtr element, const Document &doc, const s
|
|||
// First time compute size (it could be large like 64Gb and it is good to allocate it once)
|
||||
for (uint32_t tokenIdx = 0; tokenIdx < numTokens; ++tokenIdx) {
|
||||
const Token *dataToken = GetRequiredToken(Content, tokenIdx);
|
||||
ERR_FAIL_COND(!dataToken);
|
||||
size_t tokenLength = dataToken->end() - dataToken->begin() - 2; // ignore double quotes
|
||||
const char *base64data = dataToken->begin() + 1;
|
||||
const size_t outLength = Util::ComputeDecodedSizeBase64(base64data, tokenLength);
|
||||
|
@ -383,10 +384,6 @@ Video::Video(uint64_t id, const ElementPtr element, const Document &doc, const s
|
|||
content = new uint8_t[len];
|
||||
::memcpy(content, data + 5, len);
|
||||
}
|
||||
} catch (...) {
|
||||
// //we don't need the content data for contents that has already been loaded
|
||||
// ASSIMP_LOG_VERBOSE_DEBUG_F("Caught exception in FBXMaterial (likely because content was already loaded): ",
|
||||
// runtimeError.what());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -173,11 +173,11 @@ def configure(env):
|
|||
env["RANLIB"] = compiler_path + "/llvm-ranlib"
|
||||
env["AS"] = compiler_path + "/clang"
|
||||
|
||||
# Disable exceptions and rtti on non-tools (template) builds
|
||||
# Disable rtti on non-tools (template) builds.
|
||||
if env["tools"]:
|
||||
env.Append(CXXFLAGS=["-frtti"])
|
||||
else:
|
||||
env.Append(CXXFLAGS=["-fno-rtti", "-fno-exceptions"])
|
||||
env.Append(CXXFLAGS=["-fno-rtti"])
|
||||
# Don't use dynamic_cast, necessary with no-rtti.
|
||||
env.Append(CPPDEFINES=["NO_SAFE_CAST"])
|
||||
|
||||
|
|
|
@ -34,7 +34,6 @@ def get_opts():
|
|||
),
|
||||
("IPHONESDK", "Path to the iPhone SDK", ""),
|
||||
BoolVariable("ios_simulator", "Build for iOS Simulator", False),
|
||||
BoolVariable("ios_exceptions", "Enable exceptions", False),
|
||||
("ios_triple", "Triple for ios toolchain", ""),
|
||||
]
|
||||
|
||||
|
@ -157,13 +156,6 @@ def configure(env):
|
|||
env.Append(CPPDEFINES=["NEED_LONG_INT"])
|
||||
env.Append(CPPDEFINES=["LIBYUV_DISABLE_NEON"])
|
||||
|
||||
# Disable exceptions on non-tools (template) builds
|
||||
if not env["tools"]:
|
||||
if env["ios_exceptions"]:
|
||||
env.Append(CCFLAGS=["-fexceptions"])
|
||||
else:
|
||||
env.Append(CCFLAGS=["-fno-exceptions"])
|
||||
|
||||
# Temp fix for ABS/MAX/MIN macros in iPhone SDK blocking compilation
|
||||
env.Append(CCFLAGS=["-Wno-ambiguous-macro"])
|
||||
|
||||
|
|
|
@ -88,9 +88,9 @@ def configure(env):
|
|||
print('Note: Forcing "initial_memory=64" as it is required for the web editor.')
|
||||
env["initial_memory"] = 64
|
||||
else:
|
||||
# Disable exceptions and rtti on non-tools (template) builds
|
||||
# These flags help keep the file size down.
|
||||
env.Append(CCFLAGS=["-fno-exceptions", "-fno-rtti"])
|
||||
# Disable rtti on non-tools (template) builds.
|
||||
# This helps keep the file size down.
|
||||
env.Append(CCFLAGS=["-fno-rtti"])
|
||||
# Don't use dynamic_cast, necessary with no-rtti.
|
||||
env.Append(CPPDEFINES=["NO_SAFE_CAST"])
|
||||
|
||||
|
|
|
@ -208,9 +208,9 @@ private:
|
|||
|
||||
struct Effect {
|
||||
Ref<AudioEffect> effect;
|
||||
bool enabled;
|
||||
bool enabled = false;
|
||||
#ifdef DEBUG_ENABLED
|
||||
uint64_t prof_time;
|
||||
uint64_t prof_time = 0;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue