From 69d3e70211abf0e543f391dc7f5dae4762070b55 Mon Sep 17 00:00:00 2001 From: nicolas <nicolas@uucidl.com> Date: Sun, 22 May 2016 13:29:12 +0200 Subject: [PATCH] Port scons build files for Windows users We disable: - the tests (which require glib) although they can be reactivated with the `--tests` command line flag - shared library (lack of export symbol declarations means that although it can be built, no symbol is exported and therefore it can't be used) The `install` target installs the library and headers under the `build` folder, because it's a traditional practice to move libraries to a central location on Windows, unless you are using cygwin. In which case pass `prefix` to the command line. We adapt tools\windows\build_examples.bat to take the library that is built using scons or using tools\windows\build.bat --- SConstruct | 43 ++++++++++++++++++++++++++--- src/SConscript | 46 +++++++++++++++++++++++--------- tools/windows/build.bat | 4 +-- tools/windows/build_examples.bat | 2 +- 4 files changed, 75 insertions(+), 20 deletions(-) diff --git a/SConstruct b/SConstruct index f9aef938..0950fa05 100644 --- a/SConstruct +++ b/SConstruct @@ -4,9 +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('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'] @@ -16,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, @@ -68,6 +75,12 @@ AddOption("--in-place", action="store_true", help="Build in-place, rather than in the build/<variant> 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"] @@ -76,13 +89,29 @@ if os.getenv("CC") == "clang" or env['PLATFORM'] == 'darwin': CXX="clang++") # Language standard and warnings -env.MergeFlags("-std=gnu99 -Wall -Wextra -Werror -Wno-unused-parameter -Wno-attributes -Wno-unused-variable") +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 platform.system() == "OpenBSD": pass +elif env['PLATFORM'] == 'win32': + # no extra lib needed + pass else: env.MergeFlags("-lrt") @@ -96,10 +125,16 @@ if GetOption("coverage"): env.ParseConfig('llvm-config --ldflags') dbg = env.Clone(VARIANT='debug') -dbg.Append(CCFLAGS=['-g']) +if env["CC"] == "cl": + dbg.Append(CCFLAGS=["/Z7"]) +else: + dbg.Append(CCFLAGS=['-g']) opt = env.Clone(VARIANT='opt') -opt.Append(CCFLAGS=["-O3"]) +if env["CC"] == "cl": + opt.Append(CCFLAGS=["/O2"]) +else: + opt.Append(CCFLAGS=["-O3"]) if GetOption("variant") == 'debug': env = dbg diff --git a/src/SConscript b/src/SConscript index 7a1b9d49..414f9f46 100644 --- a/src/SConscript +++ b/src/SConscript @@ -1,5 +1,6 @@ # -*- python -*- import os.path + Import('env testruns') dist_headers = [ @@ -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,24 +84,36 @@ ctests = ['t_benchmark.c', 't_misc.c', 't_regression.c'] + +static_library_name = 'hammer' +build_shared_library=True +if env['PLATFORM'] == 'win32': + build_shared_library=False # symbols in hammer are not exported yet, this shared lib would be useless + static_library_name = 'hammer_s' # prevent collision between .lib from dll and .lib for static lib + 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") -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") diff --git a/tools/windows/build.bat b/tools/windows/build.bat index 20f878ac..2bf39016 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 c431faeb..b6f82487 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 -- GitLab