Skip to content

Commit 93f2091

Browse files
committed
[SCons] Move toolchains logic to tools folder.
1 parent a0fcd8a commit 93f2091

File tree

8 files changed

+461
-393
lines changed

8 files changed

+461
-393
lines changed

SConstruct

+24-393
Large diffs are not rendered by default.

tools/android.py

+110
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
import os
2+
import sys
3+
import my_spawn
4+
from SCons.Script import ARGUMENTS
5+
6+
7+
def options(opts):
8+
opts.Add(
9+
"android_api_level",
10+
"Target Android API level",
11+
"18" if "32" in ARGUMENTS.get("arch", "arm64") else "21",
12+
)
13+
opts.Add(
14+
"ANDROID_NDK_ROOT",
15+
"Path to your Android NDK installation. By default, uses ANDROID_NDK_ROOT from your defined environment variables.",
16+
os.environ.get("ANDROID_NDK_ROOT", None),
17+
)
18+
19+
20+
def exists(env):
21+
if not "ANDROID_NDK_ROOT" in os.environ:
22+
return False
23+
return True
24+
25+
26+
def generate(env):
27+
if not "ANDROID_NDK_ROOT" in os.environ:
28+
raise ValueError(
29+
"To build for Android, ANDROID_NDK_ROOT must be defined. Please set ANDROID_NDK_ROOT to the root folder of your Android NDK installation."
30+
)
31+
32+
env["ANDROID_NDK_ROOT"] = os.environ["ANDROID_NDK_ROOT"]
33+
34+
if env["arch"] not in ("arm64", "x86_64", "arm32", "x86_32"):
35+
print("Only arm64, x86_64, arm32, and x86_32 are supported on Android. Exiting.")
36+
Exit()
37+
38+
if sys.platform == "win32" or sys.platform == "msys":
39+
my_spawn.configure(env)
40+
41+
# Validate API level
42+
api_level = int(env["android_api_level"])
43+
if "64" in env["arch"] and api_level < 21:
44+
print("WARN: 64-bit Android architectures require an API level of at least 21; setting android_api_level=21")
45+
env["android_api_level"] = "21"
46+
api_level = 21
47+
48+
# Setup toolchain
49+
toolchain = env["ANDROID_NDK_ROOT"] + "/toolchains/llvm/prebuilt/"
50+
if sys.platform == "win32" or sys.platform == "msys":
51+
toolchain += "windows"
52+
import platform as pltfm
53+
54+
if pltfm.machine().endswith("64"):
55+
toolchain += "-x86_64"
56+
elif sys.platform.startswith("linux"):
57+
toolchain += "linux-x86_64"
58+
elif sys.platform == "darwin":
59+
toolchain += "darwin-x86_64"
60+
env.PrependENVPath("PATH", toolchain + "/bin") # This does nothing half of the time, but we'll put it here anyways
61+
62+
# Get architecture info
63+
arch_info_table = {
64+
"arm32": {
65+
"march": "armv7-a",
66+
"target": "armv7a-linux-androideabi",
67+
"compiler_path": "armv7a-linux-androideabi",
68+
"ccflags": ["-mfpu=neon"],
69+
},
70+
"arm64": {
71+
"march": "armv8-a",
72+
"target": "aarch64-linux-android",
73+
"compiler_path": "aarch64-linux-android",
74+
"ccflags": [],
75+
},
76+
"x86_32": {
77+
"march": "i686",
78+
"target": "i686-linux-android",
79+
"compiler_path": "i686-linux-android",
80+
"ccflags": ["-mstackrealign"],
81+
},
82+
"x86_64": {
83+
"march": "x86-64",
84+
"target": "x86_64-linux-android",
85+
"compiler_path": "x86_64-linux-android",
86+
"ccflags": [],
87+
},
88+
}
89+
arch_info = arch_info_table[env["arch"]]
90+
91+
# Setup tools
92+
env["CC"] = toolchain + "/bin/clang"
93+
env["CXX"] = toolchain + "/bin/clang++"
94+
env["LINK"] = toolchain + "/bin/clang++"
95+
env["AR"] = toolchain + "/bin/llvm-ar"
96+
env["AS"] = toolchain + "/bin/llvm-as"
97+
env["STRIP"] = toolchain + "/bin/llvm-strip"
98+
env["RANLIB"] = toolchain + "/bin/llvm-ranlib"
99+
env["SHLIBSUFFIX"] = ".so"
100+
101+
env.Append(
102+
CCFLAGS=["--target=" + arch_info["target"] + env["android_api_level"], "-march=" + arch_info["march"], "-fPIC"]
103+
) # , '-fPIE', '-fno-addrsig', '-Oz'])
104+
env.Append(CCFLAGS=arch_info["ccflags"])
105+
env.Append(LINKFLAGS=["--target=" + arch_info["target"] + env["android_api_level"], "-march=" + arch_info["march"]])
106+
107+
if env["target"] == "debug":
108+
env.Append(CCFLAGS=["-Og", "-g"])
109+
elif env["target"] == "release":
110+
env.Append(CCFLAGS=["-O3"])

