diff --git a/tools/android.py b/tools/android.py index 0222121e..fee4ed25 100644 --- a/tools/android.py +++ b/tools/android.py @@ -120,4 +120,9 @@ def generate(env): env.Append(CPPDEFINES=["ANDROID_ENABLED", "UNIX_ENABLED"]) + # Refer to https://github.com/godotengine/godot/blob/master/platform/android/detect.py + # LTO benefits for Android (size, performance) haven't been clearly established yet. + if env["lto"] == "auto": + env["lto"] = "none" + common_compiler_flags.generate(env) diff --git a/tools/common_compiler_flags.py b/tools/common_compiler_flags.py index 6a1fb693..e645f390 100644 --- a/tools/common_compiler_flags.py +++ b/tools/common_compiler_flags.py @@ -22,6 +22,10 @@ def exists(env): def generate(env): + assert env["lto"] in ["thin", "full", "none"], "Unrecognized lto: {}".format(env["lto"]) + if env["lto"] != "none": + print("Using LTO: " + env["lto"]) + # Require C++17 if env.get("is_msvc", False): env.Append(CXXFLAGS=["/std:c++17"]) @@ -64,6 +68,22 @@ def generate(env): env.Append(LINKFLAGS=["/OPT:REF"]) elif env["optimize"] == "debug" or env["optimize"] == "none": env.Append(CCFLAGS=["/Od"]) + + if env["lto"] == "thin": + if not env["use_llvm"]: + print("ThinLTO is only compatible with LLVM, use `use_llvm=yes` or `lto=full`.") + env.Exit(255) + + env.Append(CCFLAGS=["-flto=thin"]) + env.Append(LINKFLAGS=["-flto=thin"]) + elif env["lto"] == "full": + if env["use_llvm"]: + env.Append(CCFLAGS=["-flto"]) + env.Append(LINKFLAGS=["-flto"]) + else: + env.AppendUnique(CCFLAGS=["/GL"]) + env.AppendUnique(ARFLAGS=["/LTCG"]) + env.AppendUnique(LINKFLAGS=["/LTCG"]) else: if env["debug_symbols"]: # Adding dwarf-4 explicitly makes stacktraces work with clang builds, @@ -91,3 +111,13 @@ def generate(env): env.Append(CCFLAGS=["-Og"]) elif env["optimize"] == "none": env.Append(CCFLAGS=["-O0"]) + + if env["lto"] == "thin": + if (env["platform"] == "windows" or env["platform"] == "linux") and not env["use_llvm"]: + print("ThinLTO is only compatible with LLVM, use `use_llvm=yes` or `lto=full`.") + env.Exit(255) + env.Append(CCFLAGS=["-flto=thin"]) + env.Append(LINKFLAGS=["-flto=thin"]) + elif env["lto"] == "full": + env.Append(CCFLAGS=["-flto"]) + env.Append(LINKFLAGS=["-flto"]) diff --git a/tools/godotcpp.py b/tools/godotcpp.py index 9ceac02b..7fc97eb4 100644 --- a/tools/godotcpp.py +++ b/tools/godotcpp.py @@ -326,6 +326,14 @@ def options(opts, env): ("none", "custom", "debug", "speed", "speed_trace", "size"), ) ) + opts.Add( + EnumVariable( + "lto", + "Link-time optimization", + "none", + ("none", "auto", "thin", "full"), + ) + ) opts.Add(BoolVariable("debug_symbols", "Build with debugging symbols", True)) opts.Add(BoolVariable("dev_build", "Developer build with dev-only debugging code (DEV_ENABLED)", False)) opts.Add(BoolVariable("verbose", "Enable verbose output for the compilation", False)) diff --git a/tools/ios.py b/tools/ios.py index 9675ab1a..25c17db3 100644 --- a/tools/ios.py +++ b/tools/ios.py @@ -97,4 +97,9 @@ def generate(env): env.Append(CPPDEFINES=["IOS_ENABLED", "UNIX_ENABLED"]) + # Refer to https://github.com/godotengine/godot/blob/master/platform/ios/detect.py: + # Disable by default as it makes linking in Xcode very slow. + if env["lto"] == "auto": + env["lto"] = "none" + common_compiler_flags.generate(env) diff --git a/tools/linux.py b/tools/linux.py index 0b268788..9e85d880 100644 --- a/tools/linux.py +++ b/tools/linux.py @@ -39,4 +39,8 @@ def generate(env): env.Append(CPPDEFINES=["LINUX_ENABLED", "UNIX_ENABLED"]) + # Refer to https://github.com/godotengine/godot/blob/master/platform/linuxbsd/detect.py + if env["lto"] == "auto": + env["lto"] = "full" + common_compiler_flags.generate(env) diff --git a/tools/macos.py b/tools/macos.py index 74181505..f88e47ff 100644 --- a/tools/macos.py +++ b/tools/macos.py @@ -73,4 +73,9 @@ def generate(env): env.Append(CPPDEFINES=["MACOS_ENABLED", "UNIX_ENABLED"]) + # Refer to https://github.com/godotengine/godot/blob/master/platform/macos/detect.py + # LTO benefits for macOS (size, performance) haven't been clearly established yet. + if env["lto"] == "auto": + env["lto"] = "none" + common_compiler_flags.generate(env) diff --git a/tools/web.py b/tools/web.py index c8f07c55..c4918807 100644 --- a/tools/web.py +++ b/tools/web.py @@ -48,4 +48,8 @@ def generate(env): env.Append(CPPDEFINES=["WEB_ENABLED", "UNIX_ENABLED"]) + # Refer to https://github.com/godotengine/godot/blob/master/platform/web/detect.py + if env["lto"] == "auto": + env["lto"] = "full" + common_compiler_flags.generate(env) diff --git a/tools/windows.py b/tools/windows.py index 6fd4b038..1a55430c 100644 --- a/tools/windows.py +++ b/tools/windows.py @@ -199,4 +199,12 @@ def generate(env): env.Append(CPPDEFINES=["WINDOWS_ENABLED"]) + # Refer to https://github.com/godotengine/godot/blob/master/platform/windows/detect.py + if env["lto"] == "auto": + if env.get("is_msvc", False): + # No LTO by default for MSVC, doesn't help. + env["lto"] = "none" + else: # Release + env["lto"] = "full" + common_compiler_flags.generate(env)