Skip to content

Commit 4afbd84

Browse files
committed
SCons: Update SConstruct from Goost to version 1.4
1 parent 3cef284 commit 4afbd84

File tree

2 files changed

+148
-52
lines changed

2 files changed

+148
-52
lines changed

.gitignore

+2-1
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,11 @@
3434
export.cfg
3535
export_presets.cfg
3636

37-
# For projects that use SCons for building: http://http://www.scons.org/
37+
# SCons
3838
.sconf_temp
3939
.sconsign*.dblite
4040
.scons_cache
41+
custom.py
4142

4243
# Godot repository
4344
/godot

SConstruct

+146-51
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,22 @@
11
#!/usr/bin/env python
22
#
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+)
55
# License: MIT
66
#
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.
98
#
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.
1311
# 2. Compile the module with the same build command, for instance:
1412
#
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
2114
#
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.
2318
#
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.
2820
#
2921
import os
3022
import sys
@@ -33,62 +25,138 @@ import subprocess
3325

3426
import config
3527

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()
3829

3930
# Module name is determined from directory name.
4031
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.
4136

4237
# Find a path to Godot source to build with this module.
38+
godot_dir = Dir("godot")
4339
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"),
4747
]
48-
godot_dir = Dir("godot")
49-
5048
for path in godot_search_dirs:
5149
if not path.exists():
5250
continue
5351
godot_dir = path
5452
break
5553

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="."):
5788
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
5990
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
61110

62111
if godot_dir == Dir("godot"):
63112
if not godot_dir.exists():
64113
# 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.
70130
build_args = ["scons"]
71131
for arg in ARGLIST:
132+
if arg[0] in opts.keys():
133+
continue
72134
opt = "%s=%s" % (arg[0], arg[1])
73135
build_args.append(opt)
74136

75137
# Link this module as a custom module.
76138
modules = []
77139
modules.append(Dir("..").abspath)
78140

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.
80142
try:
81143
modules_path = config.get_modules_path()
82144
modules.append(os.path.join(Dir(".").abspath, modules_path))
83145
except AttributeError:
84146
pass
85147

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+
86154
build_args.append("custom_modules=%s" % ",".join(modules))
87155

88156
# We cannot link to a single module using the `custom_modules` build option,
89157
# so this may compile other modules which reside in the same location as this
90158
# 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"]:
92160
DIRNAMES = 1
93161
dirs = next(os.walk(Dir("..").abspath))[DIRNAMES]
94162
parent_modules = []
@@ -103,19 +171,28 @@ if os.getenv("GOOST_PARENT_MODULES", "disabled") == "enabled":
103171
build_args.append("module_%s_enabled=no" % m)
104172

105173
# 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.
119196
build_name = module_name.capitalize()
120197
if os.getenv("BUILD_NAME"):
121198
build_name += "." + os.getenv("BUILD_NAME")
@@ -130,6 +207,24 @@ if scons_cache_path != None:
130207
CacheDir(scons_cache_path)
131208
print("SCons cache enabled... (path: '" + scons_cache_path + "')")
132209

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

Comments
 (0)