2015-10-01 19:25:36 +00:00
import os
2024-05-12 23:10:22 +00:00
import re
2022-08-26 09:55:23 +00:00
import subprocess
import sys
2022-08-23 13:21:46 +00:00
from typing import TYPE_CHECKING
2024-05-21 13:14:59 +00:00
import methods
from methods import print_error , print_warning
from platform_methods import detect_arch
2022-08-23 13:21:46 +00:00
if TYPE_CHECKING :
2023-11-24 19:31:05 +00:00
from SCons . Script . SConscript import SConsEnvironment
2022-08-23 13:21:46 +00:00
2020-03-17 17:17:41 +00:00
# To match other platforms
STACK_SIZE = 8388608
2024-07-27 20:19:28 +00:00
STACK_SIZE_SANITIZERS = 30 * 1024 * 1024
2020-03-17 17:17:41 +00:00
2016-10-30 18:05:14 +00:00
2015-10-01 19:25:36 +00:00
def get_name ( ) :
2016-10-30 17:44:57 +00:00
return " Windows "
2015-10-01 19:25:36 +00:00
2016-10-30 18:05:14 +00:00
2024-07-25 17:36:22 +00:00
def try_cmd ( test , prefix , arch , check_clang = False ) :
2024-07-25 15:14:51 +00:00
archs = [ " x86_64 " , " x86_32 " , " arm64 " , " arm32 " ]
2024-05-09 09:09:28 +00:00
if arch :
2024-07-25 15:14:51 +00:00
archs = [ arch ]
for a in archs :
2022-08-26 09:55:23 +00:00
try :
out = subprocess . Popen (
2024-07-25 15:14:51 +00:00
get_mingw_bin_prefix ( prefix , a ) + test ,
2022-08-26 09:55:23 +00:00
shell = True ,
stderr = subprocess . PIPE ,
stdout = subprocess . PIPE ,
)
2024-07-25 17:36:22 +00:00
outs , errs = out . communicate ( )
2022-08-26 09:55:23 +00:00
if out . returncode == 0 :
2024-07-25 17:36:22 +00:00
if check_clang and not outs . startswith ( b " clang " ) :
return False
2024-05-09 09:09:28 +00:00
return True
2022-08-26 09:55:23 +00:00
except Exception :
pass
2024-05-09 09:09:28 +00:00
return False
2022-08-26 09:55:23 +00:00
2015-10-01 19:25:36 +00:00
def can_build ( ) :
2020-03-30 06:28:32 +00:00
if os . name == " nt " :
2017-08-18 19:45:52 +00:00
# Building natively on Windows
2018-03-02 19:51:29 +00:00
# If VCINSTALLDIR is set in the OS environ, use traditional Godot logic to set up MSVC
2020-03-30 06:28:32 +00:00
if os . getenv ( " VCINSTALLDIR " ) : # MSVC, manual setup
2016-10-30 17:44:57 +00:00
return True
2022-08-26 09:55:23 +00:00
# Otherwise, let SCons find MSVC if installed, or else MinGW.
2018-03-02 19:51:29 +00:00
# Since we're just returning True here, if there's no compiler
# installed, we'll get errors when it tries to build with the
# null compiler.
return True
2016-10-30 17:44:57 +00:00
2020-03-30 06:28:32 +00:00
if os . name == " posix " :
2017-08-18 19:45:52 +00:00
# Cross-compiling with MinGW-w64 (old MinGW32 is not supported)
2024-05-09 09:09:28 +00:00
prefix = os . getenv ( " MINGW_PREFIX " , " " )
if try_cmd ( " gcc --version " , prefix , " " ) or try_cmd ( " clang --version " , prefix , " " ) :
2016-10-30 17:44:57 +00:00
return True
return False
2016-04-02 18:26:12 +00:00
2016-10-30 18:05:14 +00:00
2022-08-26 09:55:23 +00:00
def get_mingw_bin_prefix ( prefix , arch ) :
if not prefix :
mingw_bin_prefix = " "
elif prefix [ - 1 ] != " / " :
mingw_bin_prefix = prefix + " /bin/ "
else :
mingw_bin_prefix = prefix + " bin/ "
if arch == " x86_64 " :
mingw_bin_prefix + = " x86_64-w64-mingw32- "
elif arch == " x86_32 " :
mingw_bin_prefix + = " i686-w64-mingw32- "
elif arch == " arm32 " :
mingw_bin_prefix + = " armv7-w64-mingw32- "
elif arch == " arm64 " :
mingw_bin_prefix + = " aarch64-w64-mingw32- "
return mingw_bin_prefix
def detect_build_env_arch ( ) :
msvc_target_aliases = {
" amd64 " : " x86_64 " ,
" i386 " : " x86_32 " ,
" i486 " : " x86_32 " ,
" i586 " : " x86_32 " ,
" i686 " : " x86_32 " ,
" x86 " : " x86_32 " ,
" x64 " : " x86_64 " ,
" x86_64 " : " x86_64 " ,
" arm " : " arm32 " ,
" arm64 " : " arm64 " ,
" aarch64 " : " arm64 " ,
}
if os . getenv ( " VCINSTALLDIR " ) or os . getenv ( " VCTOOLSINSTALLDIR " ) :
if os . getenv ( " Platform " ) :
msvc_arch = os . getenv ( " Platform " ) . lower ( )
if msvc_arch in msvc_target_aliases . keys ( ) :
return msvc_target_aliases [ msvc_arch ]
if os . getenv ( " VSCMD_ARG_TGT_ARCH " ) :
msvc_arch = os . getenv ( " VSCMD_ARG_TGT_ARCH " ) . lower ( )
if msvc_arch in msvc_target_aliases . keys ( ) :
return msvc_target_aliases [ msvc_arch ]
# Pre VS 2017 checks.
if os . getenv ( " VCINSTALLDIR " ) :
PATH = os . getenv ( " PATH " ) . upper ( )
VCINSTALLDIR = os . getenv ( " VCINSTALLDIR " ) . upper ( )
path_arch = {
" BIN \\ x86_ARM; " : " arm32 " ,
" BIN \\ amd64_ARM; " : " arm32 " ,
" BIN \\ x86_ARM64; " : " arm64 " ,
" BIN \\ amd64_ARM64; " : " arm64 " ,
" BIN \\ x86_amd64; " : " a86_64 " ,
" BIN \\ amd64; " : " x86_64 " ,
" BIN \\ amd64_x86; " : " x86_32 " ,
" BIN; " : " x86_32 " ,
}
for path , arch in path_arch . items ( ) :
final_path = VCINSTALLDIR + path
if final_path in PATH :
return arch
# VS 2017 and newer.
if os . getenv ( " VCTOOLSINSTALLDIR " ) :
host_path_index = os . getenv ( " PATH " ) . upper ( ) . find ( os . getenv ( " VCTOOLSINSTALLDIR " ) . upper ( ) + " BIN \\ HOST " )
if host_path_index > - 1 :
2024-06-25 11:31:46 +00:00
first_path_arch = os . getenv ( " PATH " ) [ host_path_index : ] . split ( " ; " ) [ 0 ] . rsplit ( " \\ " , 1 ) [ - 1 ] . lower ( )
if first_path_arch in msvc_target_aliases . keys ( ) :
return msvc_target_aliases [ first_path_arch ]
2022-08-26 09:55:23 +00:00
msys_target_aliases = {
" mingw32 " : " x86_32 " ,
" mingw64 " : " x86_64 " ,
" ucrt64 " : " x86_64 " ,
" clang64 " : " x86_64 " ,
" clang32 " : " x86_32 " ,
" clangarm64 " : " arm64 " ,
}
if os . getenv ( " MSYSTEM " ) :
msys_arch = os . getenv ( " MSYSTEM " ) . lower ( )
if msys_arch in msys_target_aliases . keys ( ) :
return msys_target_aliases [ msys_arch ]
return " "
2015-10-01 19:25:36 +00:00
def get_opts ( ) :
2017-09-25 04:37:17 +00:00
from SCons . Variables import BoolVariable , EnumVariable
2015-10-01 19:25:36 +00:00
2022-08-26 09:55:23 +00:00
mingw = os . getenv ( " MINGW_PREFIX " , " " )
2015-10-01 19:25:36 +00:00
2024-01-26 11:26:13 +00:00
# Direct3D 12 SDK dependencies folder.
d3d12_deps_folder = os . getenv ( " LOCALAPPDATA " )
if d3d12_deps_folder :
d3d12_deps_folder = os . path . join ( d3d12_deps_folder , " Godot " , " build_deps " )
else :
# Cross-compiling, the deps install script puts things in `bin`.
# Getting an absolute path to it is a bit hacky in Python.
try :
import inspect
caller_frame = inspect . stack ( ) [ 1 ]
caller_script_dir = os . path . dirname ( os . path . abspath ( caller_frame [ 1 ] ) )
d3d12_deps_folder = os . path . join ( caller_script_dir , " bin " , " build_deps " )
2024-05-21 13:14:59 +00:00
except Exception : # Give up.
2024-01-26 11:26:13 +00:00
d3d12_deps_folder = " "
2023-12-13 16:58:38 +00:00
2016-10-30 17:44:57 +00:00
return [
2022-08-26 09:55:23 +00:00
( " mingw_prefix " , " MinGW prefix " , mingw ) ,
2017-12-01 20:15:56 +00:00
# Targeted Windows version: 7 (and later), minimum supported version
# XP support dropped after EOL due to missing API for IPv6 and other issues
# Vista support dropped after EOL due to GH-10243
2022-08-26 09:55:23 +00:00
(
" target_win_version " ,
" Targeted Windows version, >= 0x0601 (Windows 7) " ,
" 0x0601 " ,
) ,
2021-12-16 13:00:55 +00:00
EnumVariable ( " windows_subsystem " , " Windows subsystem " , " gui " , ( " gui " , " console " ) ) ,
2022-08-26 09:55:23 +00:00
(
" msvc_version " ,
" MSVC version to use. Ignored if VCINSTALLDIR is set in shell env. " ,
None ,
) ,
2020-12-16 15:29:32 +00:00
BoolVariable ( " use_mingw " , " Use the Mingw compiler, even if MSVC is installed. " , False ) ,
2020-03-30 06:28:32 +00:00
BoolVariable ( " use_llvm " , " Use the LLVM compiler " , False ) ,
2020-11-26 21:19:23 +00:00
BoolVariable ( " use_static_cpp " , " Link MinGW/MSVC C++ runtime libraries statically " , True ) ,
2021-03-12 16:44:06 +00:00
BoolVariable ( " use_asan " , " Use address sanitizer (ASAN) " , False ) ,
2024-07-27 20:19:28 +00:00
BoolVariable ( " use_ubsan " , " Use LLVM compiler undefined behavior sanitizer (UBSAN) " , False ) ,
2022-12-05 14:56:04 +00:00
BoolVariable ( " debug_crt " , " Compile with MSVC ' s debug CRT (/MDd) " , False ) ,
2023-08-29 21:56:25 +00:00
BoolVariable ( " incremental_link " , " Use MSVC incremental linking. May increase or decrease build times. " , False ) ,
2024-04-11 22:25:39 +00:00
BoolVariable ( " silence_msvc " , " Silence MSVC ' s cl/link stdout bloat, redirecting any errors to stderr. " , True ) ,
2021-11-12 12:49:49 +00:00
( " angle_libs " , " Path to the ANGLE static libraries " , " " ) ,
2023-01-09 15:56:16 +00:00
# Direct3D 12 support.
2023-12-13 16:58:38 +00:00
(
" mesa_libs " ,
" Path to the MESA/NIR static libraries (required for D3D12) " ,
os . path . join ( d3d12_deps_folder , " mesa " ) ,
) ,
(
" agility_sdk_path " ,
" Path to the Agility SDK distribution (optional for D3D12) " ,
os . path . join ( d3d12_deps_folder , " agility_sdk " ) ,
) ,
2023-12-19 11:48:02 +00:00
BoolVariable (
" agility_sdk_multiarch " ,
" Whether the Agility SDK DLLs will be stored in arch-specific subdirectories " ,
False ,
) ,
2024-01-26 17:02:06 +00:00
BoolVariable ( " use_pix " , " Use PIX (Performance tuning and debugging for DirectX 12) runtime " , False ) ,
2023-12-13 16:58:38 +00:00
(
" pix_path " ,
" Path to the PIX runtime distribution (optional for D3D12) " ,
os . path . join ( d3d12_deps_folder , " pix " ) ,
) ,
2016-10-30 17:44:57 +00:00
]
2016-04-02 18:26:12 +00:00
2016-10-30 18:05:14 +00:00
2023-04-19 09:23:22 +00:00
def get_doc_classes ( ) :
return [
" EditorExportPlatformWindows " ,
]
def get_doc_path ( ) :
return " doc_classes "
2015-10-01 19:25:36 +00:00
def get_flags ( ) :
2022-08-26 09:55:23 +00:00
arch = detect_build_env_arch ( ) or detect_arch ( )
2024-05-19 14:41:03 +00:00
return {
" arch " : arch ,
2024-08-21 06:58:18 +00:00
" supported " : [ " d3d12 " , " mono " , " xaudio2 " ] ,
2024-05-19 14:41:03 +00:00
}
2016-04-02 18:26:12 +00:00
2016-10-30 18:05:14 +00:00
2023-11-24 19:31:05 +00:00
def build_res_file ( target , source , env : " SConsEnvironment " ) :
2022-08-26 09:55:23 +00:00
arch_aliases = {
" x86_32 " : " pe-i386 " ,
" x86_64 " : " pe-x86-64 " ,
" arm32 " : " armv7-w64-mingw32 " ,
" arm64 " : " aarch64-w64-mingw32 " ,
}
2024-05-09 09:09:28 +00:00
cmdbase = " windres --include-dir . --target= " + arch_aliases [ env [ " arch " ] ]
mingw_bin_prefix = get_mingw_bin_prefix ( env [ " mingw_prefix " ] , env [ " arch " ] )
2020-03-30 06:28:32 +00:00
2016-10-30 17:44:57 +00:00
for x in range ( len ( source ) ) :
2024-05-09 09:09:28 +00:00
ok = True
# Try prefixed executable (MinGW on Linux).
cmd = mingw_bin_prefix + cmdbase + " -i " + str ( source [ x ] ) + " -o " + str ( target [ x ] )
2016-10-30 17:44:57 +00:00
try :
2016-10-30 17:57:40 +00:00
out = subprocess . Popen ( cmd , shell = True , stderr = subprocess . PIPE ) . communicate ( )
2016-10-30 17:44:57 +00:00
if len ( out [ 1 ] ) :
2024-05-09 09:09:28 +00:00
ok = False
2023-11-17 17:31:50 +00:00
except Exception :
2024-05-09 09:09:28 +00:00
ok = False
# Try generic executable (MSYS2).
if not ok :
cmd = cmdbase + " -i " + str ( source [ x ] ) + " -o " + str ( target [ x ] )
try :
out = subprocess . Popen ( cmd , shell = True , stderr = subprocess . PIPE ) . communicate ( )
if len ( out [ 1 ] ) :
return - 1
except Exception :
return - 1
2022-08-26 09:55:23 +00:00
2016-10-30 17:44:57 +00:00
return 0
2015-10-01 19:25:36 +00:00
2016-10-30 18:05:14 +00:00
2023-11-24 19:31:05 +00:00
def setup_msvc_manual ( env : " SConsEnvironment " ) :
2022-08-26 09:55:23 +00:00
""" Running from VCVARS environment """
2021-12-16 01:38:10 +00:00
2022-08-26 09:55:23 +00:00
env_arch = detect_build_env_arch ( )
if env [ " arch " ] != env_arch :
2024-04-26 17:35:07 +00:00
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 "
" 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. "
2022-08-26 09:55:23 +00:00
% ( env [ " arch " ] , env_arch )
2020-03-30 06:28:32 +00:00
)
2024-04-26 17:35:07 +00:00
sys . exit ( 255 )
2022-08-26 09:55:23 +00:00
2024-04-26 17:35:07 +00:00
print ( " Using VCVARS-determined MSVC, arch %s " % ( env_arch ) )
2020-03-30 06:28:32 +00:00
2018-03-02 19:51:29 +00:00
2023-11-24 19:31:05 +00:00
def setup_msvc_auto ( env : " SConsEnvironment " ) :
2018-03-02 19:51:29 +00:00
""" Set up MSVC using SCons ' s auto-detection logic """
# If MSVC_VERSION is set by SCons, we know MSVC is installed.
# But we may want a different version or target arch.
2021-12-16 01:38:10 +00:00
# Valid architectures for MSVC's TARGET_ARCH:
# ['amd64', 'emt64', 'i386', 'i486', 'i586', 'i686', 'ia64', 'itanium', 'x86', 'x86_64', 'arm', 'arm64', 'aarch64']
# Our x86_64 and arm64 are the same, and we need to map the 32-bit
# architectures to other names since MSVC isn't as explicit.
# The rest we don't need to worry about because they are
# aliases or aren't supported by Godot (itanium & ia64).
msvc_arch_aliases = { " x86_32 " : " x86 " , " arm32 " : " arm " }
if env [ " arch " ] in msvc_arch_aliases . keys ( ) :
env [ " TARGET_ARCH " ] = msvc_arch_aliases [ env [ " arch " ] ]
else :
env [ " TARGET_ARCH " ] = env [ " arch " ]
2018-03-02 19:51:29 +00:00
# The env may have already been set up with default MSVC tools, so
# reset a few things so we can set it up with the tools we want.
# (Ideally we'd decide on the tool config before configuring any
# environment, and just set the env up once, but this function runs
# on an existing env so this is the simplest way.)
2020-03-30 06:28:32 +00:00
env [ " MSVC_SETUP_RUN " ] = False # Need to set this to re-run the tool
env [ " MSVS_VERSION " ] = None
env [ " MSVC_VERSION " ] = None
2021-12-16 01:38:10 +00:00
2021-08-01 08:08:20 +00:00
if " msvc_version " in env :
2020-03-30 06:28:32 +00:00
env [ " MSVC_VERSION " ] = env [ " msvc_version " ]
env . Tool ( " msvc " )
env . Tool ( " mssdk " ) # we want the MS SDK
2022-08-26 09:55:23 +00:00
2024-07-08 14:48:18 +00:00
# Re-add potentially overwritten flags.
env . AppendUnique ( CCFLAGS = env . get ( " ccflags " , " " ) . split ( ) )
env . AppendUnique ( CXXFLAGS = env . get ( " cxxflags " , " " ) . split ( ) )
env . AppendUnique ( CFLAGS = env . get ( " cflags " , " " ) . split ( ) )
env . AppendUnique ( RCFLAGS = env . get ( " rcflags " , " " ) . split ( ) )
2018-03-02 19:51:29 +00:00
# Note: actual compiler version can be found in env['MSVC_VERSION'], e.g. "14.1" for VS2015
2024-04-26 17:35:07 +00:00
print ( " Using SCons-detected MSVC version %s , arch %s " % ( env [ " MSVC_VERSION " ] , env [ " arch " ] ) )
2018-03-02 19:51:29 +00:00
2020-03-30 06:28:32 +00:00
2023-11-24 19:31:05 +00:00
def setup_mingw ( env : " SConsEnvironment " ) :
2018-03-02 19:51:29 +00:00
""" Set up env for use with mingw """
2022-08-26 09:55:23 +00:00
env_arch = detect_build_env_arch ( )
if os . getenv ( " MSYSTEM " ) == " MSYS " :
2024-04-26 17:35:07 +00:00
print_error (
" Running from base MSYS2 console/environment, use target specific environment instead (e.g., mingw32, mingw64, clang32, clang64). "
2022-08-26 09:55:23 +00:00
)
2024-04-26 17:35:07 +00:00
sys . exit ( 255 )
2022-08-26 09:55:23 +00:00
if env_arch != " " and env [ " arch " ] != env_arch :
2024-04-26 17:35:07 +00:00
print_error (
" Arch argument ( %s ) is not matching MSYS2 console/environment that is being used to run SCons ( %s ). \n "
" 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. "
2022-08-26 09:55:23 +00:00
% ( env [ " arch " ] , env_arch )
)
2024-04-26 17:35:07 +00:00
sys . exit ( 255 )
2022-08-26 09:55:23 +00:00
2024-05-09 09:09:28 +00:00
if not try_cmd ( " gcc --version " , env [ " mingw_prefix " ] , env [ " arch " ] ) and not try_cmd (
" clang --version " , env [ " mingw_prefix " ] , env [ " arch " ]
2022-08-26 09:55:23 +00:00
) :
2024-04-26 17:35:07 +00:00
print_error ( " No valid compilers found, use MINGW_PREFIX environment variable to set MinGW path. " )
sys . exit ( 255 )
2022-08-26 09:55:23 +00:00
print ( " Using MinGW, arch %s " % ( env [ " arch " ] ) )
2018-03-02 19:51:29 +00:00
2020-03-30 06:28:32 +00:00
2023-11-24 19:31:05 +00:00
def configure_msvc ( env : " SConsEnvironment " , vcvars_msvc_config ) :
2018-03-02 19:51:29 +00:00
""" Configure env to work with MSVC """
SCons: Unify tools/target build type configuration
Implements https://github.com/godotengine/godot-proposals/issues/3371.
New `target` presets
====================
The `tools` option is removed and `target` changes to use three new presets,
which match the builds users are familiar with. These targets control the
default optimization level and enable editor-specific and debugging code:
- `editor`: Replaces `tools=yes target=release_debug`.
* Defines: `TOOLS_ENABLED`, `DEBUG_ENABLED`, `-O2`/`/O2`
- `template_debug`: Replaces `tools=no target=release_debug`.
* Defines: `DEBUG_ENABLED`, `-O2`/`/O2`
- `template_release`: Replaces `tools=no target=release`.
* Defines: `-O3`/`/O2`
New `dev_build` option
======================
The previous `target=debug` is now replaced by a separate `dev_build=yes`
option, which can be used in combination with either of the three targets,
and changes the following:
- `dev_build`: Defines `DEV_ENABLED`, disables optimization (`-O0`/`/0d`),
enables generating debug symbols, does not define `NDEBUG` so `assert()`
works in thirdparty libraries, adds a `.dev` suffix to the binary name.
Note: Unlike previously, `dev_build` defaults to off so that users who
compile Godot from source get an optimized and small build by default.
Engine contributors should now set `dev_build=yes` in their build scripts or
IDE configuration manually.
Changed binary names
====================
The name of generated binaries and object files are changed too, to follow
this format:
`godot.<platform>.<target>[.dev][.double].<arch>[.<extra_suffix>][.<ext>]`
For example:
- `godot.linuxbsd.editor.dev.arm64`
- `godot.windows.template_release.double.x86_64.mono.exe`
Be sure to update your links/scripts/IDE config accordingly.
More flexible `optimize` and `debug_symbols` options
====================================================
The optimization level and whether to generate debug symbols can be further
specified with the `optimize` and `debug_symbols` options. So the default
values listed above for the various `target` and `dev_build` combinations
are indicative and can be replaced when compiling, e.g.:
`scons p=linuxbsd target=template_debug dev_build=yes optimize=debug`
will make a "debug" export template with dev-only code enabled, `-Og`
optimization level for GCC/Clang, and debug symbols. Perfect for debugging
complex crashes at runtime in an exported project.
2022-09-22 06:28:55 +00:00
## Build type
2020-03-30 06:28:32 +00:00
SCons: Unify tools/target build type configuration
Implements https://github.com/godotengine/godot-proposals/issues/3371.
New `target` presets
====================
The `tools` option is removed and `target` changes to use three new presets,
which match the builds users are familiar with. These targets control the
default optimization level and enable editor-specific and debugging code:
- `editor`: Replaces `tools=yes target=release_debug`.
* Defines: `TOOLS_ENABLED`, `DEBUG_ENABLED`, `-O2`/`/O2`
- `template_debug`: Replaces `tools=no target=release_debug`.
* Defines: `DEBUG_ENABLED`, `-O2`/`/O2`
- `template_release`: Replaces `tools=no target=release`.
* Defines: `-O3`/`/O2`
New `dev_build` option
======================
The previous `target=debug` is now replaced by a separate `dev_build=yes`
option, which can be used in combination with either of the three targets,
and changes the following:
- `dev_build`: Defines `DEV_ENABLED`, disables optimization (`-O0`/`/0d`),
enables generating debug symbols, does not define `NDEBUG` so `assert()`
works in thirdparty libraries, adds a `.dev` suffix to the binary name.
Note: Unlike previously, `dev_build` defaults to off so that users who
compile Godot from source get an optimized and small build by default.
Engine contributors should now set `dev_build=yes` in their build scripts or
IDE configuration manually.
Changed binary names
====================
The name of generated binaries and object files are changed too, to follow
this format:
`godot.<platform>.<target>[.dev][.double].<arch>[.<extra_suffix>][.<ext>]`
For example:
- `godot.linuxbsd.editor.dev.arm64`
- `godot.windows.template_release.double.x86_64.mono.exe`
Be sure to update your links/scripts/IDE config accordingly.
More flexible `optimize` and `debug_symbols` options
====================================================
The optimization level and whether to generate debug symbols can be further
specified with the `optimize` and `debug_symbols` options. So the default
values listed above for the various `target` and `dev_build` combinations
are indicative and can be replaced when compiling, e.g.:
`scons p=linuxbsd target=template_debug dev_build=yes optimize=debug`
will make a "debug" export template with dev-only code enabled, `-Og`
optimization level for GCC/Clang, and debug symbols. Perfect for debugging
complex crashes at runtime in an exported project.
2022-09-22 06:28:55 +00:00
# TODO: Re-evaluate the need for this / streamline with common config.
if env [ " target " ] == " template_release " :
env . Append ( LINKFLAGS = [ " /ENTRY:mainCRTStartup " ] )
2018-08-19 05:37:53 +00:00
2020-08-17 16:07:12 +00:00
if env [ " windows_subsystem " ] == " gui " :
env . Append ( LINKFLAGS = [ " /SUBSYSTEM:WINDOWS " ] )
else :
env . Append ( LINKFLAGS = [ " /SUBSYSTEM:CONSOLE " ] )
2020-09-14 17:56:41 +00:00
env . AppendUnique ( CPPDEFINES = [ " WINDOWS_SUBSYSTEM_CONSOLE " ] )
2020-08-17 16:07:12 +00:00
2018-03-02 19:51:29 +00:00
## Compile/link flags
2024-05-24 13:07:22 +00:00
if env [ " use_llvm " ] :
env [ " CC " ] = " clang-cl "
env [ " CXX " ] = " clang-cl "
env [ " LINK " ] = " lld-link "
env [ " AR " ] = " llvm-lib "
env . AppendUnique ( CPPDEFINES = [ " R128_STDC_ONLY " ] )
env . extra_suffix = " .llvm " + env . extra_suffix
2024-01-13 17:38:16 +00:00
env [ " MAXLINELENGTH " ] = 8192 # Windows Vista and beyond, so always applicable.
2024-05-12 23:10:22 +00:00
if env [ " silence_msvc " ] and not env . GetOption ( " clean " ) :
2024-04-11 22:25:39 +00:00
from tempfile import mkstemp
2024-05-12 23:10:22 +00:00
# Ensure we have a location to write captured output to, in case of false positives.
capture_path = methods . base_folder_path + " platform/windows/msvc_capture.log "
2024-06-19 09:20:48 +00:00
with open ( capture_path , " wt " , encoding = " utf-8 " ) :
2024-05-12 23:10:22 +00:00
pass
2024-04-11 22:25:39 +00:00
old_spawn = env [ " SPAWN " ]
2024-05-12 23:10:22 +00:00
re_redirect_stream = re . compile ( r " ^[12]?> " )
re_cl_capture = re . compile ( r " ^.+ \ .(c|cc|cpp|cxx|c[+] {2} )$ " , re . IGNORECASE )
re_link_capture = re . compile ( r ' \ s {3} \ S.+ \ s(?: " [^ " ]+.lib " | \ S+.lib) \ s.+ \ s(?: " [^ " ]+.exp " | \ S+.exp) ' )
2024-04-11 22:25:39 +00:00
def spawn_capture ( sh , escape , cmd , args , env ) :
# We only care about cl/link, process everything else as normal.
if args [ 0 ] not in [ " cl " , " link " ] :
return old_spawn ( sh , escape , cmd , args , env )
2024-01-13 17:38:16 +00:00
2024-05-12 23:10:22 +00:00
# Process as normal if the user is manually rerouting output.
for arg in args :
if re_redirect_stream . match ( arg ) :
return old_spawn ( sh , escape , cmd , args , env )
2024-04-11 22:25:39 +00:00
tmp_stdout , tmp_stdout_name = mkstemp ( )
os . close ( tmp_stdout )
args . append ( f " > { tmp_stdout_name } " )
ret = old_spawn ( sh , escape , cmd , args , env )
try :
2024-06-19 09:20:48 +00:00
with open ( tmp_stdout_name , " r " , encoding = sys . stdout . encoding , errors = " replace " ) as tmp_stdout :
2024-05-12 23:10:22 +00:00
lines = tmp_stdout . read ( ) . splitlines ( )
2024-04-11 22:25:39 +00:00
os . remove ( tmp_stdout_name )
except OSError :
pass
2024-01-13 17:38:16 +00:00
2024-05-12 23:10:22 +00:00
# Early process no lines (OSError)
if not lines :
return ret
is_cl = args [ 0 ] == " cl "
content = " "
caught = False
for line in lines :
# These conditions are far from all-encompassing, but are specialized
# for what can be reasonably expected to show up in the repository.
if not caught and ( is_cl and re_cl_capture . match ( line ) ) or ( not is_cl and re_link_capture . match ( line ) ) :
caught = True
try :
2024-06-19 09:20:48 +00:00
with open ( capture_path , " a " , encoding = sys . stdout . encoding ) as log :
2024-05-12 23:10:22 +00:00
log . write ( line + " \n " )
except OSError :
print_warning ( f ' Failed to log captured line: " { line } " . ' )
continue
content + = line + " \n "
# Content remaining assumed to be an error/warning.
if content :
sys . stderr . write ( content )
2024-04-11 22:25:39 +00:00
return ret
2024-01-13 17:38:16 +00:00
2024-04-11 22:25:39 +00:00
env [ " SPAWN " ] = spawn_capture
2024-01-13 17:38:16 +00:00
2022-12-05 14:56:04 +00:00
if env [ " debug_crt " ] :
2022-11-28 11:51:11 +00:00
# Always use dynamic runtime, static debug CRT breaks thread_local.
env . AppendUnique ( CCFLAGS = [ " /MDd " ] )
2020-11-26 21:19:23 +00:00
else :
2022-11-28 11:51:11 +00:00
if env [ " use_static_cpp " ] :
env . AppendUnique ( CCFLAGS = [ " /MT " ] )
else :
env . AppendUnique ( CCFLAGS = [ " /MD " ] )
2021-02-08 13:20:42 +00:00
2023-08-29 21:56:25 +00:00
# MSVC incremental linking is broken and may _increase_ link time (GH-77968).
if not env [ " incremental_link " ] :
env . Append ( LINKFLAGS = [ " /INCREMENTAL:NO " ] )
2023-08-10 12:04:09 +00:00
2022-08-26 09:55:23 +00:00
if env [ " arch " ] == " x86_32 " :
env [ " x86_libtheora_opt_vc " ] = True
2024-07-23 05:52:40 +00:00
env . Append ( CCFLAGS = [ " /fp:strict " ] )
2020-11-26 21:19:23 +00:00
env . AppendUnique ( CCFLAGS = [ " /Gd " , " /GR " , " /nologo " ] )
2021-11-10 15:02:02 +00:00
env . AppendUnique ( CCFLAGS = [ " /utf-8 " ] ) # Force to use Unicode encoding.
2022-07-25 19:10:20 +00:00
# Once it was thought that only debug builds would be too large,
# but this has recently stopped being true. See the mingw function
# for notes on why this shouldn't be enabled for gcc
env . AppendUnique ( CCFLAGS = [ " /bigobj " ] )
2021-11-10 15:02:02 +00:00
2022-08-26 09:55:23 +00:00
if vcvars_msvc_config : # should be automatic if SCons found it
2018-05-06 22:42:12 +00:00
if os . getenv ( " WindowsSdkDir " ) is not None :
2023-11-24 19:31:05 +00:00
env . Prepend ( CPPPATH = [ str ( os . getenv ( " WindowsSdkDir " ) ) + " /Include " ] )
2018-05-06 22:42:12 +00:00
else :
2024-04-26 17:35:07 +00:00
print_warning ( " Missing environment variable: WindowsSdkDir " )
2018-03-02 19:51:29 +00:00
2024-02-17 22:44:06 +00:00
if int ( env [ " target_win_version " ] , 16 ) < 0x0601 :
2024-04-26 17:35:07 +00:00
print_error ( " `target_win_version` should be 0x0601 or higher (Windows 7). " )
2024-02-17 22:44:06 +00:00
sys . exit ( 255 )
2020-03-30 06:28:32 +00:00
env . AppendUnique (
CPPDEFINES = [
" WINDOWS_ENABLED " ,
" WASAPI_ENABLED " ,
" WINMIDI_ENABLED " ,
" TYPED_METHOD_BIND " ,
" WIN32 " ,
" WINVER= %s " % env [ " target_win_version " ] ,
" _WIN32_WINNT= %s " % env [ " target_win_version " ] ,
]
)
env . AppendUnique ( CPPDEFINES = [ " NOMINMAX " ] ) # disable bogus min/max WinDef.h macros
2021-12-16 01:38:10 +00:00
if env [ " arch " ] == " x86_64 " :
2020-03-30 06:28:32 +00:00
env . AppendUnique ( CPPDEFINES = [ " _WIN64 " ] )
2018-03-02 19:51:29 +00:00
2024-06-14 12:06:38 +00:00
# Sanitizers
prebuilt_lib_extra_suffix = " "
if env [ " use_asan " ] :
env . extra_suffix + = " .san "
prebuilt_lib_extra_suffix = " .san "
2024-07-27 20:19:28 +00:00
env . AppendUnique ( CPPDEFINES = [ " SANITIZERS_ENABLED " ] )
2024-06-14 12:06:38 +00:00
env . Append ( CCFLAGS = [ " /fsanitize=address " ] )
env . Append ( LINKFLAGS = [ " /INFERASANLIBS " ] )
2018-03-02 19:51:29 +00:00
## Libs
2020-03-30 06:28:32 +00:00
LIBS = [
" winmm " ,
" dsound " ,
" kernel32 " ,
" ole32 " ,
" oleaut32 " ,
2021-11-04 12:33:37 +00:00
" sapi " ,
2020-03-30 06:28:32 +00:00
" user32 " ,
" gdi32 " ,
" IPHLPAPI " ,
" Shlwapi " ,
" wsock32 " ,
" Ws2_32 " ,
" shell32 " ,
" advapi32 " ,
" dinput8 " ,
" dxguid " ,
" imm32 " ,
" bcrypt " ,
2023-04-13 19:17:55 +00:00
" Crypt32 " ,
2020-03-30 06:28:32 +00:00
" Avrt " ,
" dwmapi " ,
2022-07-08 12:38:30 +00:00
" dwrite " ,
2022-10-11 10:39:41 +00:00
" wbemuuid " ,
2023-10-07 11:36:41 +00:00
" ntdll " ,
2020-03-30 06:28:32 +00:00
]
2019-06-22 16:34:26 +00:00
2023-03-27 08:49:05 +00:00
if env . debug_features :
LIBS + = [ " psapi " , " dbghelp " ]
2022-05-08 23:25:49 +00:00
if env [ " vulkan " ] :
2023-12-22 12:49:29 +00:00
env . AppendUnique ( CPPDEFINES = [ " VULKAN_ENABLED " , " RD_ENABLED " ] )
2022-05-08 23:25:49 +00:00
if not env [ " use_volk " ] :
LIBS + = [ " vulkan " ]
2023-01-09 15:56:16 +00:00
if env [ " d3d12 " ] :
2023-12-13 16:58:38 +00:00
# Check whether we have d3d12 dependencies installed.
2024-01-26 17:02:06 +00:00
if not os . path . exists ( env [ " mesa_libs " ] ) :
2024-04-26 17:35:07 +00:00
print_error (
" The Direct3D 12 rendering driver requires dependencies to be installed. \n "
" You can install them by running `python misc \\ scripts \\ install_d3d12_sdk_windows.py`. \n "
" See the documentation for more information: \n \t "
2023-12-13 16:58:38 +00:00
" https://docs.godotengine.org/en/latest/contributing/development/compiling/compiling_for_windows.html "
)
sys . exit ( 255 )
2023-12-22 12:49:29 +00:00
env . AppendUnique ( CPPDEFINES = [ " D3D12_ENABLED " , " RD_ENABLED " ] )
2024-02-17 22:44:06 +00:00
LIBS + = [ " dxgi " , " dxguid " ]
2023-01-09 15:56:16 +00:00
LIBS + = [ " version " ] # Mesa dependency.
# Needed for avoiding C1128.
if env [ " target " ] == " release_debug " :
env . Append ( CXXFLAGS = [ " /bigobj " ] )
# PIX
2024-05-21 13:14:59 +00:00
if env [ " arch " ] not in [ " x86_64 " , " arm64 " ] or env [ " pix_path " ] == " " or not os . path . exists ( env [ " pix_path " ] ) :
2024-01-26 17:02:06 +00:00
env [ " use_pix " ] = False
if env [ " use_pix " ] :
arch_subdir = " arm64 " if env [ " arch " ] == " arm64 " else " x64 "
2023-01-09 15:56:16 +00:00
env . Append ( LIBPATH = [ env [ " pix_path " ] + " /bin/ " + arch_subdir ] )
LIBS + = [ " WinPixEventRuntime " ]
env . Append ( LIBPATH = [ env [ " mesa_libs " ] + " /bin " ] )
2024-06-14 12:06:38 +00:00
LIBS + = [ " libNIR.windows. " + env [ " arch " ] + prebuilt_lib_extra_suffix ]
2023-01-09 15:56:16 +00:00
2022-05-08 23:25:49 +00:00
if env [ " opengl3 " ] :
env . AppendUnique ( CPPDEFINES = [ " GLES3_ENABLED " ] )
2021-11-12 12:49:49 +00:00
if env [ " angle_libs " ] != " " :
env . AppendUnique ( CPPDEFINES = [ " EGL_STATIC " ] )
env . Append ( LIBPATH = [ env [ " angle_libs " ] ] )
LIBS + = [
2024-06-14 12:06:38 +00:00
" libANGLE.windows. " + env [ " arch " ] + prebuilt_lib_extra_suffix ,
" libEGL.windows. " + env [ " arch " ] + prebuilt_lib_extra_suffix ,
" libGLES.windows. " + env [ " arch " ] + prebuilt_lib_extra_suffix ,
2021-11-12 12:49:49 +00:00
]
2024-07-27 14:12:27 +00:00
LIBS + = [ " dxgi " , " d3d9 " , " d3d11 " ]
2021-11-12 12:49:49 +00:00
env . Prepend ( CPPPATH = [ " #thirdparty/angle/include " ] )
2019-06-22 16:34:26 +00:00
2022-05-13 12:42:07 +00:00
if env [ " target " ] in [ " editor " , " template_debug " ] :
LIBS + = [ " psapi " , " dbghelp " ]
2024-05-24 13:07:22 +00:00
if env [ " use_llvm " ] :
LIBS + = [ f " clang_rt.builtins- { env [ ' arch ' ] } " ]
2018-03-02 19:51:29 +00:00
env . Append ( LINKFLAGS = [ p + env [ " LIBSUFFIX " ] for p in LIBS ] )
2022-08-26 09:55:23 +00:00
if vcvars_msvc_config :
2018-05-06 22:42:12 +00:00
if os . getenv ( " WindowsSdkDir " ) is not None :
2023-11-24 19:31:05 +00:00
env . Append ( LIBPATH = [ str ( os . getenv ( " WindowsSdkDir " ) ) + " /Lib " ] )
2018-05-06 22:42:12 +00:00
else :
2024-04-26 17:35:07 +00:00
print_warning ( " Missing environment variable: WindowsSdkDir " )
2017-06-30 17:21:38 +00:00
2018-03-02 19:51:29 +00:00
## LTO
2017-06-30 17:21:38 +00:00
2022-09-13 15:01:47 +00:00
if env [ " lto " ] == " auto " : # No LTO by default for MSVC, doesn't help.
env [ " lto " ] = " none "
2022-07-21 13:15:54 +00:00
if env [ " lto " ] != " none " :
if env [ " lto " ] == " thin " :
2024-05-24 13:07:22 +00:00
if not env [ " use_llvm " ] :
print ( " ThinLTO is only compatible with LLVM, use `use_llvm=yes` or `lto=full`. " )
sys . exit ( 255 )
2024-09-10 18:48:53 +00:00
env . AppendUnique ( CCFLAGS = [ " -flto=thin " ] )
2024-05-24 13:07:22 +00:00
elif env [ " use_llvm " ] :
2024-09-10 18:48:53 +00:00
env . AppendUnique ( CCFLAGS = [ " -flto " ] )
2017-06-30 17:21:38 +00:00
else :
2024-05-24 13:07:22 +00:00
env . AppendUnique ( CCFLAGS = [ " /GL " ] )
2024-09-10 18:48:53 +00:00
if env [ " progress " ] :
env . AppendUnique ( LINKFLAGS = [ " /LTCG:STATUS " ] )
else :
env . AppendUnique ( LINKFLAGS = [ " /LTCG " ] )
env . AppendUnique ( ARFLAGS = [ " /LTCG " ] )
2017-06-30 17:21:38 +00:00
2022-08-26 09:55:23 +00:00
if vcvars_msvc_config :
2023-11-24 19:31:05 +00:00
env . Prepend ( CPPPATH = [ p for p in str ( os . getenv ( " INCLUDE " ) ) . split ( " ; " ) ] )
env . Append ( LIBPATH = [ p for p in str ( os . getenv ( " LIB " ) ) . split ( " ; " ) ] )
2017-06-30 17:21:38 +00:00
2018-03-02 19:51:29 +00:00
# Incremental linking fix
2020-03-30 06:28:32 +00:00
env [ " BUILDERS " ] [ " ProgramOriginal " ] = env [ " BUILDERS " ] [ " Program " ]
env [ " BUILDERS " ] [ " Program " ] = methods . precious_program
2023-12-06 02:51:41 +00:00
env . Append ( LINKFLAGS = [ " /NATVIS:platform \\ windows \\ godot.natvis " ] )
2024-07-27 20:19:28 +00:00
if env [ " use_asan " ] :
env . AppendUnique ( LINKFLAGS = [ " /STACK: " + str ( STACK_SIZE_SANITIZERS ) ] )
else :
env . AppendUnique ( LINKFLAGS = [ " /STACK: " + str ( STACK_SIZE ) ] )
2017-06-30 17:21:38 +00:00
2020-03-17 17:17:41 +00:00
2024-08-31 09:42:21 +00:00
def get_ar_version ( env ) :
ret = {
" major " : - 1 ,
" minor " : - 1 ,
" patch " : - 1 ,
" is_llvm " : False ,
}
try :
output = (
subprocess . check_output ( [ env . subst ( env [ " AR " ] ) , " --version " ] , shell = ( os . name == " nt " ) )
. strip ( )
. decode ( " utf-8 " )
)
except ( subprocess . CalledProcessError , OSError ) :
print_warning ( " Couldn ' t check version of `ar`. " )
return ret
2024-09-09 07:39:48 +00:00
match = re . search ( r " GNU ar \ (GNU Binutils \ ) ( \ d+) \ .( \ d+)(?: \ .( \ d+))? " , output )
2024-08-31 09:42:21 +00:00
if match :
ret [ " major " ] = int ( match [ 1 ] )
ret [ " minor " ] = int ( match [ 2 ] )
if match [ 3 ] :
ret [ " patch " ] = int ( match [ 3 ] )
else :
ret [ " patch " ] = 0
return ret
match = re . search ( r " LLVM version ( \ d+) \ .( \ d+) \ .( \ d+) " , output )
if match :
ret [ " major " ] = int ( match [ 1 ] )
ret [ " minor " ] = int ( match [ 2 ] )
ret [ " patch " ] = int ( match [ 3 ] )
ret [ " is_llvm " ] = True
return ret
print_warning ( " Couldn ' t parse version of `ar`. " )
return ret
def get_is_ar_thin_supported ( env ) :
""" Check whether `ar --thin` is supported. It is only supported since Binutils 2.38 or LLVM 14. """
ar_version = get_ar_version ( env )
if ar_version [ " major " ] == - 1 :
return False
if ar_version [ " is_llvm " ] :
return ar_version [ " major " ] > = 14
if ar_version [ " major " ] == 2 :
return ar_version [ " minor " ] > = 38
print_warning ( " Unknown Binutils `ar` version. " )
return False
2024-09-19 14:04:55 +00:00
WINPATHSEP_RE = re . compile ( r " \\ ([^ \" ' \\ ]|$) " )
def tempfile_arg_esc_func ( arg ) :
from SCons . Subst import quote_spaces
arg = quote_spaces ( arg )
# GCC requires double Windows slashes, let's use UNIX separator
return WINPATHSEP_RE . sub ( r " / \ 1 " , arg )
2023-11-24 19:31:05 +00:00
def configure_mingw ( env : " SConsEnvironment " ) :
2018-03-02 19:51:29 +00:00
# Workaround for MinGW. See:
2021-08-22 01:56:25 +00:00
# https://www.scons.org/wiki/LongCmdLinesOnWin32
2018-03-02 19:51:29 +00:00
env . use_windows_spawn_fix ( )
2016-10-30 17:44:57 +00:00
2024-08-31 20:03:00 +00:00
# In case the command line to AR is too long, use a response file.
env [ " ARCOM_ORIG " ] = env [ " ARCOM " ]
env [ " ARCOM " ] = " $ { TEMPFILE( ' $ARCOM_ORIG ' , ' $ARCOMSTR ' )} "
env [ " TEMPFILESUFFIX " ] = " .rsp "
2024-09-19 14:04:55 +00:00
if os . name == " nt " :
env [ " TEMPFILEARGESCFUNC " ] = tempfile_arg_esc_func
2024-08-31 20:03:00 +00:00
2018-03-02 19:51:29 +00:00
## Build type
2016-10-30 17:44:57 +00:00
2024-05-09 09:09:28 +00:00
if not env [ " use_llvm " ] and not try_cmd ( " gcc --version " , env [ " mingw_prefix " ] , env [ " arch " ] ) :
2022-08-26 09:55:23 +00:00
env [ " use_llvm " ] = True
2024-05-09 09:09:28 +00:00
if env [ " use_llvm " ] and not try_cmd ( " clang --version " , env [ " mingw_prefix " ] , env [ " arch " ] ) :
2022-08-26 09:55:23 +00:00
env [ " use_llvm " ] = False
2024-07-25 17:36:22 +00:00
if not env [ " use_llvm " ] and try_cmd ( " gcc --version " , env [ " mingw_prefix " ] , env [ " arch " ] , True ) :
print ( " Detected GCC to be a wrapper for Clang. " )
env [ " use_llvm " ] = True
SCons: Unify tools/target build type configuration
Implements https://github.com/godotengine/godot-proposals/issues/3371.
New `target` presets
====================
The `tools` option is removed and `target` changes to use three new presets,
which match the builds users are familiar with. These targets control the
default optimization level and enable editor-specific and debugging code:
- `editor`: Replaces `tools=yes target=release_debug`.
* Defines: `TOOLS_ENABLED`, `DEBUG_ENABLED`, `-O2`/`/O2`
- `template_debug`: Replaces `tools=no target=release_debug`.
* Defines: `DEBUG_ENABLED`, `-O2`/`/O2`
- `template_release`: Replaces `tools=no target=release`.
* Defines: `-O3`/`/O2`
New `dev_build` option
======================
The previous `target=debug` is now replaced by a separate `dev_build=yes`
option, which can be used in combination with either of the three targets,
and changes the following:
- `dev_build`: Defines `DEV_ENABLED`, disables optimization (`-O0`/`/0d`),
enables generating debug symbols, does not define `NDEBUG` so `assert()`
works in thirdparty libraries, adds a `.dev` suffix to the binary name.
Note: Unlike previously, `dev_build` defaults to off so that users who
compile Godot from source get an optimized and small build by default.
Engine contributors should now set `dev_build=yes` in their build scripts or
IDE configuration manually.
Changed binary names
====================
The name of generated binaries and object files are changed too, to follow
this format:
`godot.<platform>.<target>[.dev][.double].<arch>[.<extra_suffix>][.<ext>]`
For example:
- `godot.linuxbsd.editor.dev.arm64`
- `godot.windows.template_release.double.x86_64.mono.exe`
Be sure to update your links/scripts/IDE config accordingly.
More flexible `optimize` and `debug_symbols` options
====================================================
The optimization level and whether to generate debug symbols can be further
specified with the `optimize` and `debug_symbols` options. So the default
values listed above for the various `target` and `dev_build` combinations
are indicative and can be replaced when compiling, e.g.:
`scons p=linuxbsd target=template_debug dev_build=yes optimize=debug`
will make a "debug" export template with dev-only code enabled, `-Og`
optimization level for GCC/Clang, and debug symbols. Perfect for debugging
complex crashes at runtime in an exported project.
2022-09-22 06:28:55 +00:00
# TODO: Re-evaluate the need for this / streamline with common config.
if env [ " target " ] == " template_release " :
2024-07-19 11:31:15 +00:00
if env [ " arch " ] != " arm64 " :
env . Append ( CCFLAGS = [ " -msse2 " ] )
SCons: Unify tools/target build type configuration
Implements https://github.com/godotengine/godot-proposals/issues/3371.
New `target` presets
====================
The `tools` option is removed and `target` changes to use three new presets,
which match the builds users are familiar with. These targets control the
default optimization level and enable editor-specific and debugging code:
- `editor`: Replaces `tools=yes target=release_debug`.
* Defines: `TOOLS_ENABLED`, `DEBUG_ENABLED`, `-O2`/`/O2`
- `template_debug`: Replaces `tools=no target=release_debug`.
* Defines: `DEBUG_ENABLED`, `-O2`/`/O2`
- `template_release`: Replaces `tools=no target=release`.
* Defines: `-O3`/`/O2`
New `dev_build` option
======================
The previous `target=debug` is now replaced by a separate `dev_build=yes`
option, which can be used in combination with either of the three targets,
and changes the following:
- `dev_build`: Defines `DEV_ENABLED`, disables optimization (`-O0`/`/0d`),
enables generating debug symbols, does not define `NDEBUG` so `assert()`
works in thirdparty libraries, adds a `.dev` suffix to the binary name.
Note: Unlike previously, `dev_build` defaults to off so that users who
compile Godot from source get an optimized and small build by default.
Engine contributors should now set `dev_build=yes` in their build scripts or
IDE configuration manually.
Changed binary names
====================
The name of generated binaries and object files are changed too, to follow
this format:
`godot.<platform>.<target>[.dev][.double].<arch>[.<extra_suffix>][.<ext>]`
For example:
- `godot.linuxbsd.editor.dev.arm64`
- `godot.windows.template_release.double.x86_64.mono.exe`
Be sure to update your links/scripts/IDE config accordingly.
More flexible `optimize` and `debug_symbols` options
====================================================
The optimization level and whether to generate debug symbols can be further
specified with the `optimize` and `debug_symbols` options. So the default
values listed above for the various `target` and `dev_build` combinations
are indicative and can be replaced when compiling, e.g.:
`scons p=linuxbsd target=template_debug dev_build=yes optimize=debug`
will make a "debug" export template with dev-only code enabled, `-Og`
optimization level for GCC/Clang, and debug symbols. Perfect for debugging
complex crashes at runtime in an exported project.
2022-09-22 06:28:55 +00:00
elif env . dev_build :
2021-11-18 09:38:28 +00:00
# Allow big objects. It's supposed not to have drawbacks but seems to break
# GCC LTO, so enabling for debug builds only (which are not built with LTO
# and are the only ones with too big objects).
env . Append ( CCFLAGS = [ " -Wa,-mbig-obj " ] )
2017-06-30 17:21:38 +00:00
2020-08-17 16:07:12 +00:00
if env [ " windows_subsystem " ] == " gui " :
env . Append ( LINKFLAGS = [ " -Wl,--subsystem,windows " ] )
else :
env . Append ( LINKFLAGS = [ " -Wl,--subsystem,console " ] )
2020-09-14 17:56:41 +00:00
env . AppendUnique ( CPPDEFINES = [ " WINDOWS_SUBSYSTEM_CONSOLE " ] )
2020-08-17 16:07:12 +00:00
2018-03-02 19:51:29 +00:00
## Compiler configuration
2017-06-30 17:21:38 +00:00
2020-02-07 09:41:45 +00:00
if os . name != " nt " :
2018-03-02 19:51:29 +00:00
env [ " PROGSUFFIX " ] = env [ " PROGSUFFIX " ] + " .exe " # for linux cross-compilation
2017-09-13 17:32:24 +00:00
2021-12-16 01:38:10 +00:00
if env [ " arch " ] == " x86_32 " :
2020-11-26 21:19:23 +00:00
if env [ " use_static_cpp " ] :
env . Append ( LINKFLAGS = [ " -static " ] )
env . Append ( LINKFLAGS = [ " -static-libgcc " ] )
env . Append ( LINKFLAGS = [ " -static-libstdc++ " ] )
2018-03-02 19:51:29 +00:00
else :
2020-11-26 21:19:23 +00:00
if env [ " use_static_cpp " ] :
env . Append ( LINKFLAGS = [ " -static " ] )
2022-08-26 09:55:23 +00:00
if env [ " arch " ] in [ " x86_32 " , " x86_64 " ] :
env [ " x86_libtheora_opt_gcc " ] = True
2024-07-23 05:52:40 +00:00
env . Append ( CCFLAGS = [ " -ffp-contract=off " ] )
2024-05-09 09:09:28 +00:00
mingw_bin_prefix = get_mingw_bin_prefix ( env [ " mingw_prefix " ] , env [ " arch " ] )
2020-03-30 06:28:32 +00:00
if env [ " use_llvm " ] :
2024-05-09 09:09:28 +00:00
env [ " CC " ] = mingw_bin_prefix + " clang "
env [ " CXX " ] = mingw_bin_prefix + " clang++ "
if try_cmd ( " as --version " , env [ " mingw_prefix " ] , env [ " arch " ] ) :
env [ " AS " ] = mingw_bin_prefix + " as "
2024-06-19 18:22:10 +00:00
env . Append ( ASFLAGS = [ " -c " ] )
2024-05-09 09:09:28 +00:00
if try_cmd ( " ar --version " , env [ " mingw_prefix " ] , env [ " arch " ] ) :
env [ " AR " ] = mingw_bin_prefix + " ar "
if try_cmd ( " ranlib --version " , env [ " mingw_prefix " ] , env [ " arch " ] ) :
env [ " RANLIB " ] = mingw_bin_prefix + " ranlib "
2022-08-26 09:55:23 +00:00
env . extra_suffix = " .llvm " + env . extra_suffix
2019-10-22 09:47:12 +00:00
else :
2024-05-09 09:09:28 +00:00
env [ " CC " ] = mingw_bin_prefix + " gcc "
env [ " CXX " ] = mingw_bin_prefix + " g++ "
if try_cmd ( " as --version " , env [ " mingw_prefix " ] , env [ " arch " ] ) :
env [ " AS " ] = mingw_bin_prefix + " as "
if try_cmd ( " gcc-ar --version " , env [ " mingw_prefix " ] , env [ " arch " ] ) :
env [ " AR " ] = mingw_bin_prefix + " gcc-ar "
if try_cmd ( " gcc-ranlib --version " , env [ " mingw_prefix " ] , env [ " arch " ] ) :
env [ " RANLIB " ] = mingw_bin_prefix + " gcc-ranlib "
2015-10-01 19:25:36 +00:00
2022-09-13 15:01:47 +00:00
## LTO
if env [ " lto " ] == " auto " : # Full LTO for production with MinGW.
env [ " lto " ] = " full "
2022-07-21 13:15:54 +00:00
if env [ " lto " ] != " none " :
if env [ " lto " ] == " thin " :
if not env [ " use_llvm " ] :
print ( " ThinLTO is only compatible with LLVM, use `use_llvm=yes` or `lto=full`. " )
sys . exit ( 255 )
env . Append ( CCFLAGS = [ " -flto=thin " ] )
env . Append ( LINKFLAGS = [ " -flto=thin " ] )
elif not env [ " use_llvm " ] and env . GetOption ( " num_jobs " ) > 1 :
2020-03-30 06:28:32 +00:00
env . Append ( CCFLAGS = [ " -flto " ] )
env . Append ( LINKFLAGS = [ " -flto= " + str ( env . GetOption ( " num_jobs " ) ) ] )
2019-10-22 09:47:12 +00:00
else :
2022-07-21 13:15:54 +00:00
env . Append ( CCFLAGS = [ " -flto " ] )
env . Append ( LINKFLAGS = [ " -flto " ] )
2017-09-13 20:36:15 +00:00
2024-07-27 20:19:28 +00:00
if env [ " use_asan " ] :
env . Append ( LINKFLAGS = [ " -Wl,--stack, " + str ( STACK_SIZE_SANITIZERS ) ] )
else :
env . Append ( LINKFLAGS = [ " -Wl,--stack, " + str ( STACK_SIZE ) ] )
2015-10-01 19:25:36 +00:00
2018-03-02 19:51:29 +00:00
## Compile flags
2015-10-01 19:25:36 +00:00
2024-02-17 22:44:06 +00:00
if int ( env [ " target_win_version " ] , 16 ) < 0x0601 :
2024-04-26 17:35:07 +00:00
print_error ( " `target_win_version` should be 0x0601 or higher (Windows 7). " )
2024-02-17 22:44:06 +00:00
sys . exit ( 255 )
2022-08-26 09:55:23 +00:00
if not env [ " use_llvm " ] :
env . Append ( CCFLAGS = [ " -mwindows " ] )
2020-03-30 06:28:32 +00:00
2024-07-27 20:19:28 +00:00
if env [ " use_asan " ] or env [ " use_ubsan " ] :
if not env [ " use_llvm " ] :
print ( " GCC does not support sanitizers on Windows. " )
sys . exit ( 255 )
2024-07-28 09:20:42 +00:00
if env [ " arch " ] not in [ " x86_32 " , " x86_64 " ] :
print ( " Sanitizers are only supported for x86_32 and x86_64. " )
sys . exit ( 255 )
2024-07-27 20:19:28 +00:00
env . extra_suffix + = " .san "
env . AppendUnique ( CPPDEFINES = [ " SANITIZERS_ENABLED " ] )
san_flags = [ ]
if env [ " use_asan " ] :
san_flags . append ( " -fsanitize=address " )
if env [ " use_ubsan " ] :
san_flags . append ( " -fsanitize=undefined " )
# Disable the vptr check since it gets triggered on any COM interface calls.
san_flags . append ( " -fno-sanitize=vptr " )
env . Append ( CFLAGS = san_flags )
env . Append ( CCFLAGS = san_flags )
env . Append ( LINKFLAGS = san_flags )
2024-07-25 17:43:17 +00:00
if env [ " use_llvm " ] and os . name == " nt " and methods . _colorize :
env . Append ( CCFLAGS = [ " $(-fansi-escape-codes$) " , " $(-fcolor-diagnostics$) " ] )
2024-08-31 09:42:21 +00:00
if get_is_ar_thin_supported ( env ) :
env . Append ( ARFLAGS = [ " --thin " ] )
2024-07-25 18:03:16 +00:00
2020-03-30 06:28:32 +00:00
env . Append ( CPPDEFINES = [ " WINDOWS_ENABLED " , " WASAPI_ENABLED " , " WINMIDI_ENABLED " ] )
2022-08-26 09:55:23 +00:00
env . Append (
CPPDEFINES = [
( " WINVER " , env [ " target_win_version " ] ) ,
( " _WIN32_WINNT " , env [ " target_win_version " ] ) ,
]
)
2020-03-30 06:28:32 +00:00
env . Append (
LIBS = [
" mingw32 " ,
" dsound " ,
" ole32 " ,
" d3d9 " ,
" winmm " ,
" gdi32 " ,
" iphlpapi " ,
" shlwapi " ,
" wsock32 " ,
" ws2_32 " ,
" kernel32 " ,
" oleaut32 " ,
2021-11-04 12:33:37 +00:00
" sapi " ,
2020-03-30 06:28:32 +00:00
" dinput8 " ,
" dxguid " ,
" ksuser " ,
" imm32 " ,
" bcrypt " ,
2023-04-13 19:17:55 +00:00
" crypt32 " ,
2020-03-30 06:28:32 +00:00
" avrt " ,
" uuid " ,
" dwmapi " ,
2022-07-08 12:38:30 +00:00
" dwrite " ,
2022-10-11 10:39:41 +00:00
" wbemuuid " ,
2023-10-07 11:36:41 +00:00
" ntdll " ,
2020-03-30 06:28:32 +00:00
]
)
2023-03-27 08:49:05 +00:00
if env . debug_features :
env . Append ( LIBS = [ " psapi " , " dbghelp " ] )
2022-10-25 19:20:54 +00:00
if env [ " vulkan " ] :
2023-12-22 12:49:29 +00:00
env . Append ( CPPDEFINES = [ " VULKAN_ENABLED " , " RD_ENABLED " ] )
2022-10-25 19:20:54 +00:00
if not env [ " use_volk " ] :
env . Append ( LIBS = [ " vulkan " ] )
2019-08-05 09:48:54 +00:00
2023-01-09 15:56:16 +00:00
if env [ " d3d12 " ] :
2023-12-13 16:58:38 +00:00
# Check whether we have d3d12 dependencies installed.
2024-01-26 17:02:06 +00:00
if not os . path . exists ( env [ " mesa_libs " ] ) :
2024-04-26 17:35:07 +00:00
print_error (
" The Direct3D 12 rendering driver requires dependencies to be installed. \n "
" You can install them by running `python misc \\ scripts \\ install_d3d12_sdk_windows.py`. \n "
" See the documentation for more information: \n \t "
2023-12-13 16:58:38 +00:00
" https://docs.godotengine.org/en/latest/contributing/development/compiling/compiling_for_windows.html "
)
sys . exit ( 255 )
2024-01-26 17:02:06 +00:00
env . AppendUnique ( CPPDEFINES = [ " D3D12_ENABLED " , " RD_ENABLED " ] )
2024-02-17 22:44:06 +00:00
env . Append ( LIBS = [ " dxgi " , " dxguid " ] )
2024-01-26 17:02:06 +00:00
2023-01-09 15:56:16 +00:00
# PIX
2024-05-21 13:14:59 +00:00
if env [ " arch " ] not in [ " x86_64 " , " arm64 " ] or env [ " pix_path " ] == " " or not os . path . exists ( env [ " pix_path " ] ) :
2024-01-26 17:02:06 +00:00
env [ " use_pix " ] = False
if env [ " use_pix " ] :
arch_subdir = " arm64 " if env [ " arch " ] == " arm64 " else " x64 "
2023-12-19 11:48:02 +00:00
env . Append ( LIBPATH = [ env [ " pix_path " ] + " /bin/ " + arch_subdir ] )
env . Append ( LIBS = [ " WinPixEventRuntime " ] )
2023-01-09 15:56:16 +00:00
env . Append ( LIBPATH = [ env [ " mesa_libs " ] + " /bin " ] )
env . Append ( LIBS = [ " libNIR.windows. " + env [ " arch " ] ] )
2023-12-19 11:48:02 +00:00
env . Append ( LIBS = [ " version " ] ) # Mesa dependency.
2023-01-09 15:56:16 +00:00
2022-10-25 19:20:54 +00:00
if env [ " opengl3 " ] :
env . Append ( CPPDEFINES = [ " GLES3_ENABLED " ] )
2021-11-12 12:49:49 +00:00
if env [ " angle_libs " ] != " " :
env . AppendUnique ( CPPDEFINES = [ " EGL_STATIC " ] )
env . Append ( LIBPATH = [ env [ " angle_libs " ] ] )
env . Append (
LIBS = [
" EGL.windows. " + env [ " arch " ] ,
" GLES.windows. " + env [ " arch " ] ,
" ANGLE.windows. " + env [ " arch " ] ,
]
)
2024-07-27 14:12:27 +00:00
env . Append ( LIBS = [ " dxgi " , " d3d9 " , " d3d11 " ] )
2021-11-12 12:49:49 +00:00
env . Prepend ( CPPPATH = [ " #thirdparty/angle/include " ] )
2015-10-01 19:25:36 +00:00
2020-03-30 06:28:32 +00:00
env . Append ( CPPDEFINES = [ " MINGW_ENABLED " , ( " MINGW_HAS_SECURE_API " , 1 ) ] )
2017-09-23 20:55:26 +00:00
2018-03-02 19:51:29 +00:00
# resrc
2020-03-30 06:28:32 +00:00
env . Append ( BUILDERS = { " RES " : env . Builder ( action = build_res_file , suffix = " .o " , src_suffix = " .rc " ) } )
2017-12-14 11:59:46 +00:00
2023-11-24 19:31:05 +00:00
def configure ( env : " SConsEnvironment " ) :
2021-12-16 01:38:10 +00:00
# Validate arch.
supported_arches = [ " x86_32 " , " x86_64 " , " arm32 " , " arm64 " ]
if env [ " arch " ] not in supported_arches :
2024-04-26 17:35:07 +00:00
print_error (
2021-12-16 01:38:10 +00:00
' Unsupported CPU architecture " %s " for Windows. Supported architectures are: %s . '
% ( env [ " arch " ] , " , " . join ( supported_arches ) )
)
2024-04-26 17:35:07 +00:00
sys . exit ( 255 )
2021-12-16 01:38:10 +00:00
2018-03-02 19:51:29 +00:00
# At this point the env has been set up with basic tools/compilers.
2020-03-30 06:28:32 +00:00
env . Prepend ( CPPPATH = [ " #platform/windows " ] )
2015-10-01 19:25:36 +00:00
2020-03-30 06:28:32 +00:00
if os . name == " nt " :
env [ " ENV " ] = os . environ # this makes build less repeatable, but simplifies some things
env [ " ENV " ] [ " TMP " ] = os . environ [ " TMP " ]
2018-03-02 19:51:29 +00:00
# First figure out which compiler, version, and target arch we're using
2022-08-26 09:55:23 +00:00
if os . getenv ( " VCINSTALLDIR " ) and detect_build_env_arch ( ) and not env [ " use_mingw " ] :
2018-03-02 19:51:29 +00:00
setup_msvc_manual ( env )
env . msvc = True
2022-08-26 09:55:23 +00:00
vcvars_msvc_config = True
2020-03-30 06:28:32 +00:00
elif env . get ( " MSVC_VERSION " , " " ) and not env [ " use_mingw " ] :
2018-03-02 19:51:29 +00:00
setup_msvc_auto ( env )
env . msvc = True
2022-08-26 09:55:23 +00:00
vcvars_msvc_config = False
2018-03-02 19:51:29 +00:00
else :
setup_mingw ( env )
env . msvc = False
2015-10-01 19:25:36 +00:00
2018-03-02 19:51:29 +00:00
# Now set compiler/linker flags
if env . msvc :
2022-08-26 09:55:23 +00:00
configure_msvc ( env , vcvars_msvc_config )
2015-10-01 19:25:36 +00:00
2020-03-30 06:28:32 +00:00
else : # MinGW
2018-03-02 19:51:29 +00:00
configure_mingw ( env )