tools/ios.py

+74
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
import os
2+
import sys
3+
import subprocess
4+
from SCons.Variables import *
5+
6+
if sys.version_info < (3,):
7+
8+
def decode_utf8(x):
9+
return x
10+
11+
else:
12+
import codecs
13+
14+
def decode_utf8(x):
15+
return codecs.utf_8_decode(x)[0]
16+
17+
18+
def options(opts):
19+
opts.Add(BoolVariable("ios_simulator", "Target iOS Simulator", False))
20+
opts.Add(
21+
"IPHONEPATH",
22+
"Path to iPhone toolchain",
23+
"/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain",
24+
)
25+
26+
27+
def exists(env):
28+
return sys.platform == "darwin"
29+
30+
31+
def generate(env):
32+
if env["arch"] not in ("universal", "arm64", "x86_64"):
33+
print("Only universal, arm64, and x86_64 are supported on iOS. Exiting.")
34+
Exit()
35+
36+
if env["ios_simulator"]:
37+
sdk_name = "iphonesimulator"
38+
env.Append(CCFLAGS=["-mios-simulator-version-min=10.0"])
39+
else:
40+
sdk_name = "iphoneos"
41+
env.Append(CCFLAGS=["-miphoneos-version-min=10.0"])
42+
43+
try:
44+
sdk_path = decode_utf8(subprocess.check_output(["xcrun", "--sdk", sdk_name, "--show-sdk-path"]).strip())
45+
except (subprocess.CalledProcessError, OSError):
46+
raise ValueError("Failed to find SDK path while running xcrun --sdk {} --show-sdk-path.".format(sdk_name))
47+
48+
compiler_path = env["IPHONEPATH"] + "/usr/bin/"
49+
env["ENV"]["PATH"] = env["IPHONEPATH"] + "/Developer/usr/bin/:" + env["ENV"]["PATH"]
50+
51+
env["CC"] = compiler_path + "clang"
52+
env["CXX"] = compiler_path + "clang++"
53+
env["AR"] = compiler_path + "ar"
54+
env["RANLIB"] = compiler_path + "ranlib"
55+
env["SHLIBSUFFIX"] = ".dylib"
56+
57+
if env["arch"] == "universal":
58+
if env["ios_simulator"]:
59+
env.Append(LINKFLAGS=["-arch", "x86_64", "-arch", "arm64"])
60+
env.Append(CCFLAGS=["-arch", "x86_64", "-arch", "arm64"])
61+
else:
62+
env.Append(LINKFLAGS=["-arch", "arm64"])
63+
env.Append(CCFLAGS=["-arch", "arm64"])
64+
else:
65+
env.Append(LINKFLAGS=["-arch", env["arch"]])
66+
env.Append(CCFLAGS=["-arch", env["arch"]])
67+
68+
env.Append(CCFLAGS=["-isysroot", sdk_path])
69+
env.Append(LINKFLAGS=["-isysroot", sdk_path, "-F" + sdk_path])
70+
71+
if env["target"] == "debug":
72+
env.Append(CCFLAGS=["-Og", "-g"])
73+
elif env["target"] == "release":
74+
env.Append(CCFLAGS=["-O3"])

