11import os , sys , platform
22
33from SCons .Variables import EnumVariable , PathVariable , BoolVariable
4+ from SCons .Variables .BoolVariable import _text2bool
45from SCons .Tool import Tool
56from SCons .Builder import Builder
67from SCons .Errors import UserError
8+ from SCons .Script import ARGUMENTS
9+
710
811from binding_generator import scons_generate_bindings , scons_emit_files
912
@@ -14,6 +17,17 @@ def add_sources(sources, dir, extension):
1417 sources .append (dir + "/" + f )
1518
1619
20+ def get_cmdline_bool (option , default ):
21+ """We use `ARGUMENTS.get()` to check if options were manually overridden on the command line,
22+ and SCons' _text2bool helper to convert them to booleans, otherwise they're handled as strings.
23+ """
24+ cmdline_val = ARGUMENTS .get (option )
25+ if cmdline_val is not None :
26+ return _text2bool (cmdline_val )
27+ else :
28+ return default
29+
30+
1731def normalize_path (val , env ):
1832 return val if os .path .isabs (val ) else os .path .join (env .Dir ("#" ).abspath , val )
1933
@@ -230,16 +244,23 @@ def options(opts, env):
230244 )
231245 )
232246
247+ opts .Add (
248+ EnumVariable (
249+ "optimize" ,
250+ "The desired optimization flags" ,
251+ "speed_trace" ,
252+ ("none" , "custom" , "debug" , "speed" , "speed_trace" , "size" ),
253+ )
254+ )
255+ opts .Add (BoolVariable ("debug_symbols" , "Build with debugging symbols" , True ))
256+ opts .Add (BoolVariable ("dev_build" , "Developer build with dev-only debugging code (DEV_ENABLED)" , False ))
257+
233258 # Add platform options (custom tools can override platforms)
234259 for pl in sorted (set (platforms + custom_platforms )):
235260 tool = Tool (pl , toolpath = get_platform_tools_paths (env ))
236261 if hasattr (tool , "options" ):
237262 tool .options (opts )
238263
239- # Targets flags tool (optimizations, debug symbols)
240- target_tool = Tool ("targets" , toolpath = ["tools" ])
241- target_tool .options (opts )
242-
243264
244265def generate (env ):
245266 # Default num_jobs to local cpu count if not user specified.
@@ -286,43 +307,56 @@ def generate(env):
286307
287308 print ("Building for architecture " + env ["arch" ] + " on platform " + env ["platform" ])
288309
289- if env .get ("use_hot_reload" ) is None :
290- env ["use_hot_reload" ] = env ["target" ] != "template_release"
291- if env ["use_hot_reload" ]:
292- env .Append (CPPDEFINES = ["HOT_RELOAD_ENABLED" ])
310+ # These defaults may be needed by platform tools
311+ env .use_hot_reload = env .get ("use_hot_reload" , env ["target" ] != "template_release" )
312+ env .editor_build = env ["target" ] == "editor"
313+ env .dev_build = env ["dev_build" ]
314+ env .debug_features = env ["target" ] in ["editor" , "template_debug" ]
315+
316+ if env .dev_build :
317+ opt_level = "none"
318+ elif env .debug_features :
319+ opt_level = "speed_trace"
320+ else : # Release
321+ opt_level = "speed"
322+
323+ env ["optimize" ] = ARGUMENTS .get ("optimize" , opt_level )
324+ env ["debug_symbols" ] = get_cmdline_bool ("debug_symbols" , env .dev_build )
293325
294326 tool = Tool (env ["platform" ], toolpath = get_platform_tools_paths (env ))
295327
296328 if tool is None or not tool .exists (env ):
297329 raise ValueError ("Required toolchain not found for platform " + env ["platform" ])
298330
299331 tool .generate (env )
300- target_tool = Tool ("targets" , toolpath = ["tools" ])
301- target_tool .generate (env )
302-
303- # Disable exception handling. Godot doesn't use exceptions anywhere, and this
304- # saves around 20% of binary size and very significant build time.
305- if env ["disable_exceptions" ]:
306- if env .get ("is_msvc" , False ):
307- env .Append (CPPDEFINES = [("_HAS_EXCEPTIONS" , 0 )])
308- else :
309- env .Append (CXXFLAGS = ["-fno-exceptions" ])
310- elif env .get ("is_msvc" , False ):
311- env .Append (CXXFLAGS = ["/EHsc" ])
312-
313- if not env .get ("is_msvc" , False ):
314- if env ["symbols_visibility" ] == "visible" :
315- env .Append (CCFLAGS = ["-fvisibility=default" ])
316- env .Append (LINKFLAGS = ["-fvisibility=default" ])
317- elif env ["symbols_visibility" ] == "hidden" :
318- env .Append (CCFLAGS = ["-fvisibility=hidden" ])
319- env .Append (LINKFLAGS = ["-fvisibility=hidden" ])
320-
321- # Require C++17
322- if env .get ("is_msvc" , False ):
323- env .Append (CXXFLAGS = ["/std:c++17" ])
332+
333+ if env .use_hot_reload :
334+ env .Append (CPPDEFINES = ["HOT_RELOAD_ENABLED" ])
335+
336+ if env .editor_build :
337+ env .Append (CPPDEFINES = ["TOOLS_ENABLED" ])
338+
339+ # Configuration of build targets:
340+ # - Editor or template
341+ # - Debug features (DEBUG_ENABLED code)
342+ # - Dev only code (DEV_ENABLED code)
343+ # - Optimization level
344+ # - Debug symbols for crash traces / debuggers
345+ # Keep this configuration in sync with SConstruct in upstream Godot.
346+ if env .debug_features :
347+ # DEBUG_ENABLED enables debugging *features* and debug-only code, which is intended
348+ # to give *users* extra debugging information for their game development.
349+ env .Append (CPPDEFINES = ["DEBUG_ENABLED" ])
350+ # In upstream Godot this is added in typedefs.h when DEBUG_ENABLED is set.
351+ env .Append (CPPDEFINES = ["DEBUG_METHODS_ENABLED" ])
352+
353+ if env .dev_build :
354+ # DEV_ENABLED enables *engine developer* code which should only be compiled for those
355+ # working on the engine itself.
356+ env .Append (CPPDEFINES = ["DEV_ENABLED" ])
324357 else :
325- env .Append (CXXFLAGS = ["-std=c++17" ])
358+ # Disable assert() for production targets (only used in thirdparty code).
359+ env .Append (CPPDEFINES = ["NDEBUG" ])
326360
327361 if env ["precision" ] == "double" :
328362 env .Append (CPPDEFINES = ["REAL_T_IS_DOUBLE" ])
0 commit comments