diff --git a/SConstruct b/SConstruct index bbd54b4..48b0d84 100644 --- a/SConstruct +++ b/SConstruct @@ -1,80 +1,21 @@ # SConstruct # vim: set ft=python: -# -# Toplevel Scons build script. This should be mostly complete and generic enough -# for most builds. -# # Eryn Wells +''' +Toplevel Scons build script. This should be mostly complete and generic enough +for most builds. +''' -# -# DEFAULT CONFIGURATION VALUES -# +import logging -# Settings for the default toolchain binaries. Setting these overrides the -# defaults, provided your the given binary exists. -CC = None -CXX = None -AS = None -LINK = None +setup_logging() -# Same as above but for default CFLAGS. These are appended to both CFLAGS and -# CXXFLAGS. -CFLAGS = '-Wall -Wextra -pedantic' +BUILD_CMDS = get_bool_argument(ARGUMENTS.get('BUILD_CMDS', False)) +MODE = ARGUMENTS.get('MODE', None) - -# -# BUILD STUFF BELOW HERE -# - -if not GetOption('build_cmds'): - def comstr(action): - return '{:>18}: $TARGET'.format(action) - default_env = DefaultEnvironment() - default_env['ARCOMSTR'] = comstr('Archiving') - default_env['ASCOMSTR'] = comstr('Assembling') - default_env['ASPPCOMSTR'] = comstr('Assembling') - default_env['CCCOMSTR'] = comstr('Building (C)') - default_env['CXXCOMSTR'] = comstr('Building (C++)') - default_env['LINKCOMSTR'] = comstr('Linking') - default_env['RANLIBCOMSTR'] = comstr('Indexing') - default_env['SHCCCOMSTR'] = comstr('Building (C)') - default_env['SHCXXCOMSTR'] = comstr('Building (C++)') - default_env['SHLINKCOMSTR'] = comstr('Linking (Shared)') - - -#test_gtest_dir = Dir('#lib/gtest') -#test_gtest_include = test_gtest_dir.Dir('include') -#test_env = create_env('test', [src_dir, test_dir, test_gtest_dir], { -# 'CPPDEFINES': ['DEBUG'], -# 'CPPPATH': [test_gtest_include], -# 'LIBPATH': [test_gtest_dir], -# 'CFLAGS': debug_cflags, -# 'CXXFLAGS': debug_cflags, -#}) - - -for mode in GetOption('modes'): - try: - env = MODES[mode] - except KeyError: - print 'Skipping invalid mode: {}'.format(mode) - - # Process libraries - env.SConscript(LIB_DIR.File('SConscript'), { - 'env': env, - }, variant_dir=BUILD_DIR.Dir(env['MODE']).Dir('lib'), duplicate=0) - - # Process source - library, binary = env.SConscript(SRC_DIR.File('SConscript'), { - 'env': env - }, variant_dir=BUILD_DIR.Dir(env['MODE']).Dir('src'), duplicate=0) - env.Alias('lib', library) - env.Alias('bin', binary) - - env.SConscript(TEST_DIR.File('SConscript'), { - 'env': env, - }, variant_dir=BUILD_DIR.Dir(env['MODE']).Dir('test'), duplicate=0) - -Import('LIBS') -print LIBS +for mode in (MODE.split(',') if MODE else ['debug']): + env = Environment.for_mode(mode) + env.process_lib_dirs() + env.process_src() + env.process_tests() diff --git a/lib/SConscript b/lib/SConscript deleted file mode 100644 index 1e223b9..0000000 --- a/lib/SConscript +++ /dev/null @@ -1,24 +0,0 @@ -# SConscript -# -# SCons build script for libs in base. Aggregates static and shared libraries in -# these directories and exports them in the 'LIBS' variable. -# -# Eryn Wells - - -Import('env') - -dirs = ( - 'gtest', -) - -env['LIBS'] = {} -for d in dirs: - static, dynamic = env.SConscript(Dir(d).File('SConscript'), { - 'env': env, - }) - env['LIBS'][d] = {} - if static: - env['LIBS'][d]['static'] = static - if dynamic: - env['LIBS'][d]['dynamic'] = dynamic diff --git a/lib/gtest/SConscript b/lib/gtest/SConscript index a86241e..5d2e1c7 100644 --- a/lib/gtest/SConscript +++ b/lib/gtest/SConscript @@ -1,14 +1,8 @@ # SConscript # vim: set ft=python: -# # Eryn Wells -import os.path - -Import('env') - - -files = [ +Library('gtest', [ 'gtest-all.cc', 'gtest-death-test.cc', 'gtest-filepath.cc', @@ -17,14 +11,5 @@ files = [ 'gtest-test-part.cc', 'gtest-typed-test.cc', 'gtest.cc', -] - -objs = [] -for f in files: - objs.append(env.Object(f)) - -env.Append(CPPPATH=[Dir('include').srcnode()]) - -gtest_static = env.Library('gtest', [env.StaticObject(f) for f in files]) -gtest_dynamic = None -Return('gtest_static gtest_dynamic') + 'gtest_main.cc' +]) diff --git a/site_scons/binaries.py b/site_scons/binaries.py deleted file mode 100644 index b858376..0000000 --- a/site_scons/binaries.py +++ /dev/null @@ -1,42 +0,0 @@ -# files.py -# -# Utilities for working with files and paths in SCons. -# -# Eryn Wells - -import os - - -def which(program): - ''' - Given a program name, search the system environment's $PATH for a binary of - that name. If one exists, return its name. If not, return None. This - function will also use the system environment's $PATHEXT to find binaries - with appropriate extensions (i.e., .exe on Windows). - ''' - is_executable = lambda path: ( os.path.exists(path) - and os.access(path, os.X_OK)) - - path, name = os.path.split(program) - if path: - if is_executable(program): - return program - else: - pathext = [''] + os.environ.get('PATHEXT', '').split(os.pathsep) - for path in os.environ.get('PATH', '').split(os.pathsep): - exe = os.path.join(path, program) - for ext in pathext: - candidate = exe + ext - if is_executable(candidate): - return candidate - return None - - -def first(binaries): - ''' - Given a list of binaries, return the first one found. - ''' - for binary in binaries: - if which(binary): - return binary - return None diff --git a/site_scons/dirs.py b/site_scons/dirs.py deleted file mode 100644 index 7aa8751..0000000 --- a/site_scons/dirs.py +++ /dev/null @@ -1,9 +0,0 @@ -# dirs.py -# Eryn Wells - -from SCons.Script import Dir - -BUILD_DIR = Dir('#build') -LIB_DIR = Dir('#lib') -SRC_DIR = Dir('#src') -TEST_DIR = Dir('#test') diff --git a/site_scons/site_init.py b/site_scons/site_init.py index d296109..0c2f2ba 100644 --- a/site_scons/site_init.py +++ b/site_scons/site_init.py @@ -1,71 +1,210 @@ # site_init.py -# -# This file is read before every SConstruct and SConscript. So, anything that -# should be available to every build script should go here. -# # Eryn Wells -import os.path -import SCons.Defaults -from dirs import * +import logging +import sys +import SCons.Environment +import SCons.Errors +def setup_logging(level=logging.DEBUG): + '''Configure global logging for the SCons system.''' + root = logging.getLogger() + root.setLevel(logging.DEBUG) + root.addHandler(logging.StreamHandler()) + # -# Environment Configuration +# Argument utils # -def has_clang(env): - _, cc_tail = os.path.split(env['CC']) - _, cxx_tail = os.path.split(env['CXX']) - return all([cc_tail.startswith('clang'), cxx_tail.startswith('clang')]) - -default_env = SCons.Defaults.DefaultEnvironment() -default_env.Append(TOOLS=['gtest']) -print default_env.Dump() - -default_env.Replace( - CC=default_env.WhereIs('clang') or default_env.WhereIs('gcc'), - CXX=default_env.WhereIs('clang++') or default_env.WhereIs('gcc++')) - -default_env.Append(CCFLAGS=['-Wall', '-Wextra', '-pedantic'], - CFLAGS=['-std=c99'], - CXXFLAGS=['-std=c++11']) -if has_clang(default_env): - # Only clang supports color. - default_env.Append(CCFLAGS=['-fcolor-diagnostics']) - - -debug_env = default_env.Clone(MODE='debug', - CCFLAGS=['-O0', '-g'], - CPPDEFINES=['DEBUG']) -release_env = default_env.Clone(MODE='release', - CCFLAGS=['-O2'], - CPPDEFINES=['RELEASE']) - -MODES = { - 'debug': debug_env, - 'release': release_env -} +def get_bool_argument(arg): + ''' + Convert the given argument value to a bool. True values are any integer that + is considered true by Python, and any string value that isn't a + capitalization variant of the word "false". + ''' + try: + return bool(int(arg)) + except ValueError: + pass + return str(arg).lower() != 'false' # -# Command Line Options +# Builders # -def process_modes_option(option, opt, value, parser): - modes = value.split(',') - for m in modes: - setattr(parser.values, 'modes', set(modes)) +def program_builder(env): + original_builder = env.Program + def builder(env, prog_name, sources, *args, **kwargs): + return original_builder(prog_name, sources, *args, **kwargs) + return builder -AddOption('--show-build-cmds', - dest='build_cmds', - action='store_true', - help='Show build commands instead of friendly build messages') -AddOption('--modes', - type='string', - action='callback', - dest='modes', - metavar='MODES', - default=set(['debug']), - callback=process_modes_option, - help=('A comma separated list of modes. Choose from: {}. Default is ' - 'debug.').format(', '.join(MODES.keys()))) +# +# Environments +# + +class Environment(SCons.Environment.Environment): + ''' + Default SCons environment for building things. + ''' + + @classmethod + def _comstr(cls, action, succinct=True): + if succinct: + return '{:>25}: $TARGET'.format(action) + # Use the default *COMSTR. + return None + + @classmethod + def for_mode(cls, mode, name=None, succinct=True): + kwargs = {'succinct': succinct} + if name: + kwargs['name'] = name + mode_lower = mode.lower() + if mode_lower == 'debug': + return DebugEnvironment(**kwargs) + elif mode_lower == 'beta': + return BetaEnvironment(**kwargs) + elif mode_lower == 'release': + return ReleaseEnvironment(**kwargs) + raise SCons.Errors.UserError('Invalid mode: {}'.format(mode)) + + def __init__(self, name, modern=True, paranoid=True, colorful=True, succinct=True, **kwargs): + super(Environment, self).__init__(**self._append_custom_tools(kwargs)) + + self.SetDefault(NAME=name) + + self.SetDefault(LOGGER=logging.getLogger(name)) + + self.SetDefault(BUILD_ROOT=self.Dir('#build')) + self.SetDefault(LIB_ROOT=self.Dir('#lib')) + self.SetDefault(SRC_ROOT=self.Dir('#src')) + self.SetDefault(TEST_ROOT=self.Dir('#test')) + self.SetDefault(INCLUDE_ROOT=self.Dir('#include')) + + # Allow same directory includes. + self.AppendUnique(CPPPATH=['.']) + + self['CC'] = self.Detect(['clang', 'gcc']) + self['CXX'] = self.Detect(['clang++', 'g++']) + self['LINK'] = self.Detect(['clang++', 'clang', 'ld']) + + # Modern C/C++ + if modern: + self.AppendUnique(CFLAGS=['-std=c99']) + self.AppendUnique(CXXFLAGS=['-std=c++11']) + + # Paranoid C/C++ + if paranoid: + self.AppendUnique(CCFLAGS=['-Wall', '-Wextra', '-pedantic']) + + # Colorful C/C++ + if colorful and sys.stdout.isatty(): + if 'clang' in self['CC'] or 'clang' in self['CXX']: + self.AppendUnique(CCFLAGS=['-fcolor-diagnostics']) + elif 'gcc' in self['CC'] or 'g++' in self['CXX']: + # TODO: Also set a GCC_COLORS variable in the system environment? + self.AppendUnique(CCFLAGS=['-fdiagnostics-color=always']) + + # Pretty printing + self.SetDefault(ARCOMSTR=Environment._comstr('Archiving', succinct)) + self.SetDefault(ASCOMSTR=Environment._comstr('Assembling', succinct)) + self.SetDefault(ASPPCOMSTR=Environment._comstr('Assembling', succinct)) + self.SetDefault(CCCOMSTR=Environment._comstr('Building (C)', succinct)) + self.SetDefault(CXXCOMSTR=Environment._comstr('Building (C++)', succinct)) + self.SetDefault(LINKCOMSTR=Environment._comstr('Linking', succinct)) + self.SetDefault(RANLIBCOMSTR=Environment._comstr('Indexing', succinct)) + self.SetDefault(SHCCCOMSTR=Environment._comstr('Building (C, Shared)', succinct)) + self.SetDefault(SHCXXCOMSTR=Environment._comstr('Building (C++, Shared)', succinct)) + self.SetDefault(SHLINKCOMSTR=Environment._comstr('Linking (Shared)', succinct)) + + @property + def build_root(self): + '''Return the build output directory for this environment.''' + return self['BUILD_ROOT'].Dir(self['NAME']) + + @property + def lib_root(self): + '''Return the root directory for libraries for this environment.''' + return self['LIB_ROOT'] + + @property + def src_root(self): + '''Return the main source root directory for this environment.''' + return self['SRC_ROOT'] + + def process_src(self): + out_dir = self.build_root.Dir('src') + self.SConscript(self.src_root.File('SConscript'), + variant_dir=out_dir) + self.Append(CPPPATH=[self.src_root]) + + # + # Test processing + # + + def test_objects(self, name): + self._ensure_test_structure(name) + return self['TESTS'][name]['objects'] + + def test_program(self, name): + self._ensure_test_structure(name) + return self['TESTS'][name]['program'] + + def register_test_program(self, name, prog): + self._ensure_test_structure(name) + self['TESTS'][name]['program'] = prog + + def process_tests(self): + tests = [] + for test, struct in self['TESTS'].iteritems(): + if not struct['program']: + continue + tests.append(self.TestRun(test)) + self.Alias('test', tests) + + def _ensure_test_structure(self, name): + self['TESTS'].setdefault(name, {'program': None, 'objects': []}) + + # + # Logging + # + + def log(self, msg, *args, **kwargs): + self['LOGGER'].info(msg, *args, **kwargs) + + def log_debug(self, msg, *args, **kwargs): + self['LOGGER'].debug(msg, *args, **kwargs) + + def log_error(self, msg, *args, **kwargs): + self['LOGGER'].error(msg, *args, **kwargs) + + def _append_custom_tools(self, kwargs): + '''Add custom tools to the `kwargs`.''' + tools = kwargs.setdefault('tools', ['default']) + for tool in ['lib', 'test', 'program', 'sconscript', 'swiftc']: + if tool in tools: + continue + tools.append(tool) + return kwargs + + +class DebugEnvironment(Environment): + def __init__(self, name='debug', **kwargs): + super(DebugEnvironment, self).__init__(name, **kwargs) + self.Append(CPPDEFINES=['DEBUG']) + self.Append(CCFLAGS=['-O0', '-g']) + + +class BetaEnvironment(Environment): + def __init__(self, name='beta', **kwargs): + super(BetaEnvironment, self).__init__(name, **kwargs) + self.Append(CPPDEFINES=['DEBUG']) + self.Append(CCFLAGS=['-O3', '-g']) + + +class ReleaseEnvironment(Environment): + def __init__(self, name='release', **kwargs): + super(ReleaseEnvironment, self).__init__(name, **kwargs) + self.Append(CPPDEFINES=['NDEBUG', 'RELEASE']) + self.Append(CCFLAGS=['-O3']) diff --git a/site_scons/site_tools/gtest/__init__.py b/site_scons/site_tools/gtest/__init__.py deleted file mode 100644 index 4bb21ae..0000000 --- a/site_scons/site_tools/gtest/__init__.py +++ /dev/null @@ -1,28 +0,0 @@ -# gtestprogram.py -# Eryn Wells - -import SCons.Util -import dirs - - -def build_gtest_program(env, target, source=None, *args, **kwargs): - if not SCons.Util.is_List(source): - source = [source] - source.insert(0, dirs.LIB_DIR.Dir('gtest').File('gtest_main.cc')) - source.append(env['LIBS']['gtest']['static']) - return env.Program(target, source, *args, **kwargs) - - -def generate(env): - print 'gtestprogram generate()' - try: - env.AddMethod(build_gtest_program, 'GTestProgram') - except AttributeError: - # Old version of SCons - from SCons.Script.SConscript import SConsEnvironment - SConsEnvironment.GTestProgram = build_gtest_program - - -def exists(env): - print 'gtestprogram exists()' - return 'gtest' in env['LIBS'] diff --git a/site_scons/site_tools/lib.py b/site_scons/site_tools/lib.py new file mode 100644 index 0000000..dd47f61 --- /dev/null +++ b/site_scons/site_tools/lib.py @@ -0,0 +1,81 @@ +# lib.py +# Eryn Wells + +''' +SCons builder for a lib directory. +''' + +import os + +import SCons.Errors +import SCons.Script + + +def _lib(env, name): + return env['LOCAL_LIBS'].get(name) + + +def _register_lib(env, name, lib): + if name in env['LOCAL_LIBS']: + env.log_error('Library has already been built: {}'.format(name)) + env['LOCAL_LIBS'][name] = lib + + +def _lib_dirs(env): + for lib in os.listdir(env.lib_root.abspath): + lib_dir = env.lib_root.Dir(lib) + if not lib_dir.isdir(): + continue + yield (lib, lib_dir) + + +def _process_lib_dirs(env): + for name, _ in _lib_dirs(env): + env.LibDir(name) + + +def _process_lib_dir(env, lib, src_dir=None, out_dir=None, inc_dir=None): + if not src_dir: + src_dir = env.lib_root.Dir(lib) + if not src_dir.isdir(): + err = 'Invalid library source directory: {}'.format(src_dir) + env.log_error(err) + raise SCons.Errors.UserError(err) + if not out_dir: + out_dir = env.build_root.Dir('lib').Dir(lib) + if not inc_dir: + include_dir = src_dir.Dir('include') + if include_dir.isdir(): + inc_dir = [include_dir] + env.Append(CPPPATH=inc_dir) + out = env.SConscript(src_dir.File('SConscript'), + clone=True, + variant_dir=out_dir) + return out + + +def _build_library(env, lib_func): + original_builder = lib_func + + def builder(env, lib_name, sources, *args, **kwargs): + lib = original_builder(lib_name, sources, *args, **kwargs) + _register_lib(env, lib_name, lib) + return lib + + return builder + +# +# SCons tool interface +# + +def generate(env): + env.SetDefault(LOCAL_LIBS={}) + env.AddMethod(_process_lib_dir, 'LibDir') + env.AddMethod(_build_library(env, env.Library), 'Library') + env.AddMethod(_build_library(env, env.StaticLibrary), 'StaticLibrary') + env.AddMethod(_build_library(env, env.SharedLibrary), 'SharedLibrary') + env.AddMethod(_lib, 'lib') + env.AddMethod(_process_lib_dirs, 'process_lib_dirs') + +def exists(env): + return True diff --git a/site_scons/site_tools/osxapp.py b/site_scons/site_tools/osxapp.py new file mode 100644 index 0000000..e56a795 --- /dev/null +++ b/site_scons/site_tools/osxapp.py @@ -0,0 +1,36 @@ +# osxapp.py +# Eryn Wells + +import os.path + +_BUNDLE_SUFFIX = '.app' + + +def _assemble_app_bundle(env, bundle_name, binary, info_plist, resources_dir): + # TODO: Create directory structure, copy binary, plist, and resources. Sign the binary? app bundle? + + if not bundle_name.endswith('.app'): + bundle_name += '.app' + + bundle_dir = env.Dir(bundle_name) + contents_dir = bundle_dir.Dir('Contents') + macos_dir = contents_dir.Dir('MacOS') + resources_dir = contents_dir.Dir('Resources') + + return [env.Mkdir(contents_dir), + env.Copy(contents_dir.File('Info.plist'), info_list), + env.Mkdir(macos_dir), + env.Copy(macos_dir.File(bundle_name), binary) + + +_app_builder = Builder(action=_assemble_app_bundle, + suffix=_BUNDLE_SUFFIX) + + +def generate(env): + env['OSXAPPBUNDLESUFFIX'] = _BUNDLE_SUFFIX + env['BUILDERS']['OSXApp'] = _app_builder + + +def exists(env): + return True diff --git a/site_scons/site_tools/program.py b/site_scons/site_tools/program.py new file mode 100644 index 0000000..21bbddf --- /dev/null +++ b/site_scons/site_tools/program.py @@ -0,0 +1,46 @@ +# program.py +# Eryn Wells + +''' +SCons tool for working with Programs. +''' + +def _program(env, name): + return env['PROGRAMS'].get(name) + + +def _register_program(env, name, program): + env['PROGRAMS'][name] = program + + +def _build_program(env): + original_builder = env.Program + + def builder(env, name, sources, local_libs=None, *args, **kwargs): + # local_libs is an array of names of libs built in the local project. + # These will be looked up in the environment and added to the LIBS + # array, if present. +# if local_libs: +# local_libs = map(lambda lib: env.lib(lib), local_libs) +# try: +# kwargs['LIBS'].extend(local_libs) +# except KeyError: +# kwargs['LIBS'] = local_libs + prog = original_builder(name, sources, *args, **kwargs) + _register_program(env, name, prog) + return prog + + return builder + +# +# SCons tool interface +# + +def generate(env): + env.SetDefault(PROGRAMS={}) + env.AddMethod(_build_program(env), 'Program') + env.AddMethod(_program, 'program') + + +def exists(env): + return True diff --git a/site_scons/site_tools/sconscript.py b/site_scons/site_tools/sconscript.py new file mode 100644 index 0000000..3e9b597 --- /dev/null +++ b/site_scons/site_tools/sconscript.py @@ -0,0 +1,38 @@ +# sconscript.py +# Eryn Wells + +''' +SCons tool for working with SConscripts. +''' + +import SCons.Script + +def _do_sconscript(env): + original_sconscript = env.SConscript + + def sconscript(env, sconscript, clone=False, *args, **kwargs): + exports = { + 'Library': env.Library, + 'Object': env.Object, + 'SharedObject': env.SharedObject, + 'StaticLibrary': env.StaticLibrary, + 'SharedLibrary': env.SharedLibrary, + 'Program': env.Program, + 'env': env.Clone() if clone else env, + } + SCons.Script._SConscript.GlobalDict.update(exports) + env.log('Reading {}'.format(sconscript)) + return original_sconscript(sconscript, {}, *args, **kwargs) + + return sconscript + +# +# SCons tool interface +# + +def generate(env): + env.AddMethod(_do_sconscript(env), 'SConscript') + + +def exists(env): + return True diff --git a/site_scons/site_tools/swiftc.py b/site_scons/site_tools/swiftc.py new file mode 100644 index 0000000..5d2766d --- /dev/null +++ b/site_scons/site_tools/swiftc.py @@ -0,0 +1,33 @@ +# swiftc.py +# vim: set ft=python: +# Eryn Wells + +''' +SCons plugin for building Swift files with swiftc. +''' + +import SCons.Action +import SCons.Tool +import SCons.Util + +SwiftSuffix = '.swift' +SwiftAction = SCons.Action.Action("$SWIFTCCOM", "$SWIFTCCOMSTR") + +compilers = ['swiftc'] + +def generate(env): + static_obj, shared_obj = SCons.Tool.createObjBuilders(env) + static_obj.add_action(SwiftSuffix, SwiftAction) + static_obj.add_emitter(SwiftSuffix, SCons.Defaults.SharedObjectEmitter) + shared_obj.add_action(SwiftSuffix, SwiftAction) + shared_obj.add_emitter(SwiftSuffix, SCons.Defaults.SharedObjectEmitter) + + if 'SWIFTC' not in env: + compiler = env.Detect(compilers) + env['SWIFTC'] = compiler if compiler else compilers[0] + env['SWIFTFLAGS'] = SCons.Util.CLVar('') + env['SWIFTCCOM'] = '$SWIFTC -o $TARGET -c $SWIFTFLAGS $SOURCES' + env['SWIFTFILESUFFIX'] = SwiftSuffix + +def exists(env): + return env.Detect(compilers) diff --git a/site_scons/site_tools/test.py b/site_scons/site_tools/test.py new file mode 100644 index 0000000..df8e924 --- /dev/null +++ b/site_scons/site_tools/test.py @@ -0,0 +1,51 @@ +# test.py +# Eryn Wells + +''' +Test builder for SCons. Test files are compiled to objects and stored in the +environment. +''' + +def _process_test_dir(env, dir, program=None): + # TODO: Builder for test directories? + pass + + +def _build_test_object(env, source, program=None): + obj = env.Object(source) + if not program: + program = 'test' + try: + env.test_objects(program).extend(obj) + except TypeError: + env.test_objects(program).append(obj) + return obj + + +def _build_test_program(env, name=None): + if not name: + name = 'test' + prog = env.Program(name, env.test_objects(name), LIBS=[env.lib('gtest')]) + env.register_test_program(name, prog) + return + + +def _run_tests(env, name=None): + if not name: + name = 'test' + cmd = env.Command(env.test_program(name), None, '$SOURCE --gtest_color=yes') + env.AlwaysBuild(cmd) + return cmd + +# +# SCons tool interface +# + +def generate(env): + env.SetDefault(TESTS={}) + env.AddMethod(_build_test_object, 'Test') + env.AddMethod(_build_test_program, 'TestProgram') + env.AddMethod(_run_tests, 'TestRun') + +def exists(env): + return 'Object' in env diff --git a/src/SConscript b/src/SConscript index 9e2c37e..5d9a22e 100644 --- a/src/SConscript +++ b/src/SConscript @@ -1,32 +1,5 @@ # SConscript # vim: set ft=python: -# # Eryn Wells -import os.path - -Import('env') - - -subdirs = [ - # TODO: Put subdirectories here. -] - -for d in subdirs: - env.SConscript(os.path.join(d, 'SConscript'), {'env': env}) - - -files = [ - # TODO: Put files here. - #'hello.cc', -] - -objs = [] -for f in files: - objs.append(env.Object(f)) - -#lib = env.Library('hello', files) -#prog = env.Program('hello', lib) -lib = None -prog = None -Return('prog lib') +Program('hello', ['hello.cc']) diff --git a/src/hello.cc b/src/hello.cc new file mode 100644 index 0000000..b02d2e0 --- /dev/null +++ b/src/hello.cc @@ -0,0 +1,8 @@ +#include + +int +main() +{ + std::cout << "Hello world!" << std::endl; + return 0; +} diff --git a/test/SConscript b/test/SConscript deleted file mode 100644 index e46f7bc..0000000 --- a/test/SConscript +++ /dev/null @@ -1,27 +0,0 @@ -# SConscript -# vim: set ft=python: -# -# Eryn Wells - -import os.path - -Import('env') - - -subdirs = [ - # TODO: Put subdirectories here. -] - -for d in subdirs: - env.SConscript(os.path.join(d, 'SConscript'), {'env': env}) - - -files = [ - # TODO: Put files here. -] - -objs = [] -for f in files: - objs.append(env.Object(f)) - -env.GTestProgram('test_hello', 'test_hello.cc')