diff --git a/SConstruct b/SConstruct index bb2bb85..41b467e 100644 --- a/SConstruct +++ b/SConstruct @@ -4,10 +4,13 @@ import os.path import platform import sys +default_install_dir='/usr/local' +if platform.system() == 'Windows': + default_install_dir = 'build' # no obvious place for installation on Windows vars = Variables(None, ARGUMENTS) -vars.Add(PathVariable('DESTDIR', "Root directory to install in (useful for packaging scripts)", None, PathVariable.PathIsDirCreate)) -vars.Add(PathVariable('prefix', "Where to install in the FHS", "/usr/local", PathVariable.PathAccept)) +vars.Add(PathVariable('DESTDIR', 'Root directory to install in (useful for packaging scripts)', None, PathVariable.PathIsDirCreate)) +vars.Add(PathVariable('prefix', 'Where to install in the FHS', default_install_dir, PathVariable.PathAccept)) vars.Add(ListVariable('bindings', 'Language bindings to build', 'none', ['cpp', 'dotnet', 'perl', 'php', 'python', 'ruby'])) tools = ['default', 'scanreplace'] @@ -17,6 +20,9 @@ if 'dotnet' in ARGUMENTS.get('bindings', []): envvars = {'PATH' : os.environ['PATH']} if 'PKG_CONFIG_PATH' in os.environ: envvars['PKG_CONFIG_PATH'] = os.environ['PKG_CONFIG_PATH'] +if platform.system() == 'Windows': + # from the scons FAQ (keywords: LNK1104 TEMPFILE), needed by link.exe + envvars['TMP'] = os.environ['TMP'] env = Environment(ENV = envvars, variables = vars, @@ -29,7 +35,7 @@ if not 'bindings' in env: def calcInstallPath(*elements): path = os.path.abspath(os.path.join(*map(env.subst, elements))) if 'DESTDIR' in env: - path = os.path.join(env['DESTDIR'], os.path.relpath(path, start="/")) + path = os.path.join(env['DESTDIR'], os.path.relpath(path, start='/')) return path rel_prefix = not os.path.isabs(env['prefix']) @@ -37,102 +43,131 @@ env['prefix'] = os.path.abspath(env['prefix']) if 'DESTDIR' in env: env['DESTDIR'] = os.path.abspath(env['DESTDIR']) if rel_prefix: - print >>sys.stderr, "--!!-- You used a relative prefix with a DESTDIR. This is probably not what you" - print >>sys.stderr, "--!!-- you want; files will be installed in" - print >>sys.stderr, "--!!-- %s" % (calcInstallPath("$prefix"),) + print >>sys.stderr, '--!!-- You used a relative prefix with a DESTDIR. This is probably not what you' + print >>sys.stderr, '--!!-- you want; files will be installed in' + print >>sys.stderr, '--!!-- %s' % (calcInstallPath('$prefix'),) -env['libpath'] = calcInstallPath("$prefix", "lib") -env['incpath'] = calcInstallPath("$prefix", "include", "hammer") -env['parsersincpath'] = calcInstallPath("$prefix", "include", "hammer", "parsers") -env['backendsincpath'] = calcInstallPath("$prefix", "include", "hammer", "backends") -env['pkgconfigpath'] = calcInstallPath("$prefix", "lib", "pkgconfig") +env['libpath'] = calcInstallPath('$prefix', 'lib') +env['incpath'] = calcInstallPath('$prefix', 'include', 'hammer') +env['parsersincpath'] = calcInstallPath('$prefix', 'include', 'hammer', 'parsers') +env['backendsincpath'] = calcInstallPath('$prefix', 'include', 'hammer', 'backends') +env['pkgconfigpath'] = calcInstallPath('$prefix', 'lib', 'pkgconfig') env.ScanReplace('libhammer.pc.in') -env.MergeFlags("-std=gnu99 -Wall -Wextra -Werror -Wno-unused-parameter -Wno-attributes -Wno-unused-variable") +AddOption('--variant', + dest='variant', + nargs=1, type='choice', + choices=['debug', 'opt'], + default='opt', + action='store', + help='Build variant (debug or opt)') +AddOption('--coverage', + dest='coverage', + default=False, + action='store_true', + help='Build with coverage instrumentation') + +AddOption('--in-place', + dest='in_place', + default=False, + action='store_true', + help='Build in-place, rather than in the build/ tree') + +AddOption('--tests', + dest='with_tests', + default=env['PLATFORM'] != 'win32', + action='store_true', + help='Build tests') + +env['CC'] = os.getenv('CC') or env['CC'] +env['CXX'] = os.getenv('CXX') or env['CXX'] + +if os.getenv('CC') == 'clang' or env['PLATFORM'] == 'darwin': + env.Replace(CC='clang', + CXX='clang++') + +# Language standard and warnings +if env['CC'] == 'cl': + env.MergeFlags('-W3 -WX') + env.Append( + CPPDEFINES=[ + '_CRT_SECURE_NO_WARNINGS' # allow uses of sprintf + ], + CFLAGS=[ + '-wd4018', # 'expression' : signed/unsigned mismatch + '-wd4244', # 'argument' : conversion from 'type1' to 'type2', possible loss of data + '-wd4267', # 'var' : conversion from 'size_t' to 'type', possible loss of data + ] + ) +else: + env.MergeFlags('-std=gnu99 -Wall -Wextra -Werror -Wno-unused-parameter -Wno-attributes -Wno-unused-variable') + +# Linker options if env['PLATFORM'] == 'darwin': - env.Append(SHLINKFLAGS = '-install_name ' + env["libpath"] + '/${TARGET.file}') -elif os.uname()[0] == "OpenBSD": + env.Append(SHLINKFLAGS = '-install_name ' + env['libpath'] + '/${TARGET.file}') +elif platform.system() == 'OpenBSD': + pass +elif env['PLATFORM'] == 'win32': + # no extra lib needed pass else: - env.MergeFlags("-lrt") + env.MergeFlags('-lrt') -AddOption("--variant", - dest="variant", - nargs=1, type="choice", - choices=["debug", "opt"], - default="opt", - action="store", - help="Build variant (debug or opt)") - -AddOption("--coverage", - dest="coverage", - default=False, - action="store_true", - help="Build with coverage instrumentation") - -AddOption("--in-place", - dest="in_place", - default=False, - action="store_true", - help="Build in-place, rather than in the build/ tree") - - -dbg = env.Clone(VARIANT='debug') -dbg.Append(CCFLAGS=['-g']) - -opt = env.Clone(VARIANT='opt') -opt.Append(CCFLAGS=["-O3"]) - -if GetOption("variant") == 'debug': - env = dbg -else: - env = opt - -env["CC"] = os.getenv("CC") or env["CC"] -env["CXX"] = os.getenv("CXX") or env["CXX"] - -if GetOption("coverage"): - env.Append(CFLAGS=["--coverage"], - CXXFLAGS=["--coverage"], - LDFLAGS=["--coverage"]) - if env["CC"] == "gcc": +if GetOption('coverage'): + env.Append(CFLAGS=['--coverage'], + CXXFLAGS=['--coverage'], + LDFLAGS=['--coverage']) + if env['CC'] == 'gcc': env.Append(LIBS=['gcov']) else: env.ParseConfig('llvm-config --ldflags') -if os.getenv("CC") == "clang" or env['PLATFORM'] == 'darwin': - env.Replace(CC="clang", - CXX="clang++") +dbg = env.Clone(VARIANT='debug') +if env['CC'] == 'cl': + dbg.Append(CCFLAGS=['/Z7']) +else: + dbg.Append(CCFLAGS=['-g']) -env["ENV"].update(x for x in os.environ.items() if x[0].startswith("CCC_")) +opt = env.Clone(VARIANT='opt') +if env['CC'] == 'cl': + opt.Append(CCFLAGS=['/O2']) +else: + opt.Append(CCFLAGS=['-O3']) + +if GetOption('variant') == 'debug': + env = dbg +else: + env = opt + +env['ENV'].update(x for x in os.environ.items() if x[0].startswith('CCC_')) #rootpath = env['ROOTPATH'] = os.path.abspath('.') -#env.Append(CPPPATH=os.path.join('#', "hammer")) +#env.Append(CPPPATH=os.path.join('#', 'hammer')) testruns = [] -targets = ["$libpath", - "$incpath", - "$parsersincpath", - "$backendsincpath", - "$pkgconfigpath"] +targets = ['$libpath', + '$incpath', + '$parsersincpath', + '$backendsincpath', + '$pkgconfigpath'] Export('env') Export('testruns') Export('targets') -if not GetOption("in_place"): +if not GetOption('in_place'): env['BUILD_BASE'] = 'build/$VARIANT' - lib = env.SConscript(["src/SConscript"], variant_dir='$BUILD_BASE/src') - env.Alias("examples", env.SConscript(["examples/SConscript"], variant_dir='$BUILD_BASE/examples')) + lib = env.SConscript(['src/SConscript'], variant_dir='$BUILD_BASE/src') + env.Alias('examples', env.SConscript(['examples/SConscript'], variant_dir='$BUILD_BASE/examples')) else: env['BUILD_BASE'] = '.' - lib = env.SConscript(["src/SConscript"]) - env.Alias(env.SConscript(["examples/SConscript"])) + lib = env.SConscript(['src/SConscript']) + env.Alias(env.SConscript(['examples/SConscript'])) for testrun in testruns: - env.Alias("test", testrun) + env.Alias('test', testrun) -env.Alias("install", targets) +env.Alias('install', targets) diff --git a/appveyor.yml b/appveyor.yml index b0d87a7..16aa8e8 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,9 +1,16 @@ platform: - x86 - x64 +environment: + PYTHON: "C:\\Python27" version: 1.0.{build} os: Visual Studio 2015 +install: + - SET "PATH=%PYTHON%;%PYTHON%\\Scripts;%PATH%" + - easy_install scons build_script: +- scons --version +- scons install - '@echo off' - setlocal - ps: >- diff --git a/src/SConscript b/src/SConscript index 7a1b9d4..a46ddac 100644 --- a/src/SConscript +++ b/src/SConscript @@ -1,23 +1,24 @@ # -*- python -*- import os.path + Import('env testruns') dist_headers = [ - "hammer.h", - "allocator.h", - "compiler_specifics.h", - "glue.h", - "internal.h", - "platform.h" + 'hammer.h', + 'allocator.h', + 'compiler_specifics.h', + 'glue.h', + 'internal.h', + 'platform.h' ] parsers_headers = [ - "parsers/parser_internal.h" + 'parsers/parser_internal.h' ] backends_headers = [ - "backends/regex.h", - "backends/contextfree.h" + 'backends/regex.h', + 'backends/contextfree.h' ] parsers = ['parsers/%s.c'%s for s in @@ -48,7 +49,7 @@ parsers = ['parsers/%s.c'%s for s in 'unimplemented', 'whitespace', 'xor', - 'value']] + 'value']] backends = ['backends/%s.c' % s for s in ['packrat', 'llk', 'regex', 'glr', 'lalr', 'lr', 'lr0']] @@ -63,11 +64,18 @@ misc_hammer_parts = [ 'desugar.c', 'glue.c', 'hammer.c', - 'platform_bsdlike.c', 'pprint.c', 'registry.c', 'system_allocator.c'] +if env['PLATFORM'] == 'win32': + misc_hammer_parts += [ + 'platform_win32.c', + 'tsearch.c', + ] +else: + misc_hammer_parts += ['platform_bsdlike.c'] + ctests = ['t_benchmark.c', 't_bitreader.c', 't_bitwriter.c', @@ -76,26 +84,40 @@ ctests = ['t_benchmark.c', 't_misc.c', 't_regression.c'] + +static_library_name = 'hammer' +build_shared_library=True +if env['PLATFORM'] == 'win32': + # FIXME(windows): symbols in hammer are not exported yet, a shared lib would be useless + build_shared_library=False + # prevent collision between .lib from dll and .lib for static lib + static_library_name = 'hammer_s' + libhammer_shared = env.SharedLibrary('hammer', parsers + backends + misc_hammer_parts) -libhammer_static = env.StaticLibrary('hammer', parsers + backends + misc_hammer_parts) -Default(libhammer_shared, libhammer_static) +libhammer_static = env.StaticLibrary(static_library_name, parsers + backends + misc_hammer_parts) +if build_shared_library: + Default(libhammer_shared, libhammer_static) + env.Install('$libpath', [libhammer_static, libhammer_shared]) +else: + Default(libhammer_static) + env.Install('$libpath', [libhammer_static]) -env.Install("$libpath", [libhammer_static, libhammer_shared]) -env.Install("$incpath", dist_headers) -env.Install("$parsersincpath", parsers_headers) -env.Install("$backendsincpath", backends_headers) -env.Install("$pkgconfigpath", "../../../libhammer.pc") +env.Install('$incpath', dist_headers) +env.Install('$parsersincpath', parsers_headers) +env.Install('$backendsincpath', backends_headers) +env.Install('$pkgconfigpath', '../../../libhammer.pc') -testenv = env.Clone() -testenv.ParseConfig('pkg-config --cflags --libs glib-2.0') -testenv.Append(LIBS=['hammer']) -testenv.Prepend(LIBPATH=['.']) -ctestexec = testenv.Program('test_suite', ctests + ['test_suite.c'], LINKFLAGS="--coverage" if testenv.GetOption("coverage") else None) -ctest = Alias('testc', [ctestexec], "".join(["env LD_LIBRARY_PATH=", os.path.dirname(ctestexec[0].path), " ", ctestexec[0].path])) -AlwaysBuild(ctest) -testruns.append(ctest) +if GetOption('with_tests'): + testenv = env.Clone() + testenv.ParseConfig('pkg-config --cflags --libs glib-2.0') + testenv.Append(LIBS=['hammer']) + testenv.Prepend(LIBPATH=['.']) + ctestexec = testenv.Program('test_suite', ctests + ['test_suite.c'], LINKFLAGS='--coverage' if testenv.GetOption('coverage') else None) + ctest = Alias('testc', [ctestexec], ''.join(['env LD_LIBRARY_PATH=', os.path.dirname(ctestexec[0].path), ' ', ctestexec[0].path])) + AlwaysBuild(ctest) + testruns.append(ctest) -Export("libhammer_static libhammer_shared") +Export('libhammer_static libhammer_shared') for b in env['bindings']: - env.SConscript(["bindings/%s/SConscript" % b]) + env.SConscript(['bindings/%s/SConscript' % b]) diff --git a/tools/windows/build.bat b/tools/windows/build.bat index 20f878a..2bf3901 100644 --- a/tools/windows/build.bat +++ b/tools/windows/build.bat @@ -24,8 +24,8 @@ cl.exe -nologo -FC -EHsc -Z7 -Oi -GR- -Gm- %CLFLAGS% -c ^ -Fo%BUILD%\obj\ if %errorlevel% neq 0 goto err -lib.exe %BUILD%\obj\*.obj -OUT:%BUILD%\hammer.lib -echo STATIC_LIBRARY %BUILD%\hammer.lib +lib.exe %BUILD%\obj\*.obj -OUT:%BUILD%\lib\hammer_s.lib +echo STATIC_LIBRARY %BUILD%\lib\hammer_s.lib if %errorlevel% neq 0 goto err popd diff --git a/tools/windows/build_examples.bat b/tools/windows/build_examples.bat index c431fae..b6f8248 100644 --- a/tools/windows/build_examples.bat +++ b/tools/windows/build_examples.bat @@ -15,7 +15,7 @@ call %HEREPATH%\clvars.bat echo SRC=%SRC%, BUILD=%BUILD% echo CLFLAGS=%CLFLAGS% -set HAMMERLIB=%BUILD%\hammer.lib +set HAMMERLIB=%BUILD%\lib\hammer_s.lib REM Now let's build some example programs