X-Git-Url: https://git.dogcows.com/gitweb?p=chaz%2Fyoink;a=blobdiff_plain;f=configure;h=d4435162569e366a992f552e31ac3cdaff3added;hp=06a303d39c002ec9a9432ca170dd8178f0be31f7;hb=51069fee9139ab8d14ecc80dffbe5deecb73d9e0;hpb=7ac3aee9efa7f9ce1a966df030b1f76f2b82ef2d diff --git a/configure b/configure index 06a303d..d443516 100755 --- a/configure +++ b/configure @@ -1,448 +1,609 @@ -#!/bin/sh - -# -# Yoink -# Execute this file to configure the build system. -# - -PACKAGE="Yoink" -VERSION="0.1" -BUGREPORT="chaz@dogcows.com" - - -showhelp() -{ - cat <<"END" - -This script prepares Yoink for building on your system. +#!/usr/bin/env lua + +-- +-- 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 program to run on HOST + --host=HOST cross-compile the program to run on HOST - --prefix=DIR base directory to install program + --prefix=DIR base directory to install programs to --bindir=DIR directory to install executables - --libdir=DIR directory to install libraries --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-double-precision use doubles instead of floats --enable-profile compile in gprof profiling instructions - --enable-extra-warnings make the gcc compiler give more warnings - --enable-link-sh try to decrease the number of direct dependencies - --enable-clock_gettime use clock_gettime() instead of SDL - --enable-threads use threads for concurrency where appropriate - --enable-hotloading monitor assets and reload them when they change - - --with-gtk use gtk2 modal dialogs - --with-qt4 use qt4 modal dialogs; overridden by --with-gtk - -END -} - -. "build/functions.sh" - - -# -# Perform a quick sanity check. -# - -test -f configure -a -f Makefile || die <<"END" -You must `cd' to the project root directory where the Makefile resides. -END - - -# -# Define some default values. -# - -CC="" -CXX="" -AR="" -RANLIB="" + --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 + + +-- +-- Setup a temporary file to collect error messages. +-- + +error_log = "config.log" +os.remove(error_log) + + +-- +-- Define some useful functions. +-- + +-- Return true if a file exists, false otherwise. +function file_exists(file) + return os.execute("test -f "..file) == 0 +end + +-- Print an error message and exit with an error. +function die(...) + for _,value in ipairs(arg) do + print("fatal: "..tostring(value)) + end + if file_exists(error_log) then + print() + print("Look through the file `config.log' for more information:\n") + os.execute("tail "..error_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) + local fd = io.popen(command.." 2>>"..error_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) + return os.execute(command.." >/dev/null 2>>"..error_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 _,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. -CFLAGS="-g -O2" -CXXFLAGS="$CFLAGS" -LDFLAGS="" -LIBS="" - -prefix='/usr/local' -bindir='$prefix/bin' -libdir='$prefix/lib' -datadir='$prefix/share/yoink' -mandir='$prefix/share/man' - -host=$(./build/config.guess) -althost=$(./build/config.sub $host) -cross_compile="no" - - -# -# Parse the command-line options. -# - -for opt in "$@" -do - case $opt in - -h|--help) - showhelp - exit 0 - ;; - - --host=*) - host=$(parse_argument host $opt) - cross_compile="yes" - ;; - --prefix=*) - prefix=$(parse_argument prefix $opt) - ;; - --bindir=*) - bindir=$(parse_argument bindir $opt) - ;; - --libdir=*) - libdir=$(parse_argument libdir $opt) - ;; - --datadir=*) - datadir=$(parse_argument datadir $opt) - ;; - --mandir=*) - mandir=$(parse_argument mandir $opt) - ;; - - --enable-debug) - cflags="$cflags -O0 -Wall -Wno-uninitialized" - define "DEBUG" - ;; - --enable-double-precision) - define "USE_DOUBLE_PRECISION" - ;; - --enable-profile) - cflags="$cflags -pg" - define "PROFILING_ENABLED" - ;; - --enable-extra-warnings) - cflags="$cflags -Wextra -Wno-unused-parameter" - ;; - --enable-link-sh) - link_sh=yes - ;; - --enable-clock_gettime) - clock_gettime=yes - ;; - --enable-threads) - define "USE_THREADS" - ;; - --enable-hotloading) - define "USE_HOTLOADING" - ;; - --with-gtk) - gtk=yes - ;; - --with-qt4) - qt4=yes - ;; - *) - if echo "$opt" | grep -q '^[A-Za-z0-9_]*=.*' - then - export "$opt" - else - echo "warning: unknown option: $opt" - fi - ;; - esac -done - - -# -# Evaluate any dependent paths. -# - -eval bindir="$bindir" -eval datadir="$datadir" -eval libdir="$libdir" -eval mandir="$mandir" - -is_defined "DEBUG" || define "NDEBUG" - -export PKG_CONFIG_PATH="$libdir/pkgconfig:$PKG_CONFIG_PATH" - -define_string "YOINK_DATADIR" "$datadir" - - -# -# Determine the target platform. -# - -case $host in - *mingw32*) HOST=win32 ;; - *netbsd*) HOST=netbsd ;; -esac - - -# -# Define the check functions. -# - -# Run a command and return its exit code. If the third argument is given, -# stdin will be read and written to the specified file before the command -# is executed. If the command creates any files inside the current -# directory, they will be removed automatically. -# $1 The command to run. -# $2 The arguments to be passed to the command. -# $3 Optional filename where stdin will be written. -check_run_command() -{ - tmpdir=$(mktemp -d "tmp-XXXXXXXX") || die "could not create temp directory" - cd $tmpdir || die "could not enter temp directory" - - if test "x$3" != x - then - while read line - do - echo $line - done >$3 - fi - - saved_ifs=$IFS - IFS=: - for path in $PATH - do - if test -x "$path/$1" - then - eval "$1 $2" 2>&1 >/dev/null - exit_code=$? - - cd .. - rm -rf $tmpdir - IFS=$saved_ifs - return $exit_code - fi - done - - cd .. - rm -rf $tmpdir - IFS=$saved_ifs - return 1 -} - - -# -# Do some common checks. -# - -if test "x$cross_compile" = xno -then - # If we are not cross-compiling, we also want to consider tools without - # host prefixes. - extra_cc="gcc cc" - extra_cxx="g++ c++" - extra_ar="ar" - extra_ranlib="ranlib" - extra_windres="windres" -fi - -for exe in $CC $host-gcc $host-cc $althost-gcc $althost-cc $extra_cc do - if check_run_command "$exe" "test.c" "test.c" <<"END" + 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 _,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 not features["dependency-tracking"] then + features["dependency-tracking"] = 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 int main() { printf("Hello world!\n"); return 0; } -END - then - CC="$exe" - break - fi -done - -for exe in $CXX $host-g++ $host-c++ $althost-g++ $althost-c++ $extra_cxx -do - if check_run_command "$exe" "test.cpp" "test.cpp" <<"END" +]]) + 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()..".c" +tmpfile, err = io.open(tmpname, "w") +if tmpfile then + tmpfile:write([[ #include int main() { std::cout << "Hello world!" << std::endl; return 0; } -END - then - CXX="$exe" - break - fi -done - -for exe in $AR $host-ar $althost-ar $extra_ar +]]) + 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 - if check_run_command "$exe" "--version" - then - AR="$exe" - break - fi -done - -for exe in $RANLIB $host-ranlib $althost-ranlib $extra_ranlib + 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 - if check_run_command "$exe" "--version" - then - RANLIB="$exe" - break - fi -done - -if test x$HOST = xwin32 -then - for exe in $WINDRES $host-windres $althost-windres $extra_windres - do - if check_run_command "$exe" "--version" - then - WINDRES="$exe" - break - fi - done -fi - -if test "x$CC" = x -o "x$CXX" = x -o "x$AR" = x -o "x$RANLIB" = x -then - die <config.mk <