Compare commits
	
		
			7 commits
		
	
	
		
			master
			...
			site_scons
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 921890e0b2 | |||
| c9ff381f39 | |||
| d054006625 | |||
| 637cd2d664 | |||
| ee0808aa41 | |||
| 31a51b7ce9 | |||
| 42baed281a | 
					 10 changed files with 231 additions and 140 deletions
				
			
		
							
								
								
									
										183
									
								
								SConstruct
									
										
									
									
									
								
							
							
						
						
									
										183
									
								
								SConstruct
									
										
									
									
									
								
							|  | @ -27,149 +27,54 @@ CFLAGS = '-Wall -Wextra -pedantic' | |||
| # BUILD STUFF BELOW HERE | ||||
| # | ||||
| 
 | ||||
| import os | ||||
| import os.path | ||||
| import SCons.Errors | ||||
| 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)') | ||||
| 
 | ||||
| 
 | ||||
| def which(program): | ||||
|     def is_executable(path): | ||||
|         return 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 | ||||
| #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, | ||||
| #}) | ||||
| 
 | ||||
| 
 | ||||
| def get_bool_argument(arg): | ||||
| for mode in GetOption('modes'): | ||||
|     try: | ||||
|         return bool(int(arg)) | ||||
|     except ValueError: | ||||
|         pass | ||||
|     if arg in ('False', 'FALSE', 'false', ''): | ||||
|         return False | ||||
|     return True | ||||
| 
 | ||||
| 
 | ||||
| def set_toolchain_binary(env, var, user_binary, binaries=()): | ||||
|     if user_binary and which(user_binary): | ||||
|         env[var] = user_binary | ||||
|         return | ||||
|     for c in binaries: | ||||
|         if which(c): | ||||
|             env[var] = c | ||||
|             break | ||||
| 
 | ||||
| common_env = Environment() | ||||
| set_toolchain_binary(common_env, 'CC', CC, ('clang', 'gcc')) | ||||
| set_toolchain_binary(common_env, 'CXX', CXX, ('clang++', 'g++')) | ||||
| set_toolchain_binary(common_env, 'AS', AS) | ||||
| set_toolchain_binary(common_env, 'LINK', LINK) | ||||
| common_env.Append(CFLAGS='{} -std=c99'.format(CFLAGS)) | ||||
| common_env.Append(CXXFLAGS='{} -std=c++11'.format(CFLAGS)) | ||||
| 
 | ||||
| # Add color error messages for clang | ||||
| if 'clang' in common_env['CC']: | ||||
|     common_env.Append(CFLAGS=' -fcolor-diagnostics') | ||||
| if 'clang' in common_env['CXX']: | ||||
|     common_env.Append(CXXFLAGS=' -fcolor-diagnostics') | ||||
| 
 | ||||
| BUILD_CMDS = get_bool_argument(ARGUMENTS.get('BUILD_CMDS', False)) | ||||
| if not BUILD_CMDS: | ||||
|     def generate_comstr(action): | ||||
|         return '{:>25}: $TARGET'.format(action) | ||||
|     common_env['ARCOMSTR'] = generate_comstr('Archiving') | ||||
|     common_env['ASCOMSTR'] = generate_comstr('Assembling') | ||||
|     common_env['ASPPCOMSTR'] = generate_comstr('Assembling') | ||||
|     common_env['CCCOMSTR'] = generate_comstr('Building (C)') | ||||
|     common_env['CXXCOMSTR'] = generate_comstr('Building (C++)') | ||||
|     common_env['LINKCOMSTR'] = generate_comstr('Linking') | ||||
|     common_env['RANLIBCOMSTR'] = generate_comstr('Indexing') | ||||
|     common_env['SHCCCOMSTR'] = generate_comstr('Building (C, Shared)') | ||||
|     common_env['SHCXXCOMSTR'] = generate_comstr('Building (C++, Shared)') | ||||
|     common_env['SHLINKCOMSTR'] = generate_comstr('Linking (Shared)') | ||||
| 
 | ||||
| build_dir = Dir('#build') | ||||
| lib_dir = Dir('#lib') | ||||
| src_dir = Dir('#src') | ||||
| test_dir = Dir('#test') | ||||
| 
 | ||||
| 
 | ||||
