-#!/usr/bin/env lua
+#!/bin/sh
---
--- Yoink
--- Execute this file to configure the build system.
---
+#
+# Yoink
+# Execute this file to configure the build system.
+#
-project = "Yoink"
-version = "0.1"
-bugreport = "chaz@dogcows.com"
-
-
-function ShowHelp()
- 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
- --enable-link-sh decrease the number of direct dependencies
-
-Program options:
- --enable-debug include debugging symbols and code paths
- --enable-double-precision use doubles instead of floats
- --enable-profile compile in gprof profiling instructions
- --enable-clock_gettime use clock_gettime() for timing
- --enable-threads use threads for concurrency
- --enable-hotloading watch assets for automatic reloading
-
- --with-gtk use the gtk2 toolkit (overrides --with-qt4)
- --with-qt4 use the qt4 gui toolkit
-]])
-end
-
-
---
--- Define some useful functions.
---
-
-function Die(...)
- for _,value in ipairs(arg) do
- print("fatal: "..tostring(value))
- end
- os.exit(1)
-end
-
-function FileExists(file)
- return os.execute("test -f "..file) == 0
-end
-
-function ReadCommand(command)
- local fd = io.popen(command)
- if fd then
- local stdout = fd:read("*l")
- fd:close()
- return stdout
- end
- return nil
-end
-
-function TryCommand(command)
- return os.execute(command.." 2>&1 >/dev/null") == 0
-end
-
-function Trim(str)
- str = str:gsub("^%s+", "")
- return str:gsub("%s+$", "")
-end
-
-function Reduce(str)
- str = str:gsub("%s+", " ")
- return Trim(str)
-end
-
-
---
--- Perform a quick sanity check.
---
-
-if not FileExists("configure") or not FileExists("Makefile") then
- Die("You must `cd' to the project root where the Makefile is.")
-end
-
-
---
--- Parse the command-line options.
---
-
-do
- local features = {}
- local packages = {}
- local directories = {}
- local definitions = {}
-
- local function AddFeature(feature, value)
- if value == "yes" or value == "" then value = true end
- if value == "no" then value = false end
- features[feature] = value
- end
-
- local function AddPackage(package, value)
- if value == "yes" or value == "" then value = true end
- if value == "no" then value = false end
- packages[package] = value
- end
-
- local function AddDirectory(directory, path)
- directories[directory] = path
- end
-
- local function AddDefinition(key, value)
- definitions[key] = value
- end
-
- local handlers = {
- ["--help"] = function() ShowHelp() os.exit(0) end,
- ["--host=(.+)"] = function(arg) host = arg cross_compile = true end,
- ["--enable%-([%w_-]+)=?(.*)"] = AddFeature,
- ["--disable%-([%w_-]+)"] = function(arg) AddFeature(arg, "no") end,
- ["--with%-([%w_-]+)=?(.*)"] = AddPackage,
- ["--without%-([%w_-]+)"] = function(arg) AddPackage(arg, "no") end,
- ["--(%l+)dir=(.+)"] = AddDirectory,
- ["--prefix=(.+)"] = function(arg) prefix = arg end,
- ["--exec-prefix=(.+)"] = function(arg) eprefix = arg end,
- ["([%w_]+)=(.*)"] = AddDefinition,
- }
- handlers["-h"] = handlers["--help"]
-
- local function ParseArg(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
-
-
- -- Define some default values.
-
- prefix = "/usr/local"
-
- CC = ""
- CXX = ""
- AR = ""
- RANLIB = ""
- WINDRES = ""
-
- CFLAGS = "-g -O2"
- CXXFLAGS = CFLAGS
- LDFLAGS = ""
- LIBS = ""
-
- features["dependency-tracking"] = true
-
-
- -- Read the arguments from the command-line.
- for _,arg in ipairs(arg) do
- ParseArg(arg)
- end
-
- function GetFeature(feature) return features[feature] end
- function GetPackage(package) return packages[package] end
-
- for key,value in pairs(directories) do
- _G[key.."dir"] = value
- end
- for key,value in pairs(definitions) do
- _G[key] = value
- end
-
-
- -- Define the dependent values.
-
- package = project:lower()
- tarname = package.."-"..version
-
- if not host then host = ReadCommand("tools/config.guess") end
- alt_host = ReadCommand("tools/config.sub "..host)
-
- if not eprefix then eprefix = prefix end
- if not bindir then bindir = eprefix.."/bin" end
- if not sbindir then sbindir = eprefix.."/sbin" end
- if not libexecdir then libexecdir = eprefix.."/libexec" end
- if not sysconfdir then sysconfdir = prefix.."/etc" end
- if not localstatedir then localstatedir = prefix.."/var" end
- if not libdir then libdir = eprefix.."/lib" end
- if not includedir then includedir = prefix.."/include" end
- if not datarootdir then datarootdir = prefix.."/share" end
- if not datadir then datadir = datarootdir.."/"..package end
- if not infodir then infodir = datarootdir.."/info" end
- if not localedir then localedir = datarootdir.."/locale" end
- if not mandir then mandir = datarootdir.."/man" end
- if not docdir then docdir = datarootdir.."/doc/"..package end
-
- cflags = ""
- config = {}
- define = {}
- export = {}
-
- define.DEP_TRACKING = GetFeature("dependency-tracking")
-end
-
-
---
--- Determine the target platform.
---
-
-if host:match("mingw32") then platform = "win32"
-elseif host:match("netbsd") then platform = "netbsd" end
-
-
---
--- Define the check function.
---
-
-do
- local path = os.getenv("PATH")
-
- -- 1. List of possible command names.
- -- 2. Command arguments.
- function FindCommand(commands, args)
- if not args then args = "" end
- for _,command in ipairs(commands) do
- if command then
- for dir in path:gmatch("[^:]+") do
- if FileExists(dir.."/"..command) and TryCommand(command.." "..args) then
- return command
- end
- end
- end
- end
- return nil
- end
-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 = FindCommand({
- 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()..".c"
-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 = FindCommand({
- 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 = FindCommand({
- 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 = FindCommand({
- 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 = FindCommand({
- WINDRES,
- host.."-windres",
- alt_host.."-windres",
- extra()}, "--version")
- if not WINDRES then Die("Can't find a working win32 resource compiler.") end
-end
-
-
---
--- Configure the features and packages.
---
-
-if GetFeature("debug") then
- cflags = cflags.." -O0 -Wall -Wno-uninitialized"
- config.DEBUG = true
-else
- config.NDEBUG = true
-end
-
-if GetFeature("double-precision") then
- config.USE_DOUBLE_PRECISION = true
-end
-
-if GetFeature("profile") then
- cflags = cflags.." -pg"
- config.PROFILING_ENABLED = true
-end
-
-if GetFeature("extra-warnings") then
- cflags = cflags.." -Wextra -Wno-unused-parameter"
-end
-
-if GetFeature("link-sh") then
- -- TODO
-end
-
-if GetFeature("clock_gettime") then
- -- TODO
-end
-
-if GetFeature("threads") then
- config.USE_THREADS = true
-end
-
-if GetFeature("hotloading") then
- print("FYI: Hotloading is very experimental and only works on Linux.");
- config.USE_HOTLOADING = true
-end
-
-if GetPackage("gtk") then
- -- TODO
-end
-
-if GetPackage("qt4") then
- -- TODO
-end
-
-
---
--- Check for the libraries we need.
---
-
-do
- local command = "PKG_CONFIG_PATH="..libdir.."/pkgconfig:$PKG_CONFIG_PATH pkg-config"
- local deps = "sdl gl glu libpng openal vorbisfile lua"
-
- if GetPackage("gtk") then
- deps = deps.." gtk+-2.0"
- elseif GetPackage("qt4") then
- deps = deps.." QtGui"
- end
-
- local pc_cflags = ReadCommand(command.." --cflags "..deps)
- if not pc_cflags then Die("Couldn't determine CFLAGS.") end
- CFLAGS = CFLAGS.." "..pc_cflags
- CXXFLAGS = CXXFLAGS.." "..pc_cflags
-
- local pc_libs = ReadCommand(command.." --libs "..deps)
- if not pc_libs then Die("Couldn't determine LDFLAGS or LIBS.") end
- for lib in pc_libs:gmatch("%-l%S+") do
- LIBS = LIBS.." "..lib
- end
- for ldflag in pc_libs:gmatch("%-[^l]%S*") do
- LDFLAGS = LDFLAGS.." "..ldflag
- end
-
- if platform == "win32" then
- LIBS = LIBS.." -lws2_32"
- exe_extension = ".exe"
- else
- exe_extension = ""
- end
-end
-
-CFLAGS = Reduce(CFLAGS.." "..cflags)
-CXXFLAGS = Reduce(CXXFLAGS.." "..cflags)
-LDFLAGS = Reduce(LDFLAGS)
-LIBS = Reduce(LIBS)
-
-
---
--- Define the exports and definitions.
---
-
-config.YOINK_DATADIR = datadir
-export.YOINK_DATADIR = datadir
-
-do
- local vmajor = ReadCommand("v=$(echo "..version.." | cut -d. -f1); echo ${v:-0}")
- local vminor = ReadCommand("v=$(echo "..version.." | cut -d. -f2); echo ${v:-0}")
- local vrevis = ReadCommand("v=$(echo "..version.." | cut -d. -f3); echo ${v:-0}")
-
- config.VERSION_MAJOR = tonumber(vmajor)
- config.VERSION_MINOR = tonumber(vminor)
- config.VERSION_REVISION = tonumber(vrevis)
-end
-
-do
- -- Determine and define the git revision.
- local head = ReadCommand("git describe master")
- config.YOINK_GITHEAD = head
-end
-
-config.PACKAGE = project
-config.PACKAGE_NAME = project
-config.VERSION = version
-config.PACKAGE_VERSION = version
-config.PACKAGE_STRING = project.." "..version
-config.PACKAGE_BUGREPORT = bugreport
-
-define.PACKAGE = project
-define.TARNAME = tarname
-define.TARGET = host
-define.PLATFORM = platform
-define.CC = CC
-define.CXX = CXX
-define.AR = AR
-define.RANLIB = RANLIB
-define.WINDRES = WINDRES
-define.CFLAGS = CFLAGS
-define.CXXFLAGS = CXXFLAGS
-define.LDFLAGS = LDFLAGS
-define.LIBS = LIBS
-define.prefix = prefix
-define.bindir = bindir
-define.datadir = datadir
-define.mandir = mandir
-define.EXEEXT = exe_extension
-
-export.PACKAGE_BUGREPORT = bugreport
-
-
---
--- All done; output the configuration files.
---
-
--- Print 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)
- 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()
-
--- Print 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()
-
-
--- Print 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()
-
-
-print([[
-
- Configuration complete! You can review your configuration in `config.mk'.
- To finish the installation, type:
- make
- make install
-]])
+[ -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-source-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
+
+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
+
+export PATH="./build:$PATH"
+exec "$LUA" build/config.lua "$@" -L./build