tools/javascript.py

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import os
2+
3+
4+
def exists(env):
5+
return "EM_CONFIG" in os.environ
6+
7+
8+
def generate(env):
9+
if env["arch"] not in ("wasm32"):
10+
print("Only wasm32 supported on web. Exiting.")
11+
Exit()
12+
13+
if "EM_CONFIG" in os.environ:
14+
env["ENV"] = os.environ
15+
16+
env["CC"] = "emcc"
17+
env["CXX"] = "em++"
18+
env["AR"] = "emar"
19+
env["RANLIB"] = "emranlib"
20+
env.Append(CPPFLAGS=["-s", "SIDE_MODULE=1"])
21+
env.Append(LINKFLAGS=["-s", "SIDE_MODULE=1"])
22+
env["SHOBJSUFFIX"] = ".bc"
23+
env["SHLIBSUFFIX"] = ".wasm"
24+
# Use TempFileMunge since some AR invocations are too long for cmd.exe.
25+
# Use POSIX-style paths, required with TempFileMunge.
26+
env["ARCOM_POSIX"] = env["ARCOM"].replace("$TARGET", "$TARGET.posix").replace("$SOURCES", "$SOURCES.posix")
27+
env["ARCOM"] = "${TEMPFILE(ARCOM_POSIX)}"
28+
29+
# All intermediate files are just LLVM bitcode.
30+
env["OBJPREFIX"] = ""
31+
env["OBJSUFFIX"] = ".bc"
32+
env["PROGPREFIX"] = ""
33+
# Program() output consists of multiple files, so specify suffixes manually at builder.
34+
env["PROGSUFFIX"] = ""
35+
env["LIBPREFIX"] = "lib"
36+
env["LIBSUFFIX"] = ".a"
37+
env["LIBPREFIXES"] = ["$LIBPREFIX"]
38+
env["LIBSUFFIXES"] = ["$LIBSUFFIX"]
39+
env.Replace(SHLINKFLAGS="$LINKFLAGS")
40+
env.Replace(SHLINKFLAGS="$LINKFLAGS")
41+
42+
if env["target"] == "debug":
43+
env.Append(CCFLAGS=["-O0", "-g"])
44+
elif env["target"] == "release":
45+
env.Append(CCFLAGS=["-O3"])

tools/linux.py

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
from SCons.Variables import *
2+
3+
4+
def options(opts):
5+
opts.Add(BoolVariable("use_llvm", "Use the LLVM compiler - only effective when targeting Linux", False))
6+
7+
8+
def exists(env):
9+
return True
10+
11+
12+
def generate(env):
13+
if env["use_llvm"]:
14+
base = env.Tool("clang")
15+
base.generate(env)
16+
17+
env.Append(CCFLAGS=["-fPIC", "-Wwrite-strings"])
18+
env.Append(LINKFLAGS=["-Wl,-R,'$$ORIGIN'"])
19+
20+
if env["target"] == "debug":
21+
env.Append(CCFLAGS=["-Og", "-g"])
22+
elif env["target"] == "release":
23+
env.Append(CCFLAGS=["-O3"])
24+
25+
if env["arch"] == "x86_64":
26+
# -m64 and -m32 are x86-specific already, but it doesn't hurt to
27+
# be clear and also specify -march=x86-64. Similar with 32-bit.
28+
env.Append(CCFLAGS=["-m64", "-march=x86-64"])
29+
env.Append(LINKFLAGS=["-m64", "-march=x86-64"])
30+
elif env["arch"] == "x86_32":
31+
env.Append(CCFLAGS=["-m32", "-march=i686"])
32+
env.Append(LINKFLAGS=["-m32", "-march=i686"])
33+
elif env["arch"] == "arm64":
34+
env.Append(CCFLAGS=["-march=armv8-a"])
35+
env.Append(LINKFLAGS=["-march=armv8-a"])
36+
elif env["arch"] == "rv64":
37+
env.Append(CCFLAGS=["-march=rv64gc"])
38+
env.Append(LINKFLAGS=["-march=rv64gc"])