| def create_env(name, src_dirs, appends=None): | ||||
|     output_dir = build_dir.Dir(name) | ||||
|     env = common_env.Clone() | ||||
|     env['__name'] = name | ||||
|     env['__build_dir'] = output_dir | ||||
|     env['__src_dirs'] = [] | ||||
|     env['__output_dirs'] = [] | ||||
|     for d in src_dirs: | ||||
|         out_dir = output_dir.Dir(d.path) | ||||
|         env['__src_dirs'].append(d) | ||||
|         env['__output_dirs'].append(out_dir) | ||||
|         env.VariantDir(out_dir, d.path, duplicate=0) | ||||
|         env.Clean('.', out_dir) | ||||
|     if appends: | ||||
|         for k, v in appends.iteritems(): | ||||
|             if k.startswith('='): | ||||
|                 env[k[1:]] = v | ||||
|             else: | ||||
|                 env.Append(**{k: v}) | ||||
|     return env | ||||
| 
 | ||||
| 
 | ||||
| debug_cflags = ' -O0 -g' | ||||
| debug_env = create_env('debug', [src_dir], { | ||||
|     'CPPDEFINES': ['DEBUG'], | ||||
|     'CFLAGS': debug_cflags, | ||||
|     'CXXFLAGS': debug_cflags, | ||||
| }) | ||||
| 
 | ||||
| release_cflags = ' -O2' | ||||
| release_env = create_env('release', [src_dir], { | ||||
|     'CPPDEFINES': ['RELEASE'], | ||||
|     'CFLAGS': release_cflags, | ||||
|     'CXXFLAGS': release_cflags, | ||||
| }) | ||||
| 
 | ||||
| test_gtest_dir = Dir('#lib/gtest') | ||||
| test_cpppath = test_gtest_dir.Dir('include') | ||||
| test_env = create_env('test', [src_dir, test_dir, test_gtest_dir], { | ||||
|     'CPPDEFINES': ['DEBUG'], | ||||
|     'CPPPATH': [test_cpppath], | ||||
|     'LIBPATH': [test_gtest_dir], | ||||
|     'CFLAGS': debug_cflags, | ||||
|     'CXXFLAGS': debug_cflags, | ||||
| }) | ||||
| 
 | ||||
| 
 | ||||
| modes = { | ||||
|     'debug': debug_env, | ||||
|     'release': release_env, | ||||
|     'test': test_env, | ||||
| } | ||||
| 
 | ||||
| mode = ARGUMENTS.get('MODE', None) | ||||
| build_modes = [] | ||||
| if mode: | ||||
|     # If MODE=foo is specified, build only that mode. | ||||
|     build_modes.append(mode) | ||||
| else: | ||||
|     build_modes = modes.keys() | ||||
| 
 | ||||
| for mode in build_modes: | ||||
|     try: | ||||
|         env = modes[mode] | ||||
|         env = MODES[mode] | ||||
|     except KeyError: | ||||
|         print 'Skipping invalid mode: {}'.format(mode) | ||||
|     for d in env['__output_dirs']: | ||||
|         env.SConscript(d.File('SConscript'), {'env': env}) | ||||
| 
 | ||||
|     # 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 | ||||
|  | @ -25,4 +25,6 @@ for f in files: | |||
| 
 | ||||
| env.Append(CPPPATH=[Dir('include').srcnode()]) | ||||
| 
 | ||||
| gtest = env.Library('gtest', objs) | ||||
| gtest_static = env.Library('gtest', [env.StaticObject(f) for f in files]) | ||||
| gtest_dynamic = None | ||||
| Return('gtest_static gtest_dynamic') | ||||
|  |  | |||
							
								
								
									
										1
									
								
								site_scons/.gitignore
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								site_scons/.gitignore
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1 @@ | |||
| *.pyc | ||||
							
								
								
									
										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') | ||||
							
								
								
									
										71
									
								
								site_scons/site_init.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								site_scons/site_init.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +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 os.path | ||||
| import SCons.Defaults | ||||
| from dirs import * | ||||
| 
 | ||||
| 
 | ||||
| # | ||||
| # Environment Configuration | ||||
| # | ||||
| 
 | ||||
| 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 | ||||
| } | ||||
| 
 | ||||
| # | ||||
| # Command Line Options | ||||
| # | ||||
| 
 | ||||
| def process_modes_option(option, opt, value, parser): | ||||
|     modes = value.split(',') | ||||
|     for m in modes: | ||||
|         setattr(parser.values, 'modes', set(modes)) | ||||
| 
 | ||||
| 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'] | ||||
|  | @ -18,8 +18,15 @@ for d in subdirs: | |||
| 
 | ||||
| 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') | ||||
|  |  | |||
|  | @ -23,3 +23,5 @@ files = [ | |||
| 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