Skip to content

Change SCons output structure #963

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

44 changes: 30 additions & 14 deletions SConstruct
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@ Currently, the aim is to provide a way to compile or copy the implementation fil
To run the compilation for all implementations in one language, e.g. C, run the command `scons build/c`, and the resulting executables will be available in the `build/c` directory, each in their respective algorithm directory, containing the executable."""

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')])

Expand All @@ -23,48 +25,62 @@ env = Environment(ENV=os.environ,
'Go': go_builder},
tools=['gcc', 'gnulink', 'g++', 'gas', 'gfortran'])

Export('env')

env['CFLAGS'] = '-Wall -Wextra -Werror'
env['CXXFLAGS'] = '-std=c++17'
env['ASFLAGS'] = '--64'

# Add other languages here when you want to add language targets
# Put 'name_of_language_directory' : 'file_extension'
languages = {
'c': 'c',
'c': 'c',
'cpp': 'cpp',
'asm-x64': 's',
'rust': 'rs',
'go': 'go',
'fortran': 'f90',
}

# Do not add new Builders here, add them to the BUILDERS argument in the call to Environment above
env.C = env.Program
env.CPlusPlus = env.Program
env.X64 = env.Program
env.Fortran = env.Program

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

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

for chapter_dir in Path.cwd().joinpath('contents').iterdir():
if (code_dir := (chapter_dir / 'code')).exists():
for path in code_dir.iterdir():
if path.stem in languages:
# Check for overriding sconscript
if (sconscript_path := path / 'SConscript').exists():
sconscripts.append(sconscript_path)
SConscript(sconscript_path, exports='env')
FileInformation = namedtuple('FileInformation', ['path', 'chapter', 'language'])


contents_path = Path.cwd().joinpath('contents')
for chapter_dir in contents_path.iterdir():
for code_dir in chapter_dir.glob('**/code'):
# For nested chapters e.g. contents/convolutions/1d/
extended_chapter_path = code_dir.relative_to(contents_path).parent

for language_dir in code_dir.iterdir():
if (language := language_dir.stem) in languages:
new_files = [FileInformation(path=file_path,
chapter=extended_chapter_path,
language=language)
for file_path in language_dir.glob(f'**/*.{languages[language]}')
]
# Check for overriding SConscript
if (sconscript_path := language_dir / 'SConscript').exists():
SConscript(sconscript_path, exports={'files_to_compile': new_files})
else:
files_to_compile[path.stem].extend(path.glob(f'*.{languages[path.stem]}'))
files_to_compile[language].extend(new_files)

sconscript_dir_path = Path('sconscripts')
sconscript_dir_path = Path.cwd().joinpath('sconscripts')
for language, files in files_to_compile.items():
if files:
if (sconscript_path := sconscript_dir_path / f"{language}_SConscript").exists():
SConscript(sconscript_path, exports = {'files_to_compile': files,
'language': language})
SConscript(sconscript_path, exports = {'files_to_compile': files})
else:
print(f'{language} file found at {files[0]}, but no sconscript file is present ')

10 changes: 5 additions & 5 deletions contents/approximate_counting/code/c/SConscript
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Import('*')
from pathlib import Path
Import('files_to_compile env')

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

env.C(f'#/build/c/{dirname}', Glob('*.c'), LIBS='m')
for file_info in files_to_compile:
build_target = f'#/build/{file_info.language}/{file_info.chapter}/{file_info.path.stem}'
build_result = env.C(build_target, str(file_info.path), LIBS='m')
env.Alias(str(file_info.chapter), build_result)
10 changes: 5 additions & 5 deletions contents/cooley_tukey/code/asm-x64/SConscript
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Import('*')
from pathlib import Path
Import('files_to_compile env')

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

env.X64(f'#/build/asm-x64/{dirname}', Glob('*.s'), LIBS=['m'], LINKFLAGS='-no-pie')
for file_info in files_to_compile:
build_target = f'#/build/{file_info.language}/{file_info.chapter}/{file_info.path.stem}'
build_result = env.X64(build_target, str(file_info.path), LIBS='m', LINKFLAGS='-no-pie')
env.Alias(str(file_info.chapter), build_result)
10 changes: 5 additions & 5 deletions contents/cooley_tukey/code/c/SConscript
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Import('*')
from pathlib import Path
Import('files_to_compile env')

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

env.C(f'#/build/c/{dirname}', Glob('*.c'), LIBS=['m', 'fftw3'])
for file_info in files_to_compile:
build_target = f'#/build/{file_info.language}/{file_info.chapter}/{file_info.path.stem}'
build_result = env.C(build_target, str(file_info.path), LIBS=['m', 'fftw3'])
env.Alias(str(file_info.chapter), build_result)
6 changes: 0 additions & 6 deletions contents/euclidean_algorithm/code/fortran/SConscript

This file was deleted.

10 changes: 5 additions & 5 deletions contents/forward_euler_method/code/asm-x64/SConscript
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Import('*')
from pathlib import Path
Import('files_to_compile env')

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

env.X64(f'#/build/asm-x64/{dirname}', Glob('*.s'), LIBS='m', LINKFLAGS='-no-pie')
for file_info in files_to_compile:
build_target = f'#/build/{file_info.language}/{file_info.chapter}/{file_info.path.stem}'
build_result = env.X64(build_target, str(file_info.path), LIBS='m', LINKFLAGS='-no-pie')
env.Alias(str(file_info.chapter), build_result)
10 changes: 5 additions & 5 deletions contents/forward_euler_method/code/c/SConscript
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Import('*')
from pathlib import Path
Import('files_to_compile env')

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

env.C(f'#/build/c/{dirname}', Glob('*.c'), LIBS='m')
for file_info in files_to_compile:
build_target = f'#/build/{file_info.language}/{file_info.chapter}/{file_info.path.stem}'
build_result = env.C(build_target, str(file_info.path), LIBS='m')
env.Alias(str(file_info.chapter), build_result)
10 changes: 5 additions & 5 deletions contents/graham_scan/code/c/SConscript
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Import('*')
from pathlib import Path
Import('files_to_compile env')

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

env.C(f'#/build/c/{dirname}', Glob('*.c'), LIBS='m')
for file_info in files_to_compile:
build_target = f'#/build/{file_info.language}/{file_info.chapter}/{file_info.path.stem}'
build_result = env.C(build_target, str(file_info.path), LIBS='m')
env.Alias(str(file_info.chapter), build_result)
10 changes: 5 additions & 5 deletions contents/split-operator_method/code/c/SConscript
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Import('*')
from pathlib import Path
Import('files_to_compile env')

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

env.C(f'#/build/c/{dirname}', Glob('*.c'), LIBS=['m', 'fftw3'])
for file_info in files_to_compile:
build_target = f'#/build/{file_info.language}/{file_info.chapter}/{file_info.path.stem}'
build_result = env.C(build_target, str(file_info.path), LIBS=['m', 'fftw3'])
env.Alias(str(file_info.chapter), build_result)
10 changes: 5 additions & 5 deletions contents/split-operator_method/code/cpp/SConscript
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Import('*')
from pathlib import Path
Import('files_to_compile env')

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

env.CPlusPlus(f'#/build/cpp/{dirname}', Glob('*.cpp'), LIBS=['m', 'fftw3'])
for file_info in files_to_compile:
build_target = f'#/build/{file_info.language}/{file_info.chapter}/{file_info.path.stem}'
build_result = env.CPlusPlus(build_target, str(file_info.path), LIBS=['m', 'fftw3'])
env.Alias(str(file_info.chapter), build_result)
10 changes: 5 additions & 5 deletions sconscripts/asm-x64_SConscript
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Import('files_to_compile language env')
from pathlib import Path
Import('files_to_compile env')

for file in files_to_compile:
chapter_name = file.parent.parent.parent.stem
env.X64(f'#/build/{language}/{chapter_name}', str(file), LINKFLAGS='-no-pie')
for file_info in files_to_compile:
build_target = f'#/build/{file_info.language}/{file_info.chapter}/{file_info.path.stem}'
build_result = env.X64(build_target, str(file_info.path), LINKFLAGS='-no-pie')
env.Alias(str(file_info.chapter), build_result)
8 changes: 4 additions & 4 deletions sconscripts/c_SConscript
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Import('files_to_compile env')
from pathlib import Path

for file in files_to_compile:
chapter_name = file.parent.parent.parent.stem
env.C(f'#/build/c/{chapter_name}', str(file))
for file_info in files_to_compile:
build_target = f'#/build/{file_info.language}/{file_info.chapter}/{file_info.path.stem}'
build_result = env.C(build_target, str(file_info.path))
env.Alias(str(file_info.chapter), build_result)
8 changes: 4 additions & 4 deletions sconscripts/cpp_SConscript
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Import('files_to_compile env')
from pathlib import Path

for file in files_to_compile:
chapter_name = file.parent.parent.parent.stem
env.CPlusPlus(f'#/build/cpp/{chapter_name}', str(file))
for file_info in files_to_compile:
build_target = f'#/build/{file_info.language}/{file_info.chapter}/{file_info.path.stem}'
build_result = env.CPlusPlus(build_target, str(file_info.path))
env.Alias(str(file_info.chapter), build_result)
8 changes: 4 additions & 4 deletions sconscripts/fortran_SConscript
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Import('files_to_compile env')
from pathlib import Path

for file in files_to_compile:
chapter_name = file.parent.parent.parent.stem
env.Fortran(f'#/build/fortran/{chapter_name}', str(file))
for file_info in files_to_compile:
build_target = f'#/build/{file_info.language}/{file_info.chapter}/{file_info.path.stem}'
build_result = env.Fortran(build_target, str(file_info.path))
env.Alias(str(file_info.chapter), build_result)
8 changes: 4 additions & 4 deletions sconscripts/go_SConscript
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Import('files_to_compile env')
from pathlib import Path

for file in files_to_compile:
chapter_name = file.parent.parent.parent.stem
env.Go(f'#/build/go/{chapter_name}', str(file))
for file_info in files_to_compile:
build_target = f'#/build/{file_info.language}/{file_info.chapter}/{file_info.path.stem}'
build_result = env.Go(build_target, str(file_info.path))
env.Alias(str(file_info.chapter), build_result)
23 changes: 12 additions & 11 deletions sconscripts/rust_SConscript
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
Import('files_to_compile env')
from pathlib import Path

for file in files_to_compile:
chapter_name = file.parent.parent.parent.stem
if (file.parent / 'Cargo.toml').exists():
env.cargo(target=f'#/build/rust/{chapter_name}',
source=str(file),
MANIFEST=str(file.parent / 'Cargo.toml'),
SOURCE_DIR=str(file.parent))
env.Clean('rust', str(file.parent / 'target'))
for file_info in files_to_compile:
build_target = f'#/build/{file_info.language}/{file_info.chapter}/{file_info.path.stem}'
if (file_info.path.parent / 'Cargo.toml').exists():
build_result = env.cargo(target=build_target,
source=str(file_info.path),
MANIFEST=str(file_info.path.parent / 'Cargo.toml'),
SOURCE_DIR=str(file_info.path.parent))
env.Clean('rust', str(file_info.path.parent / 'target'))
else:
env.rustc(f'#/build/rust/{chapter_name}', str(file))
env.Clean('rust', f'#/build/rust/{chapter_name}.pdb')
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)