Compare commits
7 commits
master
...
site_scons
Author | SHA1 | Date | |
---|---|---|---|
921890e0b2 | |||
c9ff381f39 | |||
d054006625 | |||
637cd2d664 | |||
ee0808aa41 | |||
31a51b7ce9 | |||
42baed281a |
16 changed files with 306 additions and 507 deletions
85
SConstruct
85
SConstruct
|
@ -1,21 +1,80 @@
|
|||
# SConstruct
|
||||
# vim: set ft=python:
|
||||
#
|
||||
# Toplevel Scons build script. This should be mostly complete and generic enough
|
||||
# for most builds.
|
||||
#
|
||||
# Eryn Wells <eryn@erynwells.me>
|
||||
|
||||
'''
|
||||
Toplevel Scons build script. This should be mostly complete and generic enough
|
||||
for most builds.
|
||||
'''
|
||||
|
||||
import logging
|
||||
#
|
||||
# DEFAULT CONFIGURATION VALUES
|
||||
#
|
||||
|
||||
setup_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
|
||||
|
||||
BUILD_CMDS = get_bool_argument(ARGUMENTS.get('BUILD_CMDS', False))
|
||||
MODE = ARGUMENTS.get('MODE', None)
|
||||
# Same as above but for default CFLAGS. These are appended to both CFLAGS and
|
||||
# CXXFLAGS.
|
||||
CFLAGS = '-Wall -Wextra -pedantic'
|
||||
|
||||
for mode in (MODE.split(',') if MODE else ['debug']):
|
||||
env = Environment.for_mode(mode)
|
||||
env.process_lib_dirs()
|
||||
env.process_src()
|
||||
env.process_tests()
|
||||
|
||||
#
|
||||
# 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
|
||||
|
|
24
lib/SConscript
Normal file
24
lib/SConscript
Normal file
|
@ -0,0 +1,24 @@
|
|||
# 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 <eryn@erynwells.me>
|
||||
|
||||
|
||||
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
|
|
@ -1,8 +1,14 @@
|
|||
# SConscript
|
||||
# vim: set ft=python:
|
||||
#
|
||||
# Eryn Wells <eryn@erynwells.me>
|
||||
|
||||
Library('gtest', [
|
||||
import os.path
|
||||
|
||||
Import('env')
|
||||
|
||||
|
||||
files = [
|
||||
'gtest-all.cc',
|
||||
'gtest-death-test.cc',
|
||||
'gtest-filepath.cc',
|
||||
|
@ -11,5 +17,14 @@ Library('gtest', [
|
|||
'gtest-test-part.cc',
|
||||
'gtest-typed-test.cc',
|
||||
'gtest.cc',
|
||||
'gtest_main.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')
|
||||
|
|
42
site_scons/binaries.py
Normal file
42
site_scons/binaries.py
Normal file
|
@ -0,0 +1,42 @@
|
|||
# files.py
|
||||
#
|
||||
# Utilities for working with files and paths in SCons.
|
||||
#
|
||||
# Eryn Wells <eryn@erynwells.me>
|
||||
|
||||
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
|
9
site_scons/dirs.py
Normal file
9
site_scons/dirs.py
Normal file
|
@ -0,0 +1,9 @@
|
|||
# dirs.py
|
||||
# Eryn Wells <eryn@erynwells.me>
|
||||
|
||||
from SCons.Script import Dir
|
||||
|
||||
BUILD_DIR = Dir('#build')
|
||||
LIB_DIR = Dir('#lib')
|
||||
SRC_DIR = Dir('#src')
|
||||
TEST_DIR = Dir('#test')
|
|
@ -1,210 +1,71 @@
|
|||
# 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 <eryn@erynwells.me>
|
||||
|
||||
import logging
|
||||
import sys
|
||||
import SCons.Environment
|
||||
import SCons.Errors
|
||||
import os.path
|
||||
import SCons.Defaults
|
||||
from dirs import *
|
||||
|
||||
|
||||
def setup_logging(level=logging.DEBUG):
|
||||
'''Configure global logging for the SCons system.'''
|
||||
root = logging.getLogger()
|
||||
root.setLevel(logging.DEBUG)
|
||||
root.addHandler(logging.StreamHandler())
|
||||
|
||||
#
|
||||
# Argument utils
|
||||
# Environment Configuration
|
||||
#
|
||||
|
||||
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'
|
||||
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
|
||||
}
|
||||
|
||||
#
|
||||
# Builders
|
||||
# Command Line Options
|
||||
#
|
||||
|
||||
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
|
||||
def process_modes_option(option, opt, value, parser):
|
||||
modes = value.split(',')
|
||||
for m in modes:
|
||||
setattr(parser.values, 'modes', set(modes))
|
||||
|
||||
#
|
||||
# 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'])
|
||||
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())))
|
||||
|
|
28
site_scons/site_tools/gtest/__init__.py
Normal file
28
site_scons/site_tools/gtest/__init__.py
Normal file
|
@ -0,0 +1,28 @@
|
|||
# gtestprogram.py
|
||||
# Eryn Wells <eryn@erynwells.me>
|
||||
|
||||
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']
|
|
@ -1,81 +0,0 @@
|
|||
# lib.py
|
||||
# Eryn Wells <eryn@erynwells.me>
|
||||
|
||||
'''
|
||||
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
|
|
@ -1,36 +0,0 @@
|
|||
# osxapp.py
|
||||
# Eryn Wells <eryn@erynwells.me>
|
||||
|
||||
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
|
|
@ -1,46 +0,0 @@
|
|||
# program.py
|
||||
# Eryn Wells <eryn@erynwells.me>
|
||||
|
||||
'''
|
||||
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
|
|
@ -1,38 +0,0 @@
|
|||
# sconscript.py
|
||||
# Eryn Wells <eryn@erynwells.me>
|
||||
|
||||
'''
|
||||
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
|
|
@ -1,33 +0,0 @@
|
|||
# swiftc.py
|
||||
# vim: set ft=python:
|
||||
# Eryn Wells <eryn@erynwells.me>
|
||||
|
||||
'''
|
||||
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)
|
|
@ -1,51 +0,0 @@
|
|||
# test.py
|
||||
# Eryn Wells <eryn@erynwells.me>
|
||||
|
||||
'''
|
||||
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
|
|
@ -1,5 +1,32 @@
|
|||
# SConscript
|
||||
# vim: set ft=python:
|
||||
#
|
||||
# Eryn Wells <eryn@erynwells.me>
|
||||
|
||||
Program('hello', ['hello.cc'])
|
||||
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')
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
#include <iostream>
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
std::cout << "Hello world!" << std::endl;
|
||||
return 0;
|
||||
}
|
27
test/SConscript
Normal file
27
test/SConscript
Normal file
|
@ -0,0 +1,27 @@
|
|||
# SConscript
|
||||
# vim: set ft=python:
|
||||
#
|
||||
# Eryn Wells <eryn@erynwells.me>
|
||||
|
||||
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')
|
Loading…
Add table
Add a link
Reference in a new issue