tools/my_spawn.py

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import os
2+
3+
4+
def exists(env):
5+
return os.name == "nt"
6+
7+
8+
# Workaround for MinGW. See:
9+
# http://www.scons.org/wiki/LongCmdLinesOnWin32
10+
def configure(env):
11+
import subprocess
12+
13+
def mySubProcess(cmdline, env):
14+
# print "SPAWNED : " + cmdline
15+
startupinfo = subprocess.STARTUPINFO()
16+
startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
17+
proc = subprocess.Popen(
18+
cmdline,
19+
stdin=subprocess.PIPE,
20+
stdout=subprocess.PIPE,
21+
stderr=subprocess.PIPE,
22+
startupinfo=startupinfo,
23+
shell=False,
24+
env=env,
25+
)
26+
data, err = proc.communicate()
27+
rv = proc.wait()
28+
if rv:
29+
print("=====")
30+
print(err.decode("utf-8"))
31+
print("=====")
32+
return rv
33+
34+
def mySpawn(sh, escape, cmd, args, env):
35+
36+
newargs = " ".join(args[1:])
37+
cmdline = cmd + " " + newargs
38+
39+
rv = 0
40+
if len(cmdline) > 32000 and cmd.endswith("ar"):
41+
cmdline = cmd + " " + args[1] + " " + args[2] + " "
42+
for i in range(3, len(args)):
43+
rv = mySubProcess(cmdline + args[i], env)
44+
if rv:
45+
break
46+
else:
47+
rv = mySubProcess(cmdline, env)
48+
49+
return rv
50+
51+
env["SPAWN"] = mySpawn
52+
env.Replace(ARFLAGS=["q"])

tools/osx.py

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import os
2+
import sys
3+
4+
5+
def options(opts):
6+
opts.Add("macos_deployment_target", "macOS deployment target", "default")
7+
opts.Add("macos_sdk_path", "macOS SDK path", "")
8+
9+
10+
def exists(env):
11+
return sys.platform == "darwin"
12+
13+
14+
def generate(env):
15+
if env["arch"] not in ("universal", "arm64", "x86_64"):
16+
print("Only universal, arm64, and x86_64 are supported on macOS. Exiting.")
17+
Exit()
18+
19+
if sys.platform == "darwin":
20+
# Use clang on macOS by default
21+
env["CXX"] = "clang++"
22+
env["CC"] = "clang"
23+
24+
if env["arch"] == "universal":
25+
env.Append(LINKFLAGS=["-arch", "x86_64", "-arch", "arm64"])
26+
env.Append(CCFLAGS=["-arch", "x86_64", "-arch", "arm64"])
27+
else:
28+
env.Append(LINKFLAGS=["-arch", env["arch"]])
29+
env.Append(CCFLAGS=["-arch", env["arch"]])
30+
31+
if env["macos_deployment_target"] != "default":
32+
env.Append(CCFLAGS=["-mmacosx-version-min=" + env["macos_deployment_target"]])
33+
env.Append(LINKFLAGS=["-mmacosx-version-min=" + env["macos_deployment_target"]])
34+
35+
if env["macos_sdk_path"]:
36+
env.Append(CCFLAGS=["-isysroot", env["macos_sdk_path"]])
37+
env.Append(LINKFLAGS=["-isysroot", env["macos_sdk_path"]])
38+
39+
env.Append(
40+
LINKFLAGS=[
41+
"-framework",
42+
"Cocoa",
43+
"-Wl,-undefined,dynamic_lookup",
44+
]
45+
)
46+
47+
if env["target"] == "debug":
48+
env.Append(CCFLAGS=["-Og", "-g"])
49+
elif env["target"] == "release":
50+
env.Append(CCFLAGS=["-O3"])

0 commit comments

Comments
 (0)