On the page [Jim Tcl as a basis for configure and build system] there has been discussion about replacing bash -> m4 -> autoconf -> automake -> make with a Tcl-based system. '''autosetup''' (https://github.com/msteveb/autosetup) is a piece of that puzzle. It is a Tcl-based replacement for autoconf. One interesting feature is that it solves the bootstrap problem by including a single-sourcefile version of Jim Tcl which will automatically be compiled and used if an appropriate Tcl interpreter isn't found. Below is the autosetup manual for easy access (but I may remove this at some point since it is also available at http://msteveb.github.com/autosetup/) Comment is welcome here. ------- *** autosetup v0.6.0 -- User Manual *** '''1. Introduction''' 'autosetup' is a tool, similar to 'autoconf', to configure a build system for the appropriate environment, according to the system capabilities and the user configuration. autosetup is designed to be light-weight, fast, simple and flexible. Notable features include: * Easily check for headers, functions, types for C/C++ * Easily support user configuration options * Can generate files based on templates, such as Makefile.in => Makefile * Can generate header files based on checked features * Excellent support for cross compilation * Replacement for autoconf in many situations * Runs with either Tcl 8.5+, Jim Tcl or just a C compiler (using the included Jim Tcl source code!) * autosetup is intended to be distributed with projects - no version issues autosetup is particularly targeted towards building C/C++ applications on Unix systems, however it can be extended for other environments as needed. autosetup is *not*: * A build system * A replacement for automake * Intended to replace all possible uses of autoconf '''2. Usage''' autosetup accepts both standard options as well as local options defined in the 'auto.def' file, and options for modules. Use 'autosetup --help' to show all available options. ====== autosetup ?options? ?settings? ====== Some important core options are: ====== -C dir change to the given directory before running autosetup --help display help and options --version display the version of autosetup --manual?=text? display the autosetup manual. Alternative formats are 'wiki' and 'asciidoc' --install install autosetup to the current directory --init create an initial 'configure' script if none exists ====== Settings are of the form 'name=value' and must be after any options. These settings allow the default values to be overridden for variables such as CC and CFLAGS. Optional modules may support additional options. For example, the cc module supports the following additional options. ====== --host=host-alias a complete or partial cpu-vendor-opsys for the system where the application will run (defaults to the same value as --build) --build=build-alias a complete or partial cpu-vendor-opsys for the system where the application will be built (defaults to the result of running config.guess) --prefix=dir the target directory for the build (defaults to /usr/local) ====== Typically, autosetup is invoked via a simpler wrapper script, 'configure'. This provides for compatibility with autoconf. For example: ====== ./configure --host=arm-linux --utf8 --prefix=/usr CFLAGS="-g -Os" ====== '''3. Features''' ''3.1. Configuration descriptions are Tcl'' Configuration requirements are given in an 'auto.def' file and are written in 'Tcl', a language slightly less obscure than 'm4'! As a full language, there are no additional dependencies on the host system such as 'awk', 'sed' and 'bash'. Tcl is widely available on modern development platforms. ''3.2. Simple Configuration Descriptions'' A typical, simple auto.def file is: ====== use cc options { shared => "build a shared library" lineedit=1 => "disable line editing" utf8 => "enabled UTF-8 support" with-regexp regexp => "use regexp" } cc-check-types "long long" cc-check-includes sys/un.h dlfcn.h cc-check-functions ualarm sysinfo lstat fork vfork cc-check-function-in-lib sqlite3_open sqlite3 if {[opt-bool utf8] && [have-feature fork]} { msg-result "Enabling UTF-8" define JIM_UTF8 } make-autoconf-h config.h make-template Makefile.in ====== ''3.3. Fast'' All the processing occurs in a single process, aside from invocations of the C compiler. Here are the results of a typical configure for a small project. 'autoconf' is particularly slow on 'cygwin'. ====== autoconf autosetup --------- --------- Linux 4.1s 1.3s Mac OS X 6.4s 2.8s cygwin 91.5s 9.9s ====== ''3.4. Deploys directly within a project'' autosetup is deployed as a single subdirectory, autosetup, at the top level of a project, containing a handful of files. This approach means that there are no dependency issues with different versions of autosetup since an appropriate version is part of the project. autosetup is written in Tcl, but can run under any of the following Tcl interpreters: * Tcl 8.5 or later (which is widely deployed * Jim Tcl - small footprint, portable Tcl interpreter The source code for Jim Tcl is included directly within autosetup and is automatically built if no other Tcl interpreter is available. ====== $ ./configure --help No installed jimsh or tclsh, building local bootstrap jimsh0 Usage: configure [options] This is autosetup, a faster, better alternative to autoconf. Use the --manual option for the full autosetup manual, including standard autosetup options. Local options: --shared Create a shared library --disable-utf8 Disable utf8 support ====== ''3.5. No separate generate/run step'' autosetup parses 'auto.def' and updates the configuration in a single step. This simplifies and speeds development. '''4. Writing auto.def files''' auto.def files are generally simple to write, but have the full power of Tcl if required for implementing complex checks or option processing. The 'auto.def' file is structured as follows: * 'use' modules * 'options' declaration * checks and option processing * template, header file and other output generation ''4.1. Optional modules'' autosetup includes the common, optional modules 'cc' and 'cc-shared'. If these modules are required, declared *before* 'options' so that any module-specific options can be recognized. ====== # This project checks for C/C++ features use cc # And supports shared libraries/shared objects use cc-shared options { ... } ====== ''4.2. Declaring User Options'' Allowed options are defined using the 'options' declaration in the 'auto.def' file. *Note*: Every auto.def *must* have an 'options' declaration immediately after any 'use' declarations, even if it is empty. This ensures that 'configure --help' behaves correctly. Options are declared as follows. ====== options { boolopt => "a boolean option which defaults to disabled" boolopt2=1 => "a boolean option which defaults to enabled" stringopt: => "an option which takes an argument, e.g. --stringopt=value" stringopt2:=value => "an option where the argument is optional and defaults to 'value'" optalias booltopt3 => "a boolean with a hidden alias. --optalias is not shown in --help" boolopt4 => { Multiline description for this option which is carefully formatted. } } ====== The '=>' syntax is used to indicate the help description for the option. If an option is not followed by '=>', the option is not displayed in '--help' but is still available. If the first character of the help description is a newline (as for 'boolopt4'), the description will not be reformatted. String options can be specified multiple times, and all given values are available. If there is no default value, the value must be specified. Within auto.def, options are checked with the commands 'opt-bool' and 'opt-val'. ''4.3. Setting Options'' Boolean options can be enabled or disabled with one of the following forms (some of which are for autoconf compatibility): ====== Enable the option: --boolopt --enable-boolopt --boolopt=1 --boolopt=yes Disable the option: --disable-boolopt --boolopt=0 --boolopt=no ====== String options must have a value specified, unless the option has a default value. ====== --stropt - OK if a default values is given for stropt --stropt=value - Adds the given value for the option ====== ''4.4. Configuration Variables'' At it's heart, autosetup is about examining user options, performing checks and setting configuration variables representing the options and environment. These variables are set either directly with the 'define' or 'define-feature' commands, or indirectly via one of the test commands such as 'cc-check-includes'. All configuration variables are available for template substitution ('make-template'), header file generation ('make-autoconf-h') or can be tested and set within 'auto.def'. Certain naming conventions are used to provide expected behavior. All commands which check for the existence of a feature, use HAVE_xxx as the name of the corresponding variable (this is autoconf compatible). See 'feature-define-name' for the rules used to convert a feature name to a variable name. ====== cc-check-includes time.h sys/types.h => HAVE_TIME_H HAVE_SYS_TYPES_H cc-check-functions strlcat => HAVE_STRLCAT cc-check-types "long long" "struct stat" => HAVE_LONG_LONG HAVE_STRUCT_STAT ====== These two are equivalent: ====== have-feature sys/types.h get-define HAVE_SYS_TYPE_H ====== 'cc-check-sizeof' uses the SIZEOF_ prefix rather than the HAVE_ prefix. Variables used to store command names are simply the uppercase of the base command. ====== CC - The C compiler LD - The linker AR - ar RANLIB - ranlib ====== ''4.5. configure'' In order to provide compatibility with autoconf, and to simplify out-of-tree builds, autosetup can be run via a simple 'configure' script. The following script is created by 'autosetup --init'. ====== #!/bin/sh dir="$(dirname "$0")/autosetup" WRAPPER="$0" exec $("$dir/find-tclsh" || echo false) "$dir/autosetup" "$@" ====== This script invokes autosetup in the autosetup/ subdirectory after setting the WRAPPER environment variable. 'autosetup --init' will create this script if it doesn't exist. ''4.6. Checking Features'' Apart from checking user options, the primary purpose of autosetup and 'auto.def' is to check for the availability of features in the environment. The 'cc' module provides commands to check various settings by compiling small test programs with the specified C compiler. The following is a typical example: ====== use cc options {} cc-check-types "long long" cc-check-includes sys/un.h cc-check-functions regcomp waitpid sigaction cc-check-tools ar ranlib strip ====== See the command reference for details of these builtin checks. ''4.7. Controlling the build'' Once the user options have been processed and the environment checked for supported features, it is necessary to use this information to control the build. The 'cc' module provides two mechanisms for this: * 'make-template' creates a file from a template by applying substitutions based on the configuration variables. For example, replacing '@CC@' with 'arm-linux-gcc'. * 'make-autoconf-h' creates a C/C++ header file based on the configuration variables It is easy to create other file formats based on configuration variables. For example, one system produces configuration files in the Linux kconfig format. It is also possible to output configuration variables in Makefile format. autosetup has far more control over generating files to control the build since the configuration variables are directly accessible in 'Tcl' from 'auto.def'. ''4.8. A "standard" Makefile.in'' If autosetup is being used to control a make-based build system, the use of a a 'Makefile.in' with a standard structure will provide behavior similar to that provided by autoconf/automake systems. autosetup provides a typical 'Makefile.in' in 'examples/typical/Makefile.in'. This example provides the following: * Use CC, AR, RANLIB as determined by cross compiler settings or user overrides * Install to --prefix, overridable with DESTDIR * Use of VPATH to support out-of-tree builds * Dummy automake targets to allow for use as a subproject with automake * Automatically reconfigure if auto.def changes '''5. Command Reference''' autosetup provides a number of builtin commands which are documented below. These may be used from 'auto.def' to test for features, define variables create files from templates and other similar actions. This commands are all implemented as Tcl procedures. Custom commands may be added simply by defining additional Tcl procedures in the 'auto.def' file. : '''opt-bool option ...''' Check each of the named, boolean options and return 1 if any of them have been set by the user. : '''opt-val option-list ?default=""?''' Returns a list containing all the values given for the non-boolean options in 'option-list'. There will be one entry in the list for each option given by the user, including if the same option was used multiple times. If only a single value is required, use something like: ====== lindex [opt-val $names] end ====== If no options were set, $default is returned (exactly, not as a list). : '''define name ?value=1?''' Defines the named variable to the given value. These name, values pairs represent the results of the configuration check and are available to be checked, modified and substituted. : '''define-append name value''' Appends the given value to the given 'defined' variable. If the variable is not defined or empty, it is set to $value. Otherwise the value is appended, separated by a space. : '''get-define name ?default=0?''' Returns the current value of the 'defined' variable, or $default if not set. : '''is-defined name''' Returns 1 if the given variable is defined. : '''get-env name default''' If $name was specified on the command line, return it. If $name was set in the environment, return it. Otherwise return $default. : '''readfile filename ?default=""?''' Return the contents of the file, without the trailing newline. If the doesn't exist or can't be read, returns $default. : '''writefile filename value''' Creates the given file containing $value. Does not add an extra newline. : '''find-executable name''' Searches the path for an executable with the given name. Returns 1 if found, or 0 if not. : '''find-an-executable ?-required? name ...''' Given a list of possible executable names, searches for one of these on the path. Returns the name found, or "" if none found. If the first parameter is '-required', an error is generated if no executable is found. : '''configlog msg''' Writes the given message to the configuration log, config.log : '''msg-checking msg''' Writes the message with no newline to stdout. : '''msg-result msg''' Writes the message to stdout. : '''user-error msg''' Indicate incorrect usage to the user, including if required components or features are not found. autosetup exits with a non-zero return code. : '''user-notice msg''' Output the given message to stderr. : '''use module ...''' Load the given library modules. e.g. use cc cc-shared : '''MODULE: use cc-shared''' Module which provides support for shared libraries and shared objects. Defines the following variables: ====== SH_CFLAGS Flags to use compiling sources destined for a shared library SH_LDFLAGS Flags to use linking a shared library SHOBJ_CFLAGS Flags to use compiling sources destined for a shared object SHOBJ_LDFLAGS Flags to use linking a shared object SH_LINKFLAGS Flags to use linking an executable which will load shared objects LD_LIBRARY_PATH Environment variable which specifies path to shared libraries ====== : '''MODULE: use cc''' This module supports checking various 'features' of the C compiler/linker environment. Common commands are cc-check-includes, cc-check-types, cc-check-functions, make-autoconf-h and make-template. : '''have-feature name ?default=0?''' Returns the value of the feature if defined, or $default if not. : '''define-feature name ?value=1?''' Sets the feature 'define' to the given value. : '''feature-checked name''' Returns 1 if the feature has been checked, whether true or not : '''feature-define-name name ?prefix=HAVE_?''' Converts a name to the corresponding define, e.g. sys/stat.h becomes HAVE_SYS_STAT_H. Converts * to P and all non-alphanumerical characters to underscore. : '''cc-check-sizeof ?-args? type ...''' Checks the size of the given types (between 2 and 32). Defines a variable with the size determined, or "unknown" otherwise. e.g. for type 'long long', defines SIZEOF_LONG_LONG. Returns the size of the last type. The first arg may be a list of additional arguments to cctest. : '''cc-check-includes ?-args? includes ...''' Checks that the given include files can be used The first arg may be a list of additional arguments to cctest. : '''cc-check-types ?-args? type ...''' Checks that the types exist. The first arg may be a list of additional arguments to cctest. : '''cc-check-functions ?-args? function ...''' Checks that the given functions exist (can be linked) The first arg may be a list of additional arguments to cctest. : '''cc-check-members ?-args? type.member ...''' Checks that the given type/structure members exist. A structure member is of the form "struct stat.st_mtime" The first arg may be a list of additional arguments to cctest. : '''cc-check-function-in-lib function libs ?otherlibs?''' Checks that the given given function can be found on one of the libs. First checks for no library required, then checks each of the libraries in turn. If the function is found, the feature is defined and lib_$function is defined to -l$lib where the function was found, or "" if no library required. In addition, -l$lib is added to the LIBS define. If additional libraries may be needed to linked, they should be specified as $extralibs as "-lotherlib1 -lotherlib2". These libraries are not automatically added to LIBS. Returns 1 if found or 0 if not. : '''cc-check-tools tool ...''' Checks for existence of the given compiler tools, taking into account any cross compilation prefix. For example, when checking for "ar", first AR is checked on the command line and then in the environment. If not found, "${host}-ar" or simply "ar" is assumed depending upon whether cross compiling. The path is searched for this executable, and if found AR is defined to the executable name. It is an error if the executable is not found. : '''cc-check-progs prog ...''' Checks for existence of the given executables on the path. For example, when checking for "grep", the path is searched for the executable, 'grep', and if found GREP is defined as "grep". It the executable is not found, the variable is defined as false. Returns 1 if all programs were found, or 0 otherwise. : '''cctest ?settings?''' Low level C compiler checker. Compiles and or links a small C program according to the arguments and returns 1 if OK, or 0 if not. ====== Supported settings are: -cflags cflags A list of flags to pass to the compiler -includes list A list of includes, e.g. {stdlib.h stdio.h} -declare code Code to declare before main() -link 1 Don't just compile, link too -libs liblist List of libraries to link, e.g. {-ldl -lm} -code code Code to compile in the body of main() -source code Compile a complete program. Ignore -includes, -declare and -code -sourcefile file Shorthand for -source [readfile [get-define srcdir]/$file] ====== ====== #include /* same for remaining includes in the list */ declare-code /* any code in -declare, verbatim */ int main(void) { code /* any code in -code, verbatim */ return 0; } ====== Any failures are recorded in 'config.log' '''6. Examples''' autosetup includes a number of examples, including: * typical - A simple, but full feature example * minimal - A minimal example * jim - The Jim Tcl project uses autosetup These examples can be found along with the autosetup source at https://github.com/msteveb/autosetup '''7. Tips on moving from autoconf''' autosetup attempts to be reasonably compatible with an autoconf-generated 'configure' script. Some differences are noted below. ''7.1. No --target, no need for --build'' While autosetup has good cross compile support with '--host', it has no explicit support for '--target' (which is almost never needed). Additionally, --build is rarely needed since the build system can be guessed with 'config.guess'. ''7.2. Single variable namespace'' All variables defined with 'define' and 'define-feature' use a single namespace. This essentially means that AC_SUBST and AC_DEFINE are equivalent, which simplifies configuration in practice. ''7.3. No autoheader'' autosetup has no need for 'autoheader' since a configuration header file can simply be generated directly (see 'make-autoconf-h') without a template. ''7.4. No subdirectory support'' autoconf supports configuring subdirectories with AC_CONFIG_SUBDIRS. autosetup has no explicit support for this feature. ''7.5. No automake'' autosetup is not designed to be used with automake. autosetup is flexible enough to be used with plain 'make', or other builds systems. ''7.6. No AC_TRY_RUN'' autosetup has no equivalent of AC_TRY_RUN which attempts to run a test program. This feature is often used unnecessarily, and is useless when cross compiling, which is a core feature of autosetup. ''7.7. Modern Platform Assumption'' autoconf includes support for many old and obsolete platforms. Most of these are no longer relevant. autosetup assumes that the build environment is somewhat POSIX compliant. This includes both cygwin and mingw on Windows. ''7.8. Thus, no need to check for standard headers'' such as stdlib.h, string.h, etc. ''7.9. No AC_PROG_xxxx'' Use the generic 'cc-check-progs' ====== if {![cc-check-progs grep]} { user-error "You don't have grep, but we need it" } foreach prog {gawk mawk nawk awk} { if {[cc-check-progs $prog]} { define AWK $prog break } } # If not found, AWK is defined as false ====== ''7.10. No AC_FUNC_xxx'' Use the generic 'cc-check-functions' instead ''7.11. No special commands to use replacement functions'' Instead consider something like the following. ====== # auto.def: Check all functions cc-check-functions strtod backtrace /* replacements.c */ #include "config.h" #ifndef HAVE_STRTOD double strtod(...) { /* implementation */ } #endif ====== Alternatively, implement each missing function in it's own file. ====== define EXTRA_OBJS "" foreach f {strtod backtrace} { if {![cc-check-functions $f]} { define-append EXTRA_OBJS $f.o } } ====== ''7.12. Default checks do not use any include files.'' autoconf normally adds certain include files to every test build, such as stdio.h. This can cause problems where declarations in these standard headers conflict with the code being tested. For this reason, autosetup compile tests uses no standard headers. If headers are required, they should be added explicitly. ''7.13. Checking for includes'' When adding includes with '-includes', these are not checked for existence first '''8. Cross Compiling''' In general, cross compilation works the same way as autoconf. Generally this simply means specifying --host=. For example, if you have arm-linux-gcc and related tools, run: ====== ./configure --host=arm-linux ====== If additional compiler options are needed, such as -mbig-endian, these can be specified with CFLAGS. In this case, the default CFLAGS of "-g -O2" won't be used so the desired debugging and optimization flags should also be added. ====== ./configure --host=arm-linux CFLAGS="-mbig-endian -msoft-float -static-libgcc -g -Os" ====== If the compiler and related tools have a non-standard prefix, it may be necessary to set CROSS in addition to --host. ====== ./configure --host=arm-linux CROSS=my- ====== In this case, C the compiler should be named my-cc or my-gcc, and similarly for the other tools. This is usually simpler than specifying CC, AR, RANLIB, STRIP, etc. '''9. Installing''' Like autoconf, autosetup uses a combination of '--prefix' and 'DESTDIR' to determine where the project is installed. The '--prefix' option is used during with './configure' to specify the top level installation directory. It defaults to '/usr/local'. Use '--prefix=' to install at the top level (e.g. '/bin'). The application may use this value (via '@prefix@' or one of the related values such as '@bindir@') to find files at runtime. The 'DESTDIR' Makefile variable may be used at installation time to specify an different install root directory. This is especially useful to stage the installed files in a temporary location before they are installed to their final location (e.g. when building a filesystem for an embedded target). It defaults to the empty string (i.e. files are installed to '--prefix'). ====== ./configure --prefix=/usr make DESTDIR=/tmp/staging install ====== autosetup has no special support for installing other than providing '--prefix'. The use of 'DESTDIR' is by convention. In order to provide expected behavior, Makefile.in should contain something like: ====== prefix = @prefix@ ... install: all @echo Installing from @srcdir@ and `pwd` to $(DESTDIR)$(prefix) ====== '''10. Automatic remaking''' It is convenient for configure to be rerun automatically if any of the input files change (for example autosetup or any of the template files). This can be achieved by adding the following to Makefile.in. ====== ifeq ($(findstring clean,$(MAKECMDGOALS)),) Makefile: @AUTODEPS@ @srcdir@/Makefile.in @@AUTOREMAKE@ endif ====== It may also be convenient to add a target to force reconfiguring with the same options. ====== reconfig: @AUTOREMAKE@ ====== '''11. Shipping autosetup''' autosetup is designed to be deployed directly as part of a project. It is installed as a single subdirectory, autosetup, at the top level of a project. In addition to autosetup, the following files are required for an autosetup-enabled project. * auto.def * configure (generated by autosetup --init) * Makefile.in (and any other template specified in auto.def) '''12. Extending autosetup''' Local modules can be added directly to the autosetup directory and loaded with the 'use' command. '''13. Future Features/Changes''' Some features are not yet implemented, but are candidates for including in an existing module, or adding to a new module. Others may require changes to the core 'autosetup'. * Explicit C++ support * pkg-config support * More fully-featured shared library support * Support for additional languages * libtool support (if we must!) * Subdirectory support. Need to resolve how options are parsed, and how variables interact between subdirectories. '''14. Motivation''' autoconf does the job and supports many platforms, but it suffers from at least the following problems: * Requires configuration descriptions in a combination of m4 and shell scripts * Creates 10,000 line shell scripts which are slow to run and impossible to debug * Requires a multi-stage process of aclocal => autoheader => autoconf => configure => Makefile + config.h autosetup attempts to address these issues as follows by directly parsing a simple 'auto.def' file, written in Tcl, and directly generating output files such as config.h and Makefile. autosetup runs under either Tcl 8.5, which is available on almost any modern system, or Jim Tcl. Jim Tcl is very easy to build on almost any system in the case where Tcl is not available. '''15. References''' * http://freshmeat.net/articles/stop-the-autoconf-insanity-why-we-need-a-new-build-system * http://www.varnish-cache.org/docs/2.1/phk/autocrap.html * http://wiki.tcl.tk/27197 * http://jim.berlios.de/ * http://www.gnu.org/software/hello/manual/autoconf/index.html * http://www.flameeyes.eu/autotools-mythbuster/index.html ''15.1. Comments on autoconf'' * http://news.ycombinator.com/item?id=1499738 * http://developers.slashdot.org/article.pl?sid=04/05/21/0154219 * http://www.airs.com/blog/archives/95 '''16. Alternative autoconf Alternatives''' * http://pmk.sourceforge.net/faq.php - PMK * https://e-reports-ext.llnl.gov/pdf/315457.pdf - autokonf * http://www2.research.att.com/~astopen/man/man1/iffe.html - iffe manual page (AT&T). Requires Korn Shell * http://gentoo.com/di/mkconfig.html - Requires Bourne Shell (written by [bll]) * http://www.cmake.org/ - CMake * https://metacpan.org/source/JHI/metaconfig-for-Perl-5.6.0 - metaconf/dist '''17. Copyright, Author and Licence''' autosetup is Copyright (c) 2010 WorkWare Systems http://workware.net.au/ autosetup was written by Steve Bennett autosetup is released under the "2-clause FreeBSD Licence" as follows. ====== autosetup - An environment autoconfigurator Copyright 2010 Steve Bennett Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE WORKWARE SYSTEMS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WORKWARE SYSTEMS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. The views and conclusions contained in the software and documentation are those of the authors and should not be interpreted as representing official policies, either expressed or implied, of WorkWare Systems. ====== <>Development | Dev. Tools