1
1
#!/usr/bin/env python
2
2
#
3
- # Upstream: https://github.com/goostengine/goost (see `SConstruct` file)
4
- # Version: 1.0
3
+ # Upstream: https://github.com/goostengine/goost
4
+ # Version: 1.4 (Godot Engine 3.2.2+)
5
5
# License: MIT
6
6
#
7
- # This is a convenience/compatibility SConstruct which allows to build any
8
- # C++ module in the same way as building Godot Engine (3.2+).
7
+ # `SConstruct` which allows to build any C++ module just like Godot Engine.
9
8
#
10
- # Installation:
11
- #
12
- # 1. Copy this SConstruct to your module's source root.
9
+ # Usage:
10
+ # 1. Copy this `SConstruct` to your module's source root.
13
11
# 2. Compile the module with the same build command, for instance:
14
12
#
15
- # scons target=release_debug tools=yes bits=64
16
- #
17
- # This will clone the Godot repository directly into this module and compile it
18
- # accordingly. Alternatively, this script will compile the engine externally if
19
- # the source code can be found in the parent directory or `GODOT_SOURCE_PATH`
20
- # environment variable is defined pointing to Godot source.
13
+ # scons target=release_debug tools=yes bits=64
21
14
#
22
- # Caveats/Limitations:
15
+ # This will clone the Godot repository directly into this module and compile the
16
+ # engine with the module automatically. `GODOT_SOURCE_PATH` environment variable
17
+ # can be used instead pointing to the existing Godot source.
23
18
#
24
- # - You have to switch to the relevant git branch in Godot repository yourself
25
- # if you use parent directory or `GODOT_SOURCE_PATH`, else done automatically.
26
- # - The `custom_modules`, `extra_suffix`, `profile` build options are overridden
27
- # to build this module, so you cannot use these from the command-line.
19
+ # Run `scons --help` for other build options to configure the default behavior.
28
20
#
29
21
import os
30
22
import sys
@@ -33,62 +25,138 @@ import subprocess
33
25
34
26
import config
35
27
36
- godot_version = os .getenv ("GODOT_VERSION" , "3.2" ) # A branch, commit, tag etc.
37
- godot_url = os .getenv ("GODOT_REPO_URL" , "https://github.com/godotengine/godot" )
28
+ env = Environment ()
38
29
39
30
# Module name is determined from directory name.
40
31
module_name = os .path .basename (Dir ("." ).abspath )
32
+ print ("Configuring %s module ..." % module_name .capitalize ())
33
+
34
+ # Environment variables (can override default build options).
35
+ godot_version = os .getenv ("GODOT_VERSION" , "3.2" ) # A branch, commit, tag etc.
41
36
42
37
# Find a path to Godot source to build with this module.
38
+ godot_dir = Dir ("godot" )
43
39
godot_search_dirs = [
44
- Dir (os .getenv ("GODOT_SOURCE_PATH" )), # Try environment variable first.
45
- Dir ("../godot" ), # Try relative path.
46
- Dir ("godot" ), # Clone or use already checked out engine last.
40
+ # Try environment variable pointing to the Godot source, should be first.
41
+ Dir (os .getenv ("GODOT_SOURCE_PATH" )),
42
+ # Search for the Godot source in the parent directory.
43
+ Dir ("../godot" ),
44
+ # Use the Godot source within the module, should be last.
45
+ # If not found, the source is fetched from the remote URL.
46
+ Dir ("godot" ),
47
47
]
48
- godot_dir = Dir ("godot" )
49
-
50
48
for path in godot_search_dirs :
51
49
if not path .exists ():
52
50
continue
53
51
godot_dir = path
54
52
break
55
53
56
- def run_command (args , dir = "." ):
54
+ godot_url = os .getenv ("GODOT_REPO_URL" , "https://github.com/godotengine/godot" )
55
+
56
+ # Setup SCons command-line options.
57
+ opts = Variables ("custom.py" , ARGUMENTS )
58
+ opts .Add ("godot_version" , "Godot Engine version (branch, tags, commit hashes)" , godot_version )
59
+ opts .Add (BoolVariable ("godot_sync" , "Synchronize Godot Engine version from remote URL before building" , False ))
60
+ opts .Add (BoolVariable ("godot_modules_enabled" , "Build all Godot builtin modules" , True ))
61
+ opts .Add (BoolVariable ("parent_modules_enabled" , "Build all modules which may reside in the same parent directory" , False ))
62
+
63
+ # Generate help text.
64
+ Help ("\n \n %s top-level build options:\n " % module_name .capitalize (), append = True )
65
+
66
+ opts .Update (env )
67
+ Help (opts .GenerateHelpText (env ), append = True )
68
+
69
+ help_msg = """
70
+ {module} environment variables:
71
+
72
+ GODOT_VERSION: such as 3.2, 3.2.2-stable, master, commit hash etc.
73
+ Current: {version}
74
+ GODOT_SOURCE_PATH: a directory path to the existing Godot source code.
75
+ Current: {path}
76
+ GODOT_REPO_URL: URL from which the engine source code is fetched.
77
+ Current: {url}
78
+ """ .format (
79
+ module = module_name .capitalize (),
80
+ version = env ["godot_version" ],
81
+ path = godot_dir ,
82
+ url = godot_url ,
83
+ )
84
+ Help (help_msg , append = True )
85
+
86
+ # A method which allows us to run `git`, `scons`, and other commands.
87
+ def run (args , dir = "." ):
57
88
if sys .platform .startswith ("win32" ):
58
- subprocess .run (args , check = True , shell = True , cwd = dir )
89
+ return subprocess .run (args , check = True , shell = True , cwd = dir ). returncode
59
90
else :
60
- subprocess .run (args , check = True , cwd = dir )
91
+ return subprocess .run (args , check = True , cwd = dir ).returncode
92
+
93
+ def godot_check_if_branch (ref ):
94
+ try :
95
+ return run (["git" , "show-ref" , "--verify" , "--quiet" ,
96
+ "refs/heads/%s" % ref ], godot_dir .abspath ) == 0
97
+ except :
98
+ return False
99
+
100
+ def godot_verify_min_version ():
101
+ sys .path .insert (0 , godot_dir .abspath )
102
+ import version
103
+ compatible = (version .major , version .minor , version .patch ) >= (3 , 2 , 2 )
104
+ if not compatible :
105
+ print ("Cannot compile %s without `custom_modules` support." % module_name .capitalize ())
106
+ print ("The minimum required Godot version is 3.2.2 (current: %s)" % env ["godot_version" ])
107
+ sys .path .remove (godot_dir .abspath )
108
+ sys .modules .pop ("version" )
109
+ return compatible
61
110
62
111
if godot_dir == Dir ("godot" ):
63
112
if not godot_dir .exists ():
64
113
# Checkout Godot repository directly into this module.
65
- run_command (["git" , "clone" , godot_url , "-b" , godot_version , "--single-branch" ])
66
- else :
67
- run_command (["git" , "reset" , "--hard" , godot_version ], godot_dir .abspath )
68
-
69
- # Setup base SCons arguments (just copy all from the command line).
114
+ run (["git" , "clone" , godot_url ])
115
+ run (["git" , "checkout" , env ["godot_version" ], "--quiet" ], godot_dir .abspath )
116
+ if not godot_verify_min_version ():
117
+ Exit (255 )
118
+ elif env ["godot_sync" ]:
119
+ # Reset the engine, checkout, and update with remote.
120
+ print ("Synchronizing Godot version ..." )
121
+ run (["git" , "reset" , "--hard" , "HEAD" , "--quiet" ], godot_dir .abspath )
122
+ run (["git" , "checkout" , env ["godot_version" ], "--quiet" ], godot_dir .abspath )
123
+ if not godot_verify_min_version ():
124
+ Exit (255 )
125
+ if godot_check_if_branch (env ["godot_version" ]):
126
+ run (["git" , "pull" ], godot_dir .abspath )
127
+
128
+ # Setup base SCons arguments to the Godot build command.
129
+ # Copy all from the command line, except for options in this SConstruct.
70
130
build_args = ["scons" ]
71
131
for arg in ARGLIST :
132
+ if arg [0 ] in opts .keys ():
133
+ continue
72
134
opt = "%s=%s" % (arg [0 ], arg [1 ])
73
135
build_args .append (opt )
74
136
75
137
# Link this module as a custom module.
76
138
modules = []
77
139
modules .append (Dir (".." ).abspath )
78
140
79
- # This module may provide built-in and community modules, just like this one.
141
+ # This module may provide other nested modules, just like this one.
80
142
try :
81
143
modules_path = config .get_modules_path ()
82
144
modules .append (os .path .join (Dir ("." ).abspath , modules_path ))
83
145
except AttributeError :
84
146
pass
85
147
148
+ # We use the `custom_modules` build option to build this module,
149
+ # but allow to specify additional modules to build along this one.
150
+ if "custom_modules" in ARGUMENTS :
151
+ custom_modules = ARGUMENTS .get ("custom_modules" ).split ("," )
152
+ modules .extend (custom_modules )
153
+
86
154
build_args .append ("custom_modules=%s" % "," .join (modules ))
87
155
88
156
# We cannot link to a single module using the `custom_modules` build option,
89
157
# so this may compile other modules which reside in the same location as this
90
158
# module. To prevent this, we disable all modules there, excluding this one.
91
- if os . getenv ( "GOOST_PARENT_MODULES" , "disabled" ) == "enabled" :
159
+ if not env [ "parent_modules_enabled" ] :
92
160
DIRNAMES = 1
93
161
dirs = next (os .walk (Dir (".." ).abspath ))[DIRNAMES ]
94
162
parent_modules = []
@@ -103,19 +171,28 @@ if os.getenv("GOOST_PARENT_MODULES", "disabled") == "enabled":
103
171
build_args .append ("module_%s_enabled=no" % m )
104
172
105
173
# Optionally disable Godot's built-in modules which are non-essential in order
106
- # to test out this module in the engine, if possible.
107
- if os .getenv ("GODOT_BUILTIN_MODULES" , "enabled" ) == "disabled" :
108
- try :
109
- import modules_disabled
110
- build_args .append ("profile=%s" %
111
- os .path .join (Dir ("." ).abspath , "modules_disabled.py" ))
112
- except ImportError :
113
- pass
114
-
115
- # Append extra suffix to distinguish between other Godot builds.
116
- build_args .append ("extra_suffix=%s" % module_name )
117
-
118
- # Extend build name to the module name, preserving any custom build names.
174
+ # to test out this module in the engine. For more details, refer to Godot docs:
175
+ # https://docs.godotengine.org/en/latest/development/compiling/optimizing_for_size.html
176
+ if not env ["godot_modules_enabled" ]:
177
+ if "profile" in ARGUMENTS :
178
+ build_args .append ("profile=%s" % ARGUMENTS .get ("profile" ))
179
+ else :
180
+ try :
181
+ import modules_disabled
182
+ build_args .append ("profile=%s" %
183
+ os .path .join (Dir ("." ).abspath , "modules_disabled.py" ))
184
+ except ImportError :
185
+ pass
186
+
187
+ # Append the default `extra_suffix` to distinguish between other builds.
188
+ # Extend the suffix if `extra_suffix` is specified via the command line.
189
+ module_suffix = module_name
190
+ if "extra_suffix" in ARGUMENTS :
191
+ module_suffix += "." + ARGUMENTS .get ("extra_suffix" )
192
+ build_args .append ("extra_suffix=%s" % module_suffix )
193
+
194
+ # Set custom build name from the module name.
195
+ # Extend the build name if it's already overridden.
119
196
build_name = module_name .capitalize ()
120
197
if os .getenv ("BUILD_NAME" ):
121
198
build_name += "." + os .getenv ("BUILD_NAME" )
@@ -130,6 +207,24 @@ if scons_cache_path != None:
130
207
CacheDir (scons_cache_path )
131
208
print ("SCons cache enabled... (path: '" + scons_cache_path + "')" )
132
209
133
- # Build the engine with the module.
134
- print ("Building Godot with %s ..." % module_name .capitalize ())
135
- run_command (build_args , godot_dir .abspath )
210
+ # Some SCons-specific options may not trigger an actual build.
211
+ skip_build = False
212
+
213
+ # Pass commonly used SCons options to the Godot build.
214
+ scons_options = ["help" , "clean" ]
215
+ for opt in scons_options :
216
+ if not GetOption (opt ):
217
+ continue
218
+ skip_build |= opt in ["help" , "clean" ]
219
+ build_args .append ("--%s" % opt )
220
+
221
+ # The following can be overridden using the `SCONSFLAGS` environment variable,
222
+ # but for convenience, we just copy those options here.
223
+ if GetOption ("num_jobs" ) > 1 :
224
+ build_args .append ("--jobs=%s" % GetOption ("num_jobs" ))
225
+
226
+ if not skip_build :
227
+ print ("Building Godot with %s ..." % module_name .capitalize ())
228
+
229
+ # Run SCons to build Godot with the module, check the build configuration etc.
230
+ run (build_args , godot_dir .abspath )
0 commit comments