---
wscript | 408 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 408 insertions(+), 0 deletions(-)
create mode 100644 wscript
diff --git a/wscript b/wscript
new file mode 100644
index 0000000..a7d19a8
--- /dev/null
+++ b/wscript
@@ -0,0 +1,408 @@
+#<!-- -*- mode: Python; fill-column: 80; comment-column: 75; -*- -->
+
+
+# WAF based build system
+# ======================
+#
+# This is a waf script that controls the build of the system. It is built using
+# the included waf binary that is shipped with the source. The only dependency
+# for the build system should be python.
+#
+# you can build the system by running one of the following commands in the top
+# level directory.
+#
+# ### Debug
+#
+# The debug command builds a version of the jeringa executable with debugging
+# symbols enabled and no optimization what so ever. This isn't suitable for
+# release but can be vary useful if you want to run the system under gdb.
+#
+# :::sh
+# $./waf debug
+#
+# ### Test
+#
+# The test variant builds the 'test_jeringa' application, which when run will
+# run all the unit tests available. Hopefully, doing a full test of the system
+# and ensuring a good result.
+#
+# :::sh
+# $./waf test
+#
+# ### Release
+#
+# Release builds a version of jeringa that is fully ready for releasing to end
+# users. It builds a version of the executable that has no debugging symbols at
+# all, and has most sane optimizations turned on.
+
+import os
+import glob
+import errno
+import re
+import subprocess
+import shlex
+import platform
+import subprocess
+import distutils.dir_util
+
+from waflib.Tools import waf_unit_test
+from waflib.Build import BuildContext
+from waflib import Logs
+
+# Variants
+# --------
+#
+# Variants in this script serve as a way to control the options passed to the
+# compiler as well as which functions actually get called to do the varias
+# processes. Variants are just calsses that extend BuildContext and associate a
+# command, a function and a variant name together. The three variants are
+# displayed below and described above. Notice in the cfg.setenv(*variant-name*)
+# in the configuration part.
+
+class debug(BuildContext):
+ cmd = 'debug'
+ fun = 'do_debug'
+ variant = 'debug'
+
+class test(BuildContext):
+ cmd = 'test'
+ fun = 'do_test'
+ variant = 'test'
+
+class release(BuildContext):
+ cmd = 'release'
+ fun = 'do_release'
+ variant = 'release'
+
+# The top and out variables are used and modified by waf to. Top points to the
+# top most directory of the build while out points to the output location for
+# build artifacts. These can always be used in this script and should always be
+# accurate
+top = '.'
+out = 'build'
+
+# This regexp helps parse out the result of test runs. It is used in the
summary
+# function to detect test failures and print out the results.
+FAILED_REGEXP = re.compile(r'.*SUMMARY: run:(\d+) failed:(\d+) passed:(\d+).*',
+ re.DOTALL)
+
+# This build system supports building with both clang and gcc. During the
+# development phase the preferred compiler is clang as it provides much better
+# error information then gcc. However, clang still has a few issues. One of
them
+# is being able to find the built in gnu headers (like asm/errno.h). This
+# function helps dectect those and makes sure they are included in the include
+# path.
+def find_includes():
+ uname = os.uname()
+ arch = uname[4]
+
+ # The config that we will be generating later gets generated into the
+ # build directory. So we need to add that to the includes.
+ includes = ['./include',
+ os.path.join('deps', 'libarchive', 'libarchive'),
+ os.path.join('deps', 'lua', 'src'),
+ out]
+
+ if uname[0] == 'Linux':
+ possible = os.path.join('/', 'usr', 'include',
+ '%s-linux-gnu' % arch)
+ if os.path.exists(possible):
+ includes.append(possible)
+ return includes
+
+# At the moment our options are pretty simple. We just want to load the options
+# for the unit test support in waf.
+def options(opt):
+ opt.load('waf_unit_test')
+
+# Configuration
+# -------------
+#
+# The configure function does all the work for configuring the system, with
+# specialized configuration for all the various variants that exist.
+def configure(ctx):
+ is_clang = False;
+
+
+ # We want to build with clang if its available on the system. It
+ # produceses much much better error information the gcc and is an all
+ # around better compiler. However, its not available on a lot of systems
+ # and if you are not actually doing development its not really
+ # needed. We are using fairly standard c so the system can be compiled
+ # by both gcc and clang. So we are going to try finding clang and if
+ # that doesn't work we will fall back on gcc.
+
+ try:
+ ctx.env.stash()
+ ctx.find_program('clang', var='CC')
+ ctx.find_program('clang++', var='CXX')
+ ctx.env.append_value('LINKFLAGS',
+ ['-use-gold-plugin'])
+ ctx.define('CLANG', True)
+ is_clang = True
+ except ctx.errors.ConfigurationError:
+ ctx.env.revert()
+ ctx.define('CLANG', False)
+
+
+ # Regardless of the build platform or target we actually need sh
+ ctx.find_program('sh', var='SH')
+
+
+
+ # We want valgrind, to be available for testing, but its not absolutely
+ # required.
+ try:
+ ctx.env.stash()
+ ctx.find_program('valgrind', var='VALGRIND')
+ except ctx.errors.ConfigurationError:
+ ctx.env.revert()
+
+ # Unit testing is important and we want it to fit in our system. So we
+ # load up the waf unit testing support.
+ ctx.load('waf_unit_test')
+
+ # We try to get all the includes we will need depending on many factors
+ ctx.env.INCLUDES = find_includes()
+
+ ctx.env.append_value("LIBPATH",
+ [os.path.join("deps", "libarchive")])
+
+ #
+ # The default flags. Notice that we use gnu99 and turn all warnings and
+ # make those warnings errors. There is no need to not do this, and we
+ # expect it to be honored in all code contributions.
+ #
+ # In this code base we rely pretty heavily on closs object inlining. We
+ # do this instead of putting static functions in header files. we
+ # suspect that the compiler is going to do a much better job of inlining
+ # then we will manually. So its important to have this flag on all the
+ # time.
+ ctx.env.append_value('CFLAGS', ['-std=gnu99',
+ '-Wall',
+ '-Werror',
+ '-Wextra',
+ '-flto',
+ '-fstack-protector-all']),
+
+ # The clang and gcc worlds are almost identical from an argument
+ # perspective. So regardless of whether CC is set to clang or gcc we
+ # want to load up the gcc world. Note this does not load up the gcc
+ # compiler unless CC was not set to gcc.
+ ctx.load("gcc")
+
+ # ### System Specific Defines
+ #
+ # There are a few things that it is useful to know about the system we
+ # are on, here we quiery that information and generate it into a config
+ # header.
+
+ ctx.define('PATH_SEP', os.sep)
+ ctx.define('PATH_SEP_CHAR', ord(os.sep))
+ ctx.define('PATH_SEP_LEN', len(os.sep))
+
+ ctx.define('PATH_DELIM', os.pathsep)
+ ctx.define('PATH_DELIM_CHAR', ord(os.pathsep))
+ ctx.define('PATH_DELIM_LEN', len(os.pathsep))
+
+ #system = platform.system()
+
+ # ### Debug Variant Flags
+
+ # Set up the debug variant, turn off all optimizations and turn on
+ # debugging information.
+ ctx.setenv('debug', env=ctx.env.derive())
+ ctx.env.append_value('CFLAGS', ['-O0', '-g'])
+
+ # ### Test Variant Flags
+ #
+ # The test variant is very simular to debug, we want no optimizations
+ # and, debug information. We also want to set the UNIT_TEST flag so the
+ # unit tests actually appear in the built system.
+ ctx.setenv('test', env=ctx.env.derive())
+ ctx.env.append_value('CFLAGS', ['-O0', '-g', '-DUNIT_TESTS'])
+
+ # Define a temporary directory within the build for unit tests. This is
+ # setup to be relative to the location in which the build is running, ie
+ # the varinat dir
+ ctx.define('UNIT_TEST_TMP', os.path.join(".", "tmp"))
+
+ # ### Release Variant Flags
+ #
+ # The release variant is a bit different, all optimizations are on and
+ # no debuggin information is included. In the case of clang we turn on
+ # the O4 optimization to get closs object inlining, since gcc doesn't
+ # support O4, we turn on O3 for it.
+ ctx.setenv('release', env=ctx.env.derive())
+ if is_clang:
+ ctx.env.append_value('CFLAGS', ['-O4'])
+ else:
+ ctx.env.append_value('CFLAGS', ['-O3'])
+
+ ctx.write_config_header('config.h')
+
+# The Build Functions
+# -------------------
+#
+# These are the functions that actually do the work of building the various
+# variants. The actual 'build' function itself is not used. Its just a
+# placeholder that waf seams to need. So if someone runs build we just print
out
+# a message letting them know that they need to pick one of the variants.
+def build(bld):
+ print ("The build target is not supported, please choose debug, "
+ "test, or release")
+ return False
+
+# ### Debug Function
+#
+# The debug function builds the debug variant.
+def do_debug(bld):
+ build_lib(bld)
+
+ bld(
+ features = 'c cprogram',
+ source = glob.glob("src/*.c"),
+ target = 'jeringa',
+ lib='m z archive',
+ use = 'archive jeringalua')
+
+# ### Release Function
+#
+# The release function builds the debug variant.
+def do_release(bld):
+ build_lib(bld)
+
+ bld(
+ features = 'c cprogram',
+ source = glob.glob("src/*.c"),
+ lib='m z',
+ use = 'archive jeringalua')
+
+# ### Test Function
+#
+# The test function builds the test variant. Well its not actually a variant in
+# the usual sense. It builds a completely different executable. The
+# 'test_jeringa' executable. This executable is a unit test executable and only
+# exists to run all the unit tests in the system. Once the test_jeringa
+# executable is built the test variant will run it printing out success and
+# failure information.
+def do_test(bld):
+ bld.options.all_tests = True
+ bld.add_post_fun(summary)
+
+ build_lib(bld)
+
+ bld(
+ features='c cprogram test',
+ source=['src/util.c',
+ 'src/log.c',
+ 'src/working-dir.c',
+ 'src/args.c',
+ 'test/main.c',
+ 'test/test-support.c',
+ 'test/seatest.c'],
+ target='test-jeringa',
+ ut_fun= run_tests,
+ include="deps/libarchive",
+ lib='m z',
+ use = 'archive jeringalua')
+
+# Support Functions
+# -----------------
+#
+# These are the support functions for the various parts of the system.
+
+# <!BREAK!>
+
+def get_sources(bld):
+ return
+
+# there two dependencies that need to be built (in some cases). The first
+# dependency is lua, in those casese where the lua options are set. The second
+# is libarchive. both are included in the source in ./deps.
+def build_lib(bld):
+ bld.stlib(
+ source = ['deps/lua/src/lapi.c',
+ 'deps/lua/src/lbaselib.c',
+ 'deps/lua/src/lcode.c',
+ 'deps/lua/src/ldebug.c',
+ 'deps/lua/src/lgc.c',
+ 'deps/lua/src/linit.c',
+ 'deps/lua/src/llex.c',
+ 'deps/lua/src/lmathlib.c',
+ 'deps/lua/src/lmem.c',
+ 'deps/lua/src/loadlib.c',
+ 'deps/lua/src/lobject.c',
+ 'deps/lua/src/lopcodes.c',
+ 'deps/lua/src/loslib.c',
+ 'deps/lua/src/lparser.c',
+ 'deps/lua/src/lstate.c',
+ 'deps/lua/src/lstring.c',
+ 'deps/lua/src/lstrlib.c',
+ 'deps/lua/src/ltm.c',
+ 'deps/lua/src/ltable.c',
+ 'deps/lua/src/lundump.c',
+ 'deps/lua/src/lvm.c',
+ 'deps/lua/src/ldo.c',
+ 'deps/lua/src/lfunc.c',
+ 'deps/lua/src/lauxlib.c',
+ 'deps/lua/src/ldump.c',
+ 'deps/lua/src/lzio.c',
+ 'deps/lua/src/print.c'],
+ target = 'jeringalua',
+ name = 'jeringalua'),
+
+ libarchive = bld.path.find_node('deps/libarchive')
+ if not os.path.exists(os.path.join(libarchive.get_bld().abspath(),
+ 'libarchive.a')):
+ distutils.dir_util.copy_tree(libarchive.get_src().abspath(),
+ libarchive.get_bld().abspath())
+
+
+ cwd = os.getcwd()
+ os.chdir(libarchive.get_bld().abspath())
+ subprocess.call('pwd', shell=True)
+ subprocess.call(bld.env.SH + ' ./build/autogen.sh', shell =
True);
+ subprocess.call('make', shell = True);
+ os.chdir(cwd)
+
+def run_tests(self):
+ filename = self.inputs[0].abspath()
+ test_exe = getattr(self,'ut_exec', [filename])
+
+ if len(self.generator.env.VALGRIND) != []:
+ self.ut_exec = [self.generator.env.VALGRIND,
+ '--tool=memcheck',
+ '--leak-check=yes'] + test_exe
+ else:
+ self.ut_exec = test_exe
+
+
+
+# ### Summary
+#
+# The summary function parses the output of the unit test run and prints out
+# secuss or failure. Returning that information to the caller and hopefully,
+# erroring out the test when false is returned.
+def summary(bld):
+ [(_, Ret, lst, _)] = getattr(bld, 'utest_results', [])
+ if Ret != 0:
+ Logs.pprint('RED', 'TESTS FAILED BADLY!!!')
+
+ if lst:
+ match = FAILED_REGEXP.match(lst)
+ if not match:
+ Logs.pprint('RED', 'Expected test results not found!')
+ return False
+
+ ran = match.group(1)
+ failed = match.group(2)
+ passed = match.group(3)
+
+ Logs.pprint('CYAN', ' tests that fail %s/%s' %
+ (failed, ran))
+
+ if int(failed) > 0:
+ Logs.pprint('RED', lst)
+ return False
+ return True
--
1.7.5.2
--
You received this message because you are subscribed to the Google Groups
"erlware-dev" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/erlware-dev?hl=en.