]> Dogcows Code - chaz/yoink/blobdiff - configure
build system enhancements
[chaz/yoink] / configure
index 8cc0b0d183071963c2c32602c3d19421f49f83fd..09df45fdf580bdfd3bfddbca3e903027fe9e7db3 100755 (executable)
--- a/configure
+++ b/configure
-#!/usr/bin/env lua
+#!/bin/sh
 
---
--- Yoink
--- Execute this file to configure the build system.
---
+#
+# Yoink
+# Execute this file to configure the build system.
+#
 
--- Define project, version, tarname, website, and contact.
-project                = "Yoink"
-version                = "0.1"
-tarname                = project:lower():gsub("%s+", "-")
-website                = "http://www.dogcows.com/yoink"
-contact                = "onefriedrice@brokenzipper.com"
-
-
--- This script will create three different config files from three tables
--- with values determined by the host and configuration options:
---
--- The table `config' contains key-value pairs to be written to the file
--- `config.h' which is included by sources files.  Boolean values will
--- either #define or #undef the key with no associated values.  String
--- values will be defined as quoted strings while any other value,
--- particularly numbers, will be defined unquoted.
---
--- The table `define' contains key-value pairs to be written to the file
--- `config.mk' which is included by the Makefile.  Values are assigned to
--- their keys as they are, unquoted.
---
--- The table `export' contains key-value pairs to be written to the file
--- `config.sed' which is used by sed to perform search-and-replace on files
--- containing @REPLACE_ME@-style keywords.  When used with sed, such
--- keyworded keys will be replaced by their values as they are, unquoted.
-
-
-function show_help()
-       print([[
-
-This script prepares ]]..project..[[ for building on your system.
-Usage: ./configure [OPTION]... [VAR=VALUE]...
-
-This is NOT an autoconf-generated configure script, though it was written
-to be familiar by supporting many of the same options.
-
-Basic configuration:
-  -h, --help              display this help and exit
-      --host=HOST         cross-compile the program to run on HOST
-
-      --prefix=DIR        base directory to install programs to
-      --bindir=DIR        directory to install executables
-      --datadir=DIR       directory to install shared data files
-      --mandir=DIR        directory to install manual pages
-
-      --disable-dependency-tracking  speed up one-time builds (maybe)
-      --disable-special-linking      do not use direct dependency minimizer
-      --enable-profile    compile in gprof profiling instructions
-
-Program options:
-      --enable-clock_gettime         use a very accurate timing function
-      --enable-debug      compile in assertion checks and other debug helps
-      --enable-double-precision      use larger floating-point numbers
-      --enable-hotload    automatically reload modified game assets
-      --enable-threads    use threads for concurrency where appropriate
-
-      --with-gtk          use the gtk2 toolkit (overrides --with-qt4)
-      --with-qt4          use the qt4 gui toolkit
-]])
-end
-
-
---
--- Setup a temporary file to collect error messages.
---
-
-config_log = "config.log"
-os.remove(config_log)
-
-
---
--- Define some useful functions.
---
-
--- Return true if a file exists, false otherwise.
-function file_exists(path)
-       return os.execute(string.format("test -f %q", path)) == 0
-end
-
--- Print an error message and exit with an error.
-function die(...)
-       for i,value in ipairs(arg) do
-               print("fatal: "..tostring(value))
-       end
-       if file_exists(config_log) then
-               print()
-               print("Look through the file `config.log' for more information:\n")
-               os.execute("tail "..config_log)
-       end
-       os.exit(1)
-end
-
--- Execute a command and return its output or nil if the command failed to
--- run.
-function backtick_run(command)
-       os.execute("echo '# "..command.."' >>"..config_log)
-       local fd = io.popen(command.." 2>>"..config_log)
-       if fd then
-               local stdout = fd:read("*l")
-               fd:close()
-               return stdout
-       end
-       return nil
-end
-
--- Try to execute a command and return true if the command finished
--- successfully (with an exit code of zero).
-function try_run(command)
-       os.execute("echo '# "..command.."' >>"..config_log)
-       return os.execute(command.." >/dev/null 2>>"..config_log) == 0
-end
-
--- Remove the whitespace surrounding a string.
-function trim(str)
-       str  = str:gsub("^%s+", "")
-       return str:gsub("%s+$", "")
-end
-
--- Trim the string and convert all sequences of whitespace to a single
--- space.
-function reduce_whitespace(str)
-       str = str:gsub("%s+", " ")
-       return trim(str)
-end
-
--- Get the CFLAGS from pkg-config for the passed libraries.
-function pkg_config_cflags(libs)
-       local env = "PKG_CONFIG_PATH="..libdir.."/pkgconfig:$PKG_CONFIG_PATH"
-       local cmd = env.." pkg-config"
-       return backtick_run(cmd.." --cflags "..libs)
-end
-
--- Get the LDFLAGS from pkg-config for the passed libraries.
-function pkg_config_ldflags(libs)
-       local env = "PKG_CONFIG_PATH="..libdir.."/pkgconfig:$PKG_CONFIG_PATH"
-       local cmd = env.." pkg-config"
-       return (" "..backtick_run(cmd.." --libs "..libs)):gsub("%s%-l%S*", "")
-end
-
--- Get the LIBS flags from pkg-config for the passed libraries.
-function pkg_config_libs(libs)
-       local env = "PKG_CONFIG_PATH="..libdir.."/pkgconfig:$PKG_CONFIG_PATH"
-       local cmd = env.." pkg-config"
-       return backtick_run(cmd.." --libs-only-l "..libs)
-end
-
--- Add a flag to the CFLAGS and CXXFLAGS variables.
-function add_cflag(flag)
-       if CFLAGS == "" then
-               CFLAGS = flag
-       else
-               CFLAGS = string.format("%s %s", CFLAGS, flag)
-       end
-       if CXXFLAGS == "" then
-               CXXFLAGS = flag
-       else
-               CXXFLAGS = string.format("%s %s", CXXFLAGS, flag)
-       end
-end
-
--- Replace a flag in the CFLAGS and CXXFLAGS variables.
-function set_cflag(flag)
-       local cflag_set, cxxflag_set = false, false
-       CFLAGS = CFLAGS:gsub("%"..flag:sub(1, 2).."%S+", function()
-               cflag_set = true
-               return flag
-       end)
-       CXXFLAGS = CXXFLAGS:gsub("%"..flag:sub(1, 2).."%S+", function()
-               cxxflag_set = true
-               return flag
-       end)
-       if not cflag_set or not cxxflag_set then add_cflag(flag) end
-end
-
--- Look for a command from a list that can complete successfully (with exit
--- code zero) given some arguments.  Returns nil if none were successful.
-function find_command(commands, args)
-       if not args then args = "" end
-       for i,command in ipairs(commands) do
-               if try_run(command.." "..args) then return command end
-       end
-       return nil
-end
-
-
---
--- Perform a quick sanity check.
---
-
-if not file_exists("configure") or not file_exists("Makefile") then
-       -- This script doesn't support out-of-tree builds.
-       die("You must `cd' to the project root where the Makefile is.")
-end
-
-
---
--- Parse the command-line options.
---
-
--- This script supports many of the options provided by autoconf-generated
--- scripts.  In particular, all the directory-related options are
--- supported, including --prefix, --exec-prefix, and all the --dirDIR
--- options for configuring installation paths.  If passed, the option
--- parsing routine below will place these options in the global namespace
--- (i.e. prefix, eprefix, bindir, datadir, etc).
---
--- Feature and package options are also supported.  The value of any option
--- of the form --enable-OPT= and --with-OPT= can be obtained with the
--- functions get_feature and get_package, respectively.  Like
--- autoconf-generated scripts, passing --disable-OPT or --without-OPT is
--- equivalent to passing --enable-OPT=no and --without-OPT=no,
--- respectively.  Values that are either yes or no are interpreted as
--- booleans.  Any other values are interpreted as strings.
---
--- Definitions of the form KEY=VALUE are also supported.  If passed, the
--- option parsing routine below will place these options in the global
--- namespace.
---
--- Finally, the options -h, --help, and --host are also supported, the
--- former two calling the show_help function and the latter setting the
--- host global variable.
-
-do
-       local features = {}
-       local packages = {}
-       local handlers = {}
-
-
-       -- Define the option-parsing rules and handlers.
-
-       handlers["--help"]                                              = function()
-               show_help()
-               os.exit(0)
-       end
-       handlers["-h"]                                                  = handlers["--help"]
-
-       handlers["--host=(.+)"]                                 = function(triplet)
-               host = triplet
-               cross_compile = true
-       end
-
-       local add_feature                                               = function(feature, value)
-               if value == "yes" or value == "" then value = true end
-               if value == "no" then value = false end
-               features[feature] = value
-       end
-       handlers["--enable%-([%w_-]+)=?(.*)"]   = add_feature
-       handlers["--disable%-([%w_-]+)"]                = function(feature)
-               add_feature(feature, "no")
-       end
-
-       local add_package                                               = function(package, value)
-               if value == "yes" or value == "" then value = true end
-               if value == "no" then value = false end
-               packages[package] = value
-       end
-       handlers["--with%-([%w_-]+)=?(.*)"]             = add_package
-       handlers["--without%-([%w_-]+)"]                = function(package)
-               add_package(package, "no")
-       end
-
-       handlers["--(%l+)dir=(.+)"]                             = function(dir, path)
-               _G[dir.."dir"] = path
-       end
-       handlers["--prefix=(.+)"]                               = function(path)
-               prefix = path
-       end
-       handlers["--exec-prefix=(.+)"]                  = function(path)
-               eprefix = path
-       end
-
-       handlers["([%w_]+)=(.*)"]                               = function(key, value)
-               _G[key] = value
-       end
-
-
-       -- Define the feature and package accessors.
-
-       function get_feature(feature) return features[feature] end
-       function get_package(package) return packages[package] end
-
-       
-       -- Now read and parse the command-line options.
-       
-       local function parse_arg(arg)
-               for key,value in pairs(handlers) do
-                       local matches = {arg:match(key)}
-                       if matches[1] then value(unpack(matches)) return end
-               end
-               print("warning: unknown or incomplete argument "..arg)
-       end
-
-       for i,arg in ipairs(arg) do
-               parse_arg(arg)
-       end
-
-
-       -- Define default values for significant variables.
-       
-       local function define(symbol, value)
-               if not _G[symbol] then _G[symbol] = value end
-       end
-
-       define("CC",                    "")
-       define("CXX",                   "")
-       define("AR",                    "")
-       define("RANLIB",                "")
-       define("WINDRES",               "")
-
-       define("CFLAGS",                "-g -O2")
-       define("CXXFLAGS",              CFLAGS)
-       define("LDFLAGS",               "")
-       define("LIBS",                  "")
-
-       define("host",                  backtick_run("tools/config.guess"))
-       define("alt_host",              backtick_run("tools/config.sub "..host))
-
-       define("prefix",                "/usr/local")
-       define("eprefix",               prefix)
-       define("bindir",                eprefix.."/bin")
-       define("sbindir",               eprefix.."/sbin")
-       define("libexecdir",    eprefix.."/libexec")
-       define("sysconfdir",    prefix.."/etc")
-       define("localstatedir", prefix.."/var")
-       define("libdir",                eprefix.."/lib")
-       define("includedir",    prefix.."/include")
-       define("datarootdir",   prefix.."/share")
-       define("datadir",               datarootdir.."/"..tarname)
-       define("infodir",               datarootdir.."/info")
-       define("localedir",             datarootdir.."/locale")
-       define("mandir",                datarootdir.."/man")
-       define("docdir",                datarootdir.."/doc/"..tarname)
-
-       if features["dependency-tracking"] == nil then
-               features["dependency-tracking"] = true
-       end
-       
-       if features["special-linking"] == nil then
-               features["special-linking"] = true
-       end
-       
-       define("config",                {})
-       define("define",                {})
-       define("export",                {})
-end
-
-
---
--- Determine special target platforms.
---
-
--- Win32 has some special cases related to its resource file, src/yoinkrc.
-if host:match("mingw32") then platform = "win32" end
-
-
---
--- Look for a working toolchain.
---
-
-print("Please wait...")
-
--- Check for CC.
-tmpname                        = os.tmpname()..".c"
-tmpfile, err   = io.open(tmpname, "w")
-if tmpfile then
-       tmpfile:write([[
-#include <stdio.h>
-int main()
-{
-       printf("Hello world!\n");
-       return 0;
+die () {
+       while read line; do echo $line; done && exit ${1:-127}
 }
-]])
-       tmpfile:close()
-
-       function extra() if not cross_compile then return "gcc", "cc" end end
-       CC = find_command({
-               CC,
-               host.."-gcc", host.."-cc",
-               alt_host.."-gcc", alt_host.."-cc",
-               extra()}, tmpname.." -o "..tmpname..".tmp")
-       os.remove(tmpname)
-       os.remove(tmpname..".tmp")
-       if not CC then die("Can't find a working C compiler.") end
-else
-       die("failed to create temporary file: "..err)
-end
-
--- Check for CXX.
-tmpname                        = os.tmpname()..".cpp"
-tmpfile, err   = io.open(tmpname, "w")
-if tmpfile then
-       tmpfile:write([[
-#include <iostream>
-int main()
-{
-       std::cout << "Hello world!" << std::endl;
-       return 0;
-}
-]])
-       tmpfile:close()
-
-       function extra() if not cross_compile then return "g++", "c++" end end
-       CXX = find_command({
-               CXX,
-               host.."-g++", host.."-c++",
-               alt_host.."-g++", alt_host.."-c++",
-               extra()}, tmpname.." -o "..tmpname..".tmp")
-       os.remove(tmpname)
-       os.remove(tmpname..".tmp")
-       if not CXX then die("Can't find a working C++ compiler.") end
-else
-       die("failed to create temporary file: "..err)
-end
-
--- Check for AR.
-do
-       function extra() if not cross_compile then return "ar" end end
-       AR = find_command({
-               AR,
-               host.."-ar",
-               alt_host.."-ar",
-               extra()}, "--version")
-       if not AR then die("Can't find a working archiver.") end
-end
-
--- Check for RANLIB.
-do
-       function extra() if not cross_compile then return "ranlib" end end
-       RANLIB = find_command({
-               RANLIB,
-               host.."-ranlib",
-               alt_host.."-ranlib",
-               extra()}, "--version")
-       if not RANLIB then die("Can't find a working library indexer.") end
-end
-
--- Check for WINDRES.
-if platform == "win32" then
-       function extra() if not cross_compile then return "windres" end end
-       WINDRES = find_command({
-               WINDRES,
-               host.."-windres",
-               alt_host.."-windres",
-               extra()}, "--version")
-       if not WINDRES then die("Can't find a working resource compiler.") end
-end
-
-
---
--- Configure the features and packages.
---
-
-if get_feature("debug") then
-       set_cflag("-O0")
-       add_cflag("-Wall -Wno-uninitialized")
-       config.DEBUG = true
-else
-       config.NDEBUG = true
-end
-
-config.ENABLE_CLOCK_GETTIME            = get_feature("clock_gettime")
-config.ENABLE_DOUBLE_PRECISION = get_feature("double-precision")
-config.ENABLE_HOTLOADING               = get_feature("hotload")
-config.ENABLE_THREADS                  = get_feature("threads")
-if get_feature("profile") then
-       config.ENABLE_PROFILING = true
-       add_cflag("-pg")
-       LDFLAGS = LDFLAGS .. "-pg"
-end
-
-if get_package("gtk") then config.WITH_GTK = true end
-if get_package("qt4") then config.WITH_QT4 = true end
-
-
---
--- Check for the libraries we need.
---
-
-do
-       local dependencies      = "sdl gl glu libpng openal vorbisfile lua"
-
-       if get_package("gtk") then
-               dependencies = dependencies.." gtk+-2.0"
-       elseif get_package("qt4") then
-               dependencies = dependencies.." QtGui"
-       end
-
-       add_cflag(pkg_config_cflags(dependencies))
-       LDFLAGS         = LDFLAGS       .." "..pkg_config_ldflags(dependencies)
-       LIBS            = LIBS          .." "..pkg_config_libs(dependencies)
-
-       if platform == "win32" then
-               LIBS = LIBS.." -lws2_32"
-               exe_extension = ".exe"
-       else
-               exe_extension = ""
-       end
-end
-
-
---
--- Define the exports and definitions.
---
-
-if platform == "win32" then
-       -- These are used in src/yoink.rc.
-       local vmajor, vminor, vrevis = version:match("^(%d*)%.?(%d*)%.?(%d*)")
-       config.VERSION_MAJOR    = tonumber(vmajor) or 0
-       config.VERSION_MINOR    = tonumber(vminor) or 0
-       config.VERSION_REVISION = tonumber(vrevis) or 0
-end
-
-config.PACKAGE                         = tarname
-config.PACKAGE_NAME                    = project
-config.PACKAGE_VERSION         = version
-config.PACKAGE_STRING          = project.." "..version
-config.PACKAGE_TARNAME         = tarname
-config.PACKAGE_URL                     = website
-config.PACKAGE_BUGREPORT       = contact
-config.YOINK_GITHEAD           = backtick_run("git describe master")
-config.YOINK_DATADIR           = datadir
-
-define.PACKAGE                         = project
-define.TARNAME                         = tarname.."-"..version
-define.TARGET                          = host
-define.PLATFORM                                = platform
-define.CC                                      = CC
-define.CXX                                     = CXX
-define.AR                                      = AR
-define.RANLIB                          = RANLIB
-define.WINDRES                         = WINDRES
-define.CFLAGS                          = reduce_whitespace(CFLAGS)
-define.CXXFLAGS                                = reduce_whitespace(CXXFLAGS)
-define.LDFLAGS                         = reduce_whitespace(LDFLAGS)
-define.LIBS                                    = reduce_whitespace(LIBS)
-define.prefix                          = prefix
-define.bindir                          = bindir
-define.datadir                         = datadir
-define.mandir                          = mandir
-define.EXEEXT                          = exe_extension
-define.DEP_TRACKING                    = get_feature("dependency-tracking")
-define.DEP_MINIMIZING          = get_feature("special-linking")
-
-export.datadir                         = datadir               -- Used in doc/yoink.6.in.
-export.PACKAGE_BUGREPORT       = contact               -- Used in doc/yoink.6.in.
-
-
---
--- All done; output the configuration files.
---
-
--- Output the program options.
-output = io.open("config.h", "w")
-for key,value in pairs(config) do
-       key = tostring(key)
-       if type(value) == "boolean" then
-               if value then
-                       output:write("#define "..key.." 1")
-               else
-                       output:write("#undef "..key)
-               end
-       elseif type(value) == "string" then
-               output:write(string.format("#define %s %q", key, tostring(value)))
-       else
-               output:write(string.format("#define %s %s", key, tostring(value)))
-       end
-       output:write("\n")
-end
-output:close()
-
--- Output the make definitions.
-output = io.open("config.mk", "w")
-for key,value in pairs(define) do
-       key             = tostring(key)
-       value   = tostring(value)
-       output:write(string.format("%s = %s\n", key, value))
-end
-output:close()
-
 
--- Output the exported variables.
-output = io.open("config.sed", "w")
-for key,value in pairs(export) do
-       key             = key:gsub("/", "\\/")
-       value   = value:gsub("/", "\\/")
-       output:write(string.format("s/@%s@/%s/g\n", key, value))
-end
-output:close()
+[ -f build/config.lua ] || die 1 <<"END"
+You must first `cd' to the project directory root where the Makefile is.
+There is no support for out-of-tree builds.
+END
 
+LUA=${LUA:-lua}
+"$LUA" -v >/dev/null 2>&1 || die 2 <<END
+Can't find a Lua interpreter in your PATH.  Make sure Lua is installed, or
+set the LUA variable in the environment to the path of lua.
+END
 
-print([[
+unset MAKEFLAGS
+echo "$@" | grep -w -e --interactive >/dev/null && \
+       ! (cd build && ${MAKE:-make} dialog) && die 3 <<END
+The dialog module cannot be built and so the configure script cannot be
+used interactively.  Run the configure script non-interactively.
+END
 
- Configuration complete!  You can review your configuration in `config.mk'.
+export PATH="./build:$PATH"
+exec "$LUA" build/config.lua "$@" -L./build
 
- To finish the installation, type:
-  make
-  make install
-]])
+# vi:ts=4
 
This page took 0.030379 seconds and 4 git commands to generate.