Skip to content

Using SCons tools #977

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Dec 26, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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)