Skip to content

Commit

Permalink
Using SCons tools (algorithm-archivists#977)
Browse files Browse the repository at this point in the history
Changing the SCons architecture to clean up SConstruct and isolating languages more
  • Loading branch information
Amaras authored Dec 26, 2021
1 parent 62f2a31 commit b17f07b
Show file tree
Hide file tree
Showing 7 changed files with 209 additions and 23 deletions.
61 changes: 43 additions & 18 deletions SConstruct
Original file line number Diff line number Diff line change
Expand Up @@ -11,26 +11,51 @@ from pathlib import Path
from collections import namedtuple
import os


rust_cargo_builder = Builder(action=['cargo build --bins --manifest-path $MANIFEST',
Move('$TARGET$PROGSUFFIX', '$SOURCE_DIR/target/debug/main$PROGSUFFIX')])

rust_rustc_builder = Builder(action='rustc $SOURCE -o $TARGET$PROGSUFFIX')

go_builder = Builder(action='go build -o $TARGET$PROGSUFFIX $SOURCE')
import SCons
SCons.Warnings.warningAsException()

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

coconut_builder = Builder(action='coconut $COCONUTFLAGS $SOURCE $TARGET', src_suffix='.coco', target_suffix='.py')

env = Environment(ENV=os.environ,
BUILDERS={'rustc': rust_rustc_builder,
'cargo': rust_cargo_builder,
'Go': go_builder,
'Copier': copy_builder,
'Coconut': coconut_builder},
tools=['gcc', 'gnulink', 'g++', 'gas', 'gfortran', 'javac'])
BUILDERS={'Copier': copy_builder},
tools=[
'g++', 'gas', 'gcc', 'gfortran', 'gnulink', 'javac'],
toolpath=['builders'])

available_languages = {
'asm-x64',
'bash',
'c',
'cpp',
'fortran',
'java',
'julia',
'lolcode'
'lua',
'php',
'powershell',
'python',
'ruby',
'viml',
}

languages_to_import = {
'coconut': ['coconut'],
'go': ['go'],
'rust': ['rustc', 'cargo'],
}

for language, tools in languages_to_import.items():
for tool in tools:
try:
env.Tool(tool)
except SCons.Warnings.SConsWarning as w:
print(f'{w.args[0][0]}, ignoring')
break
else:
available_languages.add(language)


Export('env')

Expand Down Expand Up @@ -69,11 +94,11 @@ env.CPlusPlus = env.Program
env.X64 = env.Program
env.Fortran = env.Program

for language in languages:
for language in available_languages:
Alias(language, f'#/build/{language}')

sconscripts = []
files_to_compile = {language: [] for language in languages}
files_to_compile = {language: [] for language in languages if language in available_languages}

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

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

for language_dir in code_dir.iterdir():
if (language := language_dir.stem) in languages:
if (language := language_dir.stem) in available_languages:
new_files = [FileInformation(path=file_path,
chapter=extended_chapter_path,
language=language)
Expand Down
41 changes: 41 additions & 0 deletions builders/cargo.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
from SCons.Builder import Builder
from SCons.Script import Move
import SCons.Util

class ToolCargoWarning(SCons.Warnings.SConsWarning):
pass

class CargoNotFound(ToolCargoWarning):
pass

SCons.Warnings.enableWarningClass(ToolCargoWarning)

def _detect(env):
try:
return env['cargo']
except KeyError:
pass

cargo = env.WhereIs('cargo')
if cargo:
return cargo

SCons.Warnings.warn(CargoNotFound, 'Could not detect cargo')

def exists(env):
return env.Detect('cargo')


def generate(env):
env['CARGO'] = _detect(env)
env['CARGOFLAGS'] = []
env['MANIFEST'] = []

rust_cargo_builder = Builder(
action=['"$CARGO" build $CARGOFLAGS --bins --manifest-path $MANIFEST',
Move('$TARGET$PROGSUFFIX',
'$SOURCE_DIR/target/debug/main$PROGSUFFIX')
],
suffix='$PROGSUFFIX',
)
env.Append(BUILDERS={'cargo': rust_cargo_builder})
40 changes: 40 additions & 0 deletions builders/coconut.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
from SCons.Builder import Builder
import SCons.Util

class ToolCocoWarning(SCons.Warnings.SConsWarning):
pass

class CoconutNotFound(ToolCocoWarning):
pass

SCons.Warnings.enableWarningClass(ToolCocoWarning)

def _detect(env):
try:
return env['coconut']
except KeyError:
pass

coconut = env.WhereIs('coconut')
if coconut:
return coconut

SCons.Warnings.warn(CoconutNotFound, 'Could not find Coconut executable')


def generate(env):
env['COCONUT'] = _detect(env)
env['COCONUTFLAGS'] = []

coconut_compiler = Builder(
action='"$COCONUT" $COCONUTFLAGS $SOURCE $TARGET',
src_suffix='.coco',
suffix='.py',
)

env.Append(BUILDERS={'Coconut': coconut_compiler})

def exists(env):
return env.Detect('coconut')


37 changes: 37 additions & 0 deletions builders/go.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
from SCons.Builder import Builder
import SCons.Util

class ToolGoWarning(SCons.Warnings.SConsWarning):
pass

class GoNotFound(ToolGoWarning):
pass

SCons.Warnings.enableWarningClass(ToolGoWarning)

def _detect(env):
try:
return env['go']
except KeyError:
pass

go = env.WhereIs('go')
if go:
return go

SCons.Warnings.warn(GoNotFound, 'Could not find go executable')

def exists(env):
env.Detect('go')

def generate(env):
env['GO'] = _detect(env)
env['GOFLAGS'] = []

go_builder = Builder(
action='"$GO" build -o $TARGET $GOFLAGS $SOURCE',
src_suffix='.go',
suffix='$PROGSUFFIX',
)

env.Append(BUILDERS={'Go': go_builder})
45 changes: 45 additions & 0 deletions builders/rustc.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
from SCons.Builder import Builder
import SCons.Util

class ToolRustcWarning(SCons.Warnings.SConsWarning):
pass

class RustcNotFound(ToolRustcWarning):
pass

SCons.Warnings.enableWarningClass(ToolRustcWarning)

def _detect(env):
try:
return env['rustc']
except KeyError:
pass

cargo = env.WhereIs('rustc')
if cargo:
return cargo

SCons.Warnings.warn(RustcNotFound, 'Could not detect rustc')


def exists(env):
return env.Detect('rustc')

def rustc_emitter(target, source, env):
src_name = str(source[0])
pdb_name = src_name.replace(source[0].suffix, '.pdb')
env.SideEffect(pdb_name, target)
env.Clean(target, pdb_name)
return (target, source)

def generate(env):
env['RUSTC'] = _detect(env)
env['RUSTCFLAGS'] = []

rust_cargo_builder = Builder(
action='"$RUSTC" $RUSTCFLAGS -o $TARGET $SOURCE',
suffix='$PROGSUFFIX',
src_suffix='.rs',
emitter=rustc_emitter,
)
env.Append(BUILDERS={'rustc': rust_cargo_builder})
6 changes: 2 additions & 4 deletions contents/stacks_and_queues/code/rust/SConscript
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@ from pathlib import Path

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

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

env.rustc(f'#/build/rust/queue', '#/contents/stacks_and_queues/code/rust/Queue.rs')
env.Clean('rust', f'#/build/rust/queue.pdb')
env.rustc(f'#/build/rust/{dirname}/queue', '#/contents/stacks_and_queues/code/rust/Queue.rs')
2 changes: 1 addition & 1 deletion sconscripts/rust_SConscript
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@ for file_info in files_to_compile:
build_result = env.rustc(build_target, str(file_info.path))
env.Clean('rust', f'{build_target}.pdb')

env.Alias(str(file_info.chapter), build_result)
env.Alias(str(file_info.chapter), build_result)

0 comments on commit b17f07b

Please sign in to comment.