Skip to content

Commit b17f07b

Browse files
authored
Using SCons tools (#977)
Changing the SCons architecture to clean up SConstruct and isolating languages more
1 parent 62f2a31 commit b17f07b

File tree

7 files changed

+209
-23
lines changed

7 files changed

+209
-23
lines changed

SConstruct

Lines changed: 43 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -11,26 +11,51 @@ from pathlib import Path
1111
from collections import namedtuple
1212
import os
1313

14-
15-
rust_cargo_builder = Builder(action=['cargo build --bins --manifest-path $MANIFEST',
16-
Move('$TARGET$PROGSUFFIX', '$SOURCE_DIR/target/debug/main$PROGSUFFIX')])
17-
18-
rust_rustc_builder = Builder(action='rustc $SOURCE -o $TARGET$PROGSUFFIX')
19-
20-
go_builder = Builder(action='go build -o $TARGET$PROGSUFFIX $SOURCE')
14+
import SCons
15+
SCons.Warnings.warningAsException()
2116

2217
# For interpreted languages to copy to build directory
2318
copy_builder = Builder(action=Copy('$TARGET', '$SOURCE'))
2419

25-
coconut_builder = Builder(action='coconut $COCONUTFLAGS $SOURCE $TARGET', src_suffix='.coco', target_suffix='.py')
26-
2720
env = Environment(ENV=os.environ,
28-
BUILDERS={'rustc': rust_rustc_builder,
29-
'cargo': rust_cargo_builder,
30-
'Go': go_builder,
31-
'Copier': copy_builder,
32-
'Coconut': coconut_builder},
33-
tools=['gcc', 'gnulink', 'g++', 'gas', 'gfortran', 'javac'])
21+
BUILDERS={'Copier': copy_builder},
22+
tools=[
23+
'g++', 'gas', 'gcc', 'gfortran', 'gnulink', 'javac'],
24+
toolpath=['builders'])
25+
26+
available_languages = {
27+
'asm-x64',
28+
'bash',
29+
'c',
30+
'cpp',
31+
'fortran',
32+
'java',
33+
'julia',
34+
'lolcode'
35+
'lua',
36+
'php',
37+
'powershell',
38+
'python',
39+
'ruby',
40+
'viml',
41+
}
42+
43+
languages_to_import = {
44+
'coconut': ['coconut'],
45+
'go': ['go'],
46+
'rust': ['rustc', 'cargo'],
47+
}
48+
49+
for language, tools in languages_to_import.items():
50+
for tool in tools:
51+
try:
52+
env.Tool(tool)
53+
except SCons.Warnings.SConsWarning as w:
54+
print(f'{w.args[0][0]}, ignoring')
55+
break
56+
else:
57+
available_languages.add(language)
58+
3459

3560
Export('env')
3661

@@ -69,11 +94,11 @@ env.CPlusPlus = env.Program
6994
env.X64 = env.Program
7095
env.Fortran = env.Program
7196

72-
for language in languages:
97+
for language in available_languages:
7398
Alias(language, f'#/build/{language}')
7499

75100
sconscripts = []
76-
files_to_compile = {language: [] for language in languages}
101+
files_to_compile = {language: [] for language in languages if language in available_languages}
77102

78103
FileInformation = namedtuple('FileInformation', ['path', 'chapter', 'language'])
79104

@@ -85,7 +110,7 @@ for chapter_dir in contents_path.iterdir():
85110
extended_chapter_path = code_dir.relative_to(contents_path).parent
86111

87112
for language_dir in code_dir.iterdir():
88-
if (language := language_dir.stem) in languages:
113+
if (language := language_dir.stem) in available_languages:
89114
new_files = [FileInformation(path=file_path,
90115
chapter=extended_chapter_path,
91116
language=language)

builders/cargo.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
from SCons.Builder import Builder
2+
from SCons.Script import Move
3+
import SCons.Util
4+
5+
class ToolCargoWarning(SCons.Warnings.SConsWarning):
6+
pass
7+
8+
class CargoNotFound(ToolCargoWarning):
9+
pass
10+
11+
SCons.Warnings.enableWarningClass(ToolCargoWarning)
12+
13+
def _detect(env):
14+
try:
15+
return env['cargo']
16+
except KeyError:
17+
pass
18+
19+
cargo = env.WhereIs('cargo')
20+
if cargo:
21+
return cargo
22+
23+
SCons.Warnings.warn(CargoNotFound, 'Could not detect cargo')
24+
25+
def exists(env):
26+
return env.Detect('cargo')
27+
28+
29+
def generate(env):
30+
env['CARGO'] = _detect(env)
31+
env['CARGOFLAGS'] = []
32+
env['MANIFEST'] = []
33+
34+
rust_cargo_builder = Builder(
35+
action=['"$CARGO" build $CARGOFLAGS --bins --manifest-path $MANIFEST',
36+
Move('$TARGET$PROGSUFFIX',
37+
'$SOURCE_DIR/target/debug/main$PROGSUFFIX')
38+
],
39+
suffix='$PROGSUFFIX',
40+
)
41+
env.Append(BUILDERS={'cargo': rust_cargo_builder})

builders/coconut.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
from SCons.Builder import Builder
2+
import SCons.Util
3+
4+
class ToolCocoWarning(SCons.Warnings.SConsWarning):
5+
pass
6+
7+
class CoconutNotFound(ToolCocoWarning):
8+
pass
9+
10+
SCons.Warnings.enableWarningClass(ToolCocoWarning)
11+
12+
def _detect(env):
13+
try:
14+
return env['coconut']
15+
except KeyError:
16+
pass
17+
18+
coconut = env.WhereIs('coconut')
19+
if coconut:
20+
return coconut
21+
22+
SCons.Warnings.warn(CoconutNotFound, 'Could not find Coconut executable')
23+
24+
25+
def generate(env):
26+
env['COCONUT'] = _detect(env)
27+
env['COCONUTFLAGS'] = []
28+
29+
coconut_compiler = Builder(
30+
action='"$COCONUT" $COCONUTFLAGS $SOURCE $TARGET',
31+
src_suffix='.coco',
32+
suffix='.py',
33+
)
34+
35+
env.Append(BUILDERS={'Coconut': coconut_compiler})
36+
37+
def exists(env):
38+
return env.Detect('coconut')
39+
40+

builders/go.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
from SCons.Builder import Builder
2+
import SCons.Util
3+
4+
class ToolGoWarning(SCons.Warnings.SConsWarning):
5+
pass
6+
7+
class GoNotFound(ToolGoWarning):
8+
pass
9+
10+
SCons.Warnings.enableWarningClass(ToolGoWarning)
11+
12+
def _detect(env):
13+
try:
14+
return env['go']
15+
except KeyError:
16+
pass
17+
18+
go = env.WhereIs('go')
19+
if go:
20+
return go
21+
22+
SCons.Warnings.warn(GoNotFound, 'Could not find go executable')
23+
24+
def exists(env):
25+
env.Detect('go')
26+
27+
def generate(env):
28+
env['GO'] = _detect(env)
29+
env['GOFLAGS'] = []
30+
31+
go_builder = Builder(
32+
action='"$GO" build -o $TARGET $GOFLAGS $SOURCE',
33+
src_suffix='.go',
34+
suffix='$PROGSUFFIX',
35+
)
36+
37+
env.Append(BUILDERS={'Go': go_builder})

builders/rustc.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
from SCons.Builder import Builder
2+
import SCons.Util
3+
4+
class ToolRustcWarning(SCons.Warnings.SConsWarning):
5+
pass
6+
7+
class RustcNotFound(ToolRustcWarning):
8+
pass
9+
10+
SCons.Warnings.enableWarningClass(ToolRustcWarning)
11+
12+
def _detect(env):
13+
try:
14+
return env['rustc']
15+
except KeyError:
16+
pass
17+
18+
cargo = env.WhereIs('rustc')
19+
if cargo:
20+
return cargo
21+
22+
SCons.Warnings.warn(RustcNotFound, 'Could not detect rustc')
23+
24+
25+
def exists(env):
26+
return env.Detect('rustc')
27+
28+
def rustc_emitter(target, source, env):
29+
src_name = str(source[0])
30+
pdb_name = src_name.replace(source[0].suffix, '.pdb')
31+
env.SideEffect(pdb_name, target)
32+
env.Clean(target, pdb_name)
33+
return (target, source)
34+
35+
def generate(env):
36+
env['RUSTC'] = _detect(env)
37+
env['RUSTCFLAGS'] = []
38+
39+
rust_cargo_builder = Builder(
40+
action='"$RUSTC" $RUSTCFLAGS -o $TARGET $SOURCE',
41+
suffix='$PROGSUFFIX',
42+
src_suffix='.rs',
43+
emitter=rustc_emitter,
44+
)
45+
env.Append(BUILDERS={'rustc': rust_cargo_builder})

contents/stacks_and_queues/code/rust/SConscript

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@ from pathlib import Path
33

44
dirname = Path.cwd().parents[1].stem
55

6-
env.rustc(f'#/build/rust/stack', '#/contents/stacks_and_queues/code/rust/Stack.rs')
7-
env.Clean('rust', f'#/build/rust/stack.pdb')
6+
env.rustc(f'#/build/rust/{dirname}/stack', '#/contents/stacks_and_queues/code/rust/Stack.rs')
87

9-
env.rustc(f'#/build/rust/queue', '#/contents/stacks_and_queues/code/rust/Queue.rs')
10-
env.Clean('rust', f'#/build/rust/queue.pdb')
8+
env.rustc(f'#/build/rust/{dirname}/queue', '#/contents/stacks_and_queues/code/rust/Queue.rs')

sconscripts/rust_SConscript

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,4 @@ for file_info in files_to_compile:
1212
build_result = env.rustc(build_target, str(file_info.path))
1313
env.Clean('rust', f'{build_target}.pdb')
1414

15-
env.Alias(str(file_info.chapter), build_result)
15+
env.Alias(str(file_info.chapter), build_result)

0 commit comments

Comments
 (0)