---
 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.

Reply via email to