New, custom build system.

git-svn-id: svn://svn.code.sf.net/p/sc2/code/trunk@220 8092fc87-c524-0410-9efc-e669fe64eaf9
This commit is contained in:
meep-eep
2002-11-20 03:47:25 +00:00
parent ca9a9a3a08
commit 337c063cc4
125 changed files with 1672 additions and 775 deletions
+21
View File
@@ -0,0 +1,21 @@
ESC=""
ANSI_BOLD="${ESC}[1m"
ANSI_NORMAL="${ESC}[0m"
ANSI_BLK="${ESC}[30m"
ANSI_RED="${ESC}[31m"
ANSI_GRN="${ESC}[32m"
ANSI_YLW="${ESC}[33m"
ANSI_BLU="${ESC}[34m"
ANSI_MGN="${ESC}[35m"
ANSI_CYN="${ESC}[36m"
ANSI_WHT="${ESC}[37m"
ANSI_LBLK="${ESC}[1;30m"
ANSI_LRED="${ESC}[1;31m"
ANSI_LGRN="${ESC}[1;32m"
ANSI_LYLW="${ESC}[1;33m"
ANSI_LBLU="${ESC}[1;34m"
ANSI_LMGN="${ESC}[1;35m"
ANSI_LCYN="${ESC}[1;36m"
ANSI_LWHT="${ESC}[1;37m"
+141
View File
@@ -0,0 +1,141 @@
#!/bin/sh
# Include build functions used here
. build/config_functions
. build/menu_functions
. build/ansi
# Some requirements:
have_program gcc 2.95.3 || exit 1
COMPILE="$PROG_gcc_FILE"
# Define WORDS_BIGENDIAN on bigendian machines
check_endianness
# Libraries used
use_library SDL 1.2.3 || exit 1
use_library SDL_image || exit 1
#have_library vorbis || exit 1
have_library vorbisfile || exit 1
# Add defines for HAVE_STRUPR and STRICMP
define_have_symbol strupr
define_have_symbol stricmp
# Describe the menu:
MENU_main_ITEMS="debug graphics sound link install_path"
MENU_main_TITLE="Main menu"
MENU_main_ITEM_debug_TYPE=CHOICE
MENU_main_ITEM_graphics_TYPE=CHOICE
MENU_main_ITEM_sound_TYPE=CHOICE
MENU_main_ITEM_link_TYPE=CHOICE
MENU_main_ITEM_install_path_TYPE=MENU
CHOICE_debug_OPTIONS="debug nodebug"
CHOICE_debug_TITLE="Include debugging information"
CHOICE_debug_OPTION_debug_TITLE="Debugging information"
CHOICE_debug_OPTION_debug_ACTION='debug_action'
debug_action() {
CFLAGS="$CFLAGS -g -O0"
LDFLAGS="$LDFLAGS -O0"
DEBUG=1
}
CHOICE_debug_OPTION_nodebug_TITLE="No debugging information"
CHOICE_debug_OPTION_nodebug_ACTION='debug_action'
nodebug_action() {
CFLAGS="$CFLAGS -O3"
DEBUG=0
}
CHOICE_debug_DEFAULT=debug
CHOICE_graphics_OPTIONS="pure opengl"
CHOICE_graphics_TITLE="OpenGL graphics support"
CHOICE_graphics_OPTION_pure_TITLE="Don't include OpenGL graphics support"
CHOICE_graphics_OPTION_pure_ACTION='graphics_pure_action'
graphics_pure_action() {
CFLAGS="$CFLAGS -DGFXMODULE_SDL"
HAVE_OPENGL=0
}
CHOICE_graphics_OPTION_opengl_TITLE="Include OpenGL graphics support"
CHOICE_graphics_OPTION_opengl_ACTION='graphics_opengl_action'
CHOICE_graphics_OPTION_opengl_PRECOND="have_library opengl"
graphics_opengl_action() {
CFLAGS="$CFLAGS -DGFXMODULE_SDL -DHAVE_OPENGL"
HAVE_OPENGL=1
use_library opengl
}
CHOICE_graphics_DEFAULT=opengl
CHOICE_sound_OPTIONS="SDL_mixer openal"
CHOICE_sound_TITLE="Sound backend"
CHOICE_sound_OPTION_SDL_mixer_TITLE="Use SDL_mixer for sound"
CHOICE_sound_OPTION_SDL_mixer_PRECOND="have_library SDL_mixer"
CHOICE_sound_OPTION_SDL_mixer_ACTION='
eval SOUNDMODULE=sdl;
use_library SDL_mixer'
CHOICE_sound_OPTION_openal_TITLE="Use OpenAL for sound (experimental)"
CHOICE_sound_OPTION_openal_PRECOND="have_library openal"
CHOICE_sound_OPTION_openal_ACTION='
eval CFLAGS="$CFLAGS -DSOUNDMODULE_OPENAL";
eval SOUNDMODULE=openal;
use_library openal;
use_library vorbisfile'
# use_library vorbis;
CHOICE_sound_DEFAULT=SDL_mixer
CHOICE_link_OPTIONS="static dynamic"
CHOICE_link_TITLE="Linking"
CHOICE_link_OPTION_static_TITLE="Statically linked libraries"
CHOICE_link_OPTION_static_ACTION='eval LDFLAGS="$LDFLAGS -static"'
CHOICE_link_OPTION_dynamic_TITLE="Dynamically linked libraries"
CHOICE_link_DEFAULT=dynamic
MENU_install_path_ITEMS="install_prefix install_bindir install_libdir"
MENU_install_path_TITLE="Installation paths"
MENU_install_path_ITEM_install_prefix_TYPE=INPUT
MENU_install_path_ITEM_install_libdir_TYPE=INPUT
MENU_install_path_ITEM_install_bindir_TYPE=INPUT
INPUT_install_prefix_DEFAULT="/usr/local/games"
INPUT_install_prefix_TITLE="Installation prefix"
INPUT_install_prefix_VALIDATOR=validate_path
INPUT_install_prefix_ACTION='eval INSTALL_PREFIX=$MENU_install_prefix_VALUE'
INPUT_install_bindir_DEFAULT='$prefix/bin'
INPUT_install_bindir_TITLE="Location for binaries"
INPUT_install_bindir_VALIDATOR=validate_path
INPUT_install_libdir_DEFAULT='$prefix/lib'
INPUT_install_libdir_TITLE="Location for libraries"
INPUT_install_libdir_VALIDATOR=validate_path
# Show the menu and let people set things
do_menu main
# Set INSTALL_LIBDIR and INSTALL_BINDIR by to their set values, replacing
# '$prefix' to the prefix set.
prefix="$INPUT_install_prefix_VALUE" \
eval INSTALL_LIBDIR="${INPUT_install_libdir_VALUE%/}/"
prefix="$INPUT_install_prefix_VALUE" \
eval INSTALL_BINDIR="${INPUT_install_bindir_VALUE%/}/"
# Set the content dir
CONTENTDIR="${INSTALL_LIBDIR}uqm/content"
# Make build.vars from build.vars.in, substituting variables.
SUBSTITUTE_VARS="CFLAGS LDFLAGS MAKE DEBUG SOUNDMODULE HAVE_OPENGL"
SUBSTITUTE_FILES="build.vars"
substitute_vars SUBSTITUTE_VARS SUBSTITUTE_FILES
# Export the HAVE_ symbols to config.h, using config.h.in as template
SUBSTITUTE_VARS="$HAVE_SYMBOLS CONTENTDIR"
SUBSTITUTE_FILES="src/config.h"
substitute_vars SUBSTITUTE_VARS SUBSTITUTE_FILES
+116
View File
@@ -0,0 +1,116 @@
I've made this build system as a replacement for autoconf, autoheader,
automake, and aclocal as I found them to be too limiting and too slow.
This build system is not as complete as the auto* tools, but it's very
easy to extend.
Some of the most important differences between this system and autoconf:
- it has a menu-driven configuration
- when compiling, the current directory will never change
- the object files are stored in a seperate tree from the source files,
leaving the latter clean, and easier grep-able.
- multiple object trees can be used, so you can have for instance a
debugging tree and a release tree side by side.
- it builds faster, mostly because libtool isn't used.
The menu
--------
There are three types of menu items.
- Type MENU
A menu with menu items.
- Variables:
- MENU_${NAME}_TITLE
The title of the menu.
- MENU_${NAME}_ITEMS
The names of the menu items (space-seperated).
- MENU_${NAME}_ITEM_${ITEMNAME}_TYPE
The type of a menu item.
- Type CHOICE:
A choice between several options.
- Variables:
- CHOICE_${NAME}_TITLE
The title of the choice menu.
- CHOICE_${NAME}_OPTIONS
The names of the options (space-seperated).
- CHOICE_${NAME}_OPTION_${OPTIONNAME}_TITLE
The title of a menu option.
- CHOICE_${NAME}_OPTION_${OPTIONNAME}_ACTION
A command to be evaluated if this option is used.
- CHOICE_${NAME}_OPTION_${OPTIONNAME}_VALID (set by the config program)
0 if the choice has been verified to be a valid choice
1 if the choice has been verified to be not a valid choice
<empty> if the choice hasn't been verified to be valid
- CHOICE_${NAME}_DEFAULT (optional)
The default choice.
- CHOICE_${NAME}_VALUE (set by the config program)
The current choice.
- Type INPUT:
A string that is user-definable.
- Variables:
- INPUT_${NAME}_DEFAULT (optional)
The default value.
- INPUT_${NAME}_TITLE
The title of the input field.
- INPUT_${NAME}_VALIDATOR (optional)
A function to call after the user supplied a new value which
checks if the value is allowed. It should accept the new value as
an argument, and return 1 if the value is not allowed, or return 0
and output the (possibly modified) value, to accept it.
- INPUT_${NAME}_VALUE (set by the config program)
The current value.
- INPUT_${NAME}_OLD_VALUE (set by the config program)
The value as it was at the start of the config program.
Program info
------------
Information about programs used should be supplied in the following form:
- PROG_${PROGRAM}_NAME
A string describing the program.
- PROG_${PROGRAM}_FILE
A string that evaluates to the executable that should be present if
this program is used.
- PROG_${PROGRAM}_ACTION (optional)
A command to be executed if this program is used, after the user is
done configuring.
- PROG_${PROGRAM}_DETECT (optional)
A command to be executed which should return 0 if the program is present
on the system, or 1 otherwise. If not supplied, 'type' is
used to check for the program in the path.
- PROG_${PROGRAM}_VERSION (optional)
A string that evaluates to the version of the executable that is
present, if it is present.
- PROG_${PROGRAM}_PRESENT (set by the configuration program)
0 if the program has been verified to be present
1 if the program has been verified to be not present
<empty> if the program hasn't been verified to be present
Library info
------------
Information about libraries used should be supplied in the following form:
- LIB_${LIB}_NAME
A string describing the program.
- LIB_${LIB}_CFLAGS
A string which evaluates to the string to add to CFLAGS if this library
is used.
- LIB_${LIB}_LDLAGS
A string which evaluates to the string to add to LDLAGS if this library
is used.
- PROG_${LIB}_DETECT (optional)
A command to be executed which should return 0 if the library is present
on the system, or 1 otherwise. If not supplied, an attempt is
made to compile and link an empty C program with the flags as in
LIB_${LIB}_CFLAGS and LIB_${LIB}_LDFLAGS.
- LIB_${LIB}_VERSION (optional)
A string that evaluates to the version of the library that is
present, if it is present.
- LIB_${PROGRAM}_PRESENT (set by the configuration program)
0 if the library has been verified to be present
1 if the library has been verified to be not present
<empty> if the library hasn't been verified to be present
+111
View File
@@ -0,0 +1,111 @@
#!/bin/sh
# Build script
# Copyright (c) 2002 Serge van den Boom
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
# This file contains functions for the general building procedure.
# You shouldn't need to change this file if your project changes.
# Read in the functions we need
. build/build_functions
# Read in the config settings that affect the build, if present.
# Don't reread for every dir when recursing.
if [ -e build.vars -a -z "$BUILD_COMMAND" ]; then
. build.vars
fi
# Read in the Makeinfo file for the dir currently being processed
. "${BUILD_REC_PATH}Makeinfo"
# If we're recursing, go on.
if [ -n "$BUILD_COMMAND" ]; then
$BUILD_COMMAND
exit $?
fi
for VAR in TARGETS "$BUILD_PROJECT_NAME" "$BUILD_PROJECT_OBJS"; do
eval VALUE="\$$VAR"
if [ -z "$VALUE" ]; then
echo "$VAR needs to be defined in the top Makeinfo file"
exit 1
fi
done
##############################################
### Everything below is parsing user input ###
TOPDIR="$PWD"
export TOPDIR
if [ $# -lt 1 ]; then
usage 1>&2
exit 1;
fi
case "$1" in
cleanall)
build_cleanall
exit $?
;;
distclean)
build_distclean
exit $?
;;
esac
unset TARGET
for TEMP in $TARGETS; do
if [ "$1" = "$TEMP" ]; then
TARGET="$1"
break
fi
done
if [ -z "$TARGET" ]; then
echo "Invalid target; choose one from:"
echo " $TARGETS"
exit 1
fi
BUILD_PROJECT="$TARGET"
export TARGET BUILD_PROJECT COMPILE MKDEPEND
export "${BUILD_PROJECT}_CFLAGS" "${BUILD_PROJECT}_LDFLAGS"
# Add trailing / from objs dir
eval ${BUILD_PROJECT}_OBJS=\${${BUILD_PROJECT}_OBJS%/}/
export "${BUILD_PROJECT}_OBJS"
if [ $# -lt 2 ]; then
build_check_config
build_check_dependencies
build_compile
exit $?
fi
case "$2" in
clean)
build_clean
;;
config)
build_config
;;
depend)
build_check_config
build_rec_dependancies
;;
*)
;;
esac
+165
View File
@@ -0,0 +1,165 @@
# Auxiliary functions for build.sh
# Copyright (c) 2002 Serge van den Boom
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
# Show usage information
usage() {
echo "Main build script"
echo
echo "Syntax:"
echo " ./build <target>"
echo " ./build <target> config"
echo " ./build <target> depend"
echo " ./build <target> clean"
echo " ./build <target> install"
echo " ./build cleanall"
echo " ./build distclean"
echo
echo "Valid targets:"
for TARGET in $TARGETS; do
echo " $TARGET"
done
echo
}
# The actual recursing function
build_recurse() {
local FILES SUBDIRS
# Perform an action for this dir
eval FILES="\${$BUILD_FILES_VAR}"
for FILE in $FILES; do
$BUILD_REC_COMMAND "$BUILD_REC_PATH$FILE"
done
# Recurse for all subdirs
eval SUBDIRS="\$${BUILD_PROJECT}_SUBDIRS"
for DIR in $SUBDIRS; do
BUILD_REC_PATH="$BUILD_REC_PATH$DIR/" $SH "$0"
$BUILD_REC_DIR_COMMAND "$BUILD_REC_PATH$DIR"
done
}
# Start the recursion
build_do_recursive() {
BUILD_COMMAND=build_recurse
BUILD_REC_COMMAND="$1"
BUILD_REC_DIR_COMMAND="$2"
export BUILD_COMMAND BUILD_REC_COMMAND BUILD_REC_DIR_COMMAND
build_recurse
}
# Build dependancy information for one file
build_dependancies() {
eval echo -n \${${BUILD_PROJECT}_OBJS}\$BUILD_REC_PATH
eval \$MKDEPEND "\${${BUILD_PROJECT}_CFLAGS}" "\$1"
}
# Recursively build dependancy information
build_rec_dependancies() {
local DEPEND_FILE
echo "Building dependancy information..." 1>&2
BUILD_FILES_VAR=${BUILD_PROJECT}_CFILES
export BUILD_FILES_VAR
OFILES=`build_do_recursive build_collect_o_files :`
eval DEPEND_FILE=".depend.\${${BUILD_PROJECT}_NAME}"
{
eval echo -n "target-\${${BUILD_PROJECT}_NAME}:"
for OFILE in $OFILES; do
echo -n " $OFILE"
done
echo
build_do_recursive build_dependancies :
} > "$DEPEND_FILE"
}
# Output the .o file for a .c file.
build_collect_o_files() {
eval echo "\${${BUILD_PROJECT}_OBJS}\${1%.c}.o"
}
# Recursively collect .o-files
build_rec_collect_o_files() {
BUILD_FILES_VAR=${BUILD_PROJECT}_CFILES
export BUILD_FILES_VAR
build_do_recursive build_collect_o_files :
}
# Start the configure program.
build_config() {
$SH build/build.config
}
# Compile the lot.
# With the depend info set up, we can leave everything to make.
build_compile() {
eval CFLAGS="\${${BUILD_PROJECT}_CFLAGS}" \
LDFLAGS="\${${BUILD_PROJECT}_LDFLAGS}" \
DEPEND_FILE=".depend.\${${BUILD_PROJECT}_NAME%/}" \
\$MAKE -f Makefile.build "target-\${${BUILD_PROJECT}_NAME}"
}
# Description: Remove the .o file for one .c file
# Arguments: $1 - the .c file
build_clean_file() {
eval rm -f -- "\${${BUILD_PROJECT}_OBJS}\${1%.c}.o"
}
build_clean_dir() {
eval rmdir -- "\${${BUILD_PROJECT}_OBJS}\${1}" 2> /dev/null
return 0
}
build_clean() {
local DEPEND_FILE
eval DEPEND_FILE=".depend.\${${BUILD_PROJECT}_NAME%/}"
rm -f "$DEPEND_FILE" build.vars config.state src/config.h
BUILD_FILES_VAR=${BUILD_PROJECT}_CFILES
export BUILD_FILES_VAR
build_do_recursive build_clean_file build_clean_dir
}
build_cleanall() {
for TARGET in $TARGETS; do
build_clean "$TARGET"
done
}
build_distclean() {
build_cleanall
rm configure
}
# Description: check if the config files are present and load them.
# If they're not present, remake them.
build_check_config() {
[ ! -e build.vars -o -n "$BUILD_RUN_CONFIG" ] || return
build_config || exit $?
. build.vars
. "${BUILD_REC_PATH}Makeinfo"
unset BUILD_RUN_CONFIG
}
# Description: check if the necessary .depend file is present,
# if not, build it.
build_check_dependencies() {
eval DEPEND_FILE=".depend.\${${BUILD_PROJECT}_NAME%/}"
[ ! -e "$DEPEND_FILE" -o -n "$BUILD_RUN_DEPEND" ] || return
build_rec_dependancies || exit $?
}
+340
View File
@@ -0,0 +1,340 @@
# Auxiliary functions for custom build system
# Copyright (c) 2002 Serge van den Boom
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
BUILDLOG=/dev/null
TEMPFILE="/tmp/build.$$.tmp"
# Description: prints a command to stdout and then executes it
# Arguments: command with arguments
# Returns: the return value of the command
echo_and_perform() {
cat << EOF
$@
EOF
"$@"
}
# Description: read text from stdin to use as a c file to compile
# Arguments: $1 - CFLAGS to use for compilation (optional)
# $2 - LDFLAGS to use for linking (optional)
# Returns: 0 - if compile successful
# something else - if compile failed
try_compile_c() {
if [ -z "$COMPILE" ]; then
echo "Fatal: Program \$COMPILE is not defined!" >&2
exit 1
fi
cat > "$TEMPFILE.c"
echo_and_perform $COMPILE $1 $2 "$TEMPFILE.c" \
-o /dev/null 2>&1 >> "$BUILDLOG"
RESULT=$?
rm -f "$TEMPFILE.c"
return $RESULT
}
# Description: read text from stdin to use as a c file to compile
# Arguments: $1 - CFLAGS to use for compilation (optional)
# $2 - LDFLAGS to use for linking (optional)
# Returns: -1 - if compile failed
# otherwise - exit status of the program
try_compile_and_run_c() {
if [ -z "$COMPILE" ]; then
echo "Fatal: Program \$COMPILE is not defined!" >&2
exit 1
fi
cat > "$TEMPFILE.c"
echo_and_perform $COMPILE $1 $2 "$TEMPFILE.c" \
-o "$TEMPFILE.out" 2>&1 >> "$BUILDLOG"
if [ $? -ne 0 ]; then
return -1
fi
rm -f -- "$TEMPFILE.c"
"$TEMPFILE.out"
RESULT=$?
rm -f -- "$TEMPFILE.out"
return $RESULT
}
# Description: Output a message to stderr, unless BUILD_SILENT is set
# Arguments: the message
build_message() {
if [ -z "$BUILD_SILENT" ]; then
cat >&2 << EOF
$@
EOF
fi
}
# Description: Output a message to stderr, unless BUILD_SILENT is set
# Arguments: the message
build_message() {
if [ -z "$BUILD_SILENT" ]; then
cat >&2 << EOF
$@
EOF
fi
}
# Description: check if a program is present in the path
# Arguments:
have_program() {
local TEMP_NAME TEMP_FILE TEMP_VERSION
eval eval TEMP_NAME="\\\"\$PROG_${1}_NAME\\\""
if [ -z "$TEMP_NAME" ]; then
echo "Fatal: Program '$1' is not defined!" >&2
exit 1
fi
eval eval TEMP_FILE="\\\"\$PROG_${1}_FILE\\\""
type "$TEMP_FILE" 2>&1 > /dev/null
if [ $? -ne 0 ]; then
build_message "$TEMP_NAME not found."
return 1
fi
if [ $# -gt 1 ]; then
# Minimum version supplied
eval eval TEMP_VERSION="\\\"\$PROG_${1}_VERSION\\\""
if [ -z "$TEMP_VERSION" ]; then
echo "Fatal: Could not determine version of $TEMP_NAME" >&2
exit 1
fi
if [ "$TEMP_VERSION" \< "$2" ]; then
build_message "Found version $TEMP_VERSION of $TEMP_NAME, \
but version $2 is required!"
return 1
fi
build_message "$TEMP_NAME version $TEMP_VERSION found."
return 0
fi
build_message "$TEMP_NAME found."
return 0
}
# Description: check if a library is present on the system
# Arguments: $1 - The name of the library without 'lib' of '.so'
# $2 - (optional) minimum version required
# Pre: variables LIB_${1}_NAME, LIB_${1}_CFLAGS, and
# LIB_${1}_LDFLAGS are expected to exist. If two arguments are
# supplied, so is LIB_${1}_VERSION.
# Returns: 0 - if the library is found
# 1 - if the library is not found
have_library() {
local LIB TEMP_NAME TEMP_PRESENT TEMP_LDFLAGS TEMP_CFLAGS \
TEMP_VERSION
LIB="$1"
eval eval TEMP_NAME="\\\"\$LIB_${1}_NAME\\\""
if [ -z "$TEMP_NAME" ]; then
echo "Fatal: Library '$1' is not defined!" >&2
exit 1
fi
eval TEMP_PRESENT="\$LIB_${LIB}_PRESENT"
if [ -n "$TEMP_PRESENT" ]; then
return "$TEMP_PRESENT"
fi
eval eval TEMP_LDFLAGS="\\\"\$LIB_${LIB}_LDFLAGS\\\""
eval eval TEMP_CFLAGS="\\\"\$LIB_${LIB}_CFLAGS\\\""
try_compile_c "$TEMP_CFLAGS" "$TEMP_LDFLAGS" << EOF
int main() {
return 0;
}
EOF
if [ $? -ne 0 ]; then
eval "LIB_${LIB}_PRESENT"=1
build_message "$TEMP_NAME not found."
return 1
fi
if [ $# -gt 1 ]; then
# Minimum version supplied
eval eval TEMP_VERSION="\\\"\$LIB_${LIB}_VERSION\\\""
if [ -z "$TEMP_VERSION" ]; then
eval "LIB_${LIB}_PRESENT"=1
echo "Fatal: Could not determine version of $TEMP_NAME" >&2
exit 1
fi
if [ "$TEMP_VERSION" \< "$2" ]; then
eval "LIB_${LIB}_PRESENT"=1
build_message "Found version $TEMP_VERSION of $TEMP_NAME, \
but version $2 is required"
return 1
fi
eval "LIB_${LIB}_PRESENT"=0
build_message "$TEMP_NAME version $TEMP_VERSION found."
return 0
fi
eval "LIB_${LIB}_PRESENT"=0
build_message "$TEMP_NAME found."
return 0
}
# Description: check if a library is present on the system.
# If it is, add the appropriate flags to CFLAGS and LDFLAGS.
# If not, bail out.
# Arguments: $1 - The name of the library without 'lib' of '.so'
# $2 - (optional) minimum version required
# Pre: variables LIB_${1}_NAME, LIB_${1}_CFLAGS, and
# LIB_${1}_LDFLAGS are expected to exist. If two arguments are
# supplied, so is LIB_${1}_VERSION.
use_library() {
local TEMP_CFLAGS TEMP_LDFLAGS
have_library "$@"
[ $? -eq 0 ] || exit 1
eval eval TEMP_CFLAGS="\\\"\$LIB_${1}_CFLAGS\\\""
eval eval TEMP_LDFLAGS="\\\"\$LIB_${1}_LDFLAGS\\\""
CFLAGS="$CFLAGS $TEMP_CFLAGS"
LDFLAGS="$LDFLAGS $TEMP_LDFLAGS"
return 0
}
# Description: check if a symbol is defined.
# Arguments: $1 - the name of the symbol
have_symbol() {
local SYMBOL
SYMBOL="$1"
# TODO: I'll want the include handling to be done differently
# eventually.
try_compile_c "$TEMP_CFLAGS" "$TEMP_LDFLAGS" << EOF 2>&1 > /dev/null
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
int main() {
(void) $SYMBOL;
return 0;
}
EOF
if [ $? -gt 0 ]; then
build_message "Symbol '$SYMBOL' not found."
return 1
fi
build_message "Symbol '$SYMBOL' found."
return 0
}
# Description: check if a symbol is defined.
# set HAVE_<NAME> accordingly, where <NAME> is the capitalized
# name of the symbol.
# Arguments: $1 - the name of the symbol
define_have_symbol() {
local NAME VALUE
NAME=`$TR a-z A-Z << EOF
$1
EOF
`
if have_symbol "$1"; then
add_symbol "HAVE_$NAME" "#define HAVE_$NAME"
else
add_symbol "HAVE_$NAME" "#undef HAVE_$NAME"
fi
}
# Description: Add a symbol to be replaced by substitute_vars
# $HAVE_SYMBOLS will contain the variable names of all
# symbols added by define_have_symbol and should be passed to
# substitute_vars for the file you want them in.
# Arguments: $1 - the symbol to add
# $2 - the value of the symbol
add_symbol() {
local NAME
eval NAME="$1"
eval "$NAME"=\"\$2\"
HAVE_SYMBOLS="$HAVE_SYMBOLS $NAME"
}
check_endianness() {
try_compile_and_run_c << EOF
int main() {
int i;
i = 1;
return *((unsigned char *) &i);
}
EOF
if [ $? -eq 0 ]; then
build_message "Big-endian machine."
add_symbol WORDS_BIGENDIAN "#define WORDS_BIGENDIAN"
else
build_message "Little-endian machine."
add_symbol WORDS_BIGENDIAN "#undef WORDS_BIGENDIAN"
fi
}
# Description: substitute variables in files.
# Every supplied variable name found between @'s in the
# supplied files, is replaced by its value.
# Arguments: $1 - The name of the variable which contains a list of
# variables to substitute in the files.
# $2 - The name of the variable which contains a list of
# files to substitute variables in.
# If a filename ends on .in, that filename is used as
# source, and the filename without .in as target.
# If a filename doesn't end on .in, that filename is used
# as target, and the filename with .in attached as source.
substitute_vars() {
local VARS VAR VALUE FILES FILE
eval VARS=\"\$$1\"
eval FILES=\"\$$2\"
for VAR in $VARS; do
# Using CR as a seperator, as it's unlikely that's used in
# $VAR itself.
eval VALUE=\"\$$VAR\"
cat << EOF
s
@${VAR}@
${VALUE}
g
EOF
done > "${TEMPFILE}.sed"
for FILE in $FILES; do
FILE="${FILE%.in}"
$SED -f "${TEMPFILE}.sed" < "$FILE".in > "$FILE"
done
rm -- "${TEMPFILE}.sed"
}
# Include information about programs we can detect
. build/config_proginfo
# Some initialisations
HAVE_SYMBOLS=""
# Requirements for the config program itself
have_program sed || exit 1
SED="$PROG_sed_FILE"
have_program tr || exit 1
TR="$PROG_tr_FILE"
have_program make || exit 1
MAKE="$PROG_make_FILE"
+75
View File
@@ -0,0 +1,75 @@
# Set information on used programs and libraries
# Copyright (c) 2002 Serge van den Boom
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
# Describe the programs (possibly) used:
PROG_gcc_NAME="GNU C compiler"
PROG_gcc_FILE="gcc"
PROG_gcc_ACTION=""
PROG_gcc_VERSION='$(gcc --version)'
PROG_sed_NAME="Sed stream editor"
PROG_sed_FILE="sed"
PROG_sed_ACTION=""
PROG_sed_VERSION=''
PROG_make_NAME="Make"
PROG_make_FILE="make"
PROG_make_ACTION=""
PROG_make_VERSION=''
PROG_tr_NAME="tr"
PROG_tr_FILE="tr"
PROG_tr_ACTION=""
PROG_tr_VERSION=''
# Describe the libaries (possibly) used:
LIB_SDL_NAME="Simple DirectMedia Layer"
LIB_SDL_CFLAGS='$(sdl-config --cflags)'
LIB_SDL_LDFLAGS='$(sdl-config --libs)'
LIB_SDL_VERSION='$(sdl-config --version)'
LIB_SDL_mixer_NAME="SDL_mixer"
LIB_SDL_mixer_CFLAGS=""
LIB_SDL_mixer_LDFLAGS="-lSDL_mixer"
LIB_SDL_mixer_VERSION=""
LIB_SDL_image_NAME="SDL_image"
LIB_SDL_image_CFLAGS=""
LIB_SDL_image_LDFLAGS="-lSDL_image"
LIB_SDL_image_VERSION=""
LIB_openal_NAME="OpenAL"
LIB_openal_CFLAGS=""
LIB_openal_LDFLAGS="-lopenal"
LIB_openal_VERSION=""
LIB_opengl_NAME="OpenGL"
LIB_opengl_CFLAGS=""
LIB_opengl_LDFLAGS="-lGL"
LIB_opengl_VERSION=""
LIB_vorbis_NAME="Vorbis"
LIB_vorbis_CFLAGS=""
LIB_vorbis_LDFLAGS="-lvorbis"
LIB_vorbis_VERSION=""
LIB_vorbisfile_NAME="Vorbisfile"
LIB_vorbisfile_CFLAGS=""
LIB_vorbisfile_LDFLAGS="-lvorbisfile -lvorbis"
LIB_vorbisfile_VERSION=""
+482
View File
@@ -0,0 +1,482 @@
# Auxiliary functions for menu system for custom build system
# Copyright (c) 2002 Serge van den Boom
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
MENU_ITEM_TYPES="MENU CHOICE INPUT"
MENU_ITEM_TYPE_MENU_INIT=menu_init_menu
MENU_ITEM_TYPE_MENU_PRINT_VALUE=menu_print_value_menu
MENU_ITEM_TYPE_MENU_HANDLER=menu_handle_menu
MENU_ITEM_TYPE_MENU_SAVE=menu_save_menu
MENU_ITEM_TYPE_MENU_PROCESS=menu_process_menu
MENU_ITEM_TYPE_CHOICE_INIT=menu_init_choice
MENU_ITEM_TYPE_CHOICE_PRINT_VALUE=menu_print_value_choice
MENU_ITEM_TYPE_CHOICE_HANDLER=menu_handle_choice
MENU_ITEM_TYPE_CHOICE_SAVE=menu_save_choice
MENU_ITEM_TYPE_CHOICE_PROCESS=menu_process_choice
MENU_ITEM_TYPE_INPUT_INIT=menu_init_input
MENU_ITEM_TYPE_INPUT_PRINT_VALUE=menu_print_value_input
MENU_ITEM_TYPE_INPUT_HANDLER=menu_handle_input
MENU_ITEM_TYPE_INPUT_SAVE=menu_save_input
MENU_ITEM_TYPE_INPUT_PROCESS=menu_process_input
# Description: Check if a string can be used as a path.
# No checks are done if the path really exists.
# Arguments: $1 - the string to check
# Returns: 0 if the string makes a valid path
# 1 if the string doesn't make a valid path
# Outputs: the path, possibly modified
validate_path() {
if [ "$1" = "/" ]; then
echo "/"
return
fi
cat << EOF
${1%/}
EOF
return 0
}
# Description: Initialise a menu, setting unset values to default
# Arguments: $1 - the type of menu item
# $2 - the name of the menu item
menu_init() {
local INIT_FUN
eval INIT_FUN="\$MENU_ITEM_TYPE_$1_INIT"
"$INIT_FUN" "$2"
}
# Description: Initialise this menu
# Arguments: $1 - the name of the menu
menu_init_menu() {
local MENU TEMP_ITEMS ITEM TEMP_TYPE
MENU="$1"
eval TEMP_ITEMS="\$MENU_${MENU}_ITEMS"
for ITEM in $TEMP_ITEMS; do
eval TEMP_TYPE="\$MENU_${MENU}_ITEM_${ITEM}_TYPE"
menu_init "$TEMP_TYPE" "$ITEM"
done
}
# Description: Check if this choice is available
# Arguments: $1 - the name of the choice menu
# $2 - the name of the choice
# Returns: 0 - if the choice is available
# 1 - if the choice is not available
menu_have_choice() {
local MENU CHOICE TEMP_VALID TEMP_PRECOND
MENU="$1"
CHOICE="$2"
eval TEMP_VALID="\$CHOICE_${MENU}_OPTION_${CHOICE}_VALID"
if [ -n "$TEMP_VALID" ]; then
return "$TEMP_VALID"
fi
eval TEMP_PRECOND="\$CHOICE_${MENU}_OPTION_${CHOICE}_PRECOND"
if [ -z "$TEMP_PRECOND" ] || $TEMP_PRECOND; then
eval "CHOICE_${MENU}_OPTION_${CHOICE}_VALID"=0
return 0
fi
eval "CHOICE_${MENU}_OPTION_${CHOICE}_VALID"=1
return 1
}
# Description: Initialise this choice menu
# Arguments: $1 - the name of the choice menu
menu_init_choice() {
local MENU TEMP_VALUE TEMP_DEFAULT TEMP_OPTIONS OPTION TEMP_TITLE
MENU="$1"
eval TEMP_VALUE="\$CHOICE_${MENU}_VALUE"
eval TEMP_DEFAULT="\$CHOICE_${MENU}_DEFAULT"
eval TEMP_OPTIONS="\$CHOICE_${MENU}_OPTIONS"
for OPTION in $TEMP_VALUE $TEMP_DEFAULT $TEMP_OPTIONS; do
if menu_have_choice "$MENU" "$OPTION"; then
eval CHOICE_${MENU}_VALUE="$OPTION"
eval CHOICE_${MENU}_OLD_VALUE="$OPTION"
return
fi
done
eval TEMP_VALUE="\$CHOICE_${MENU}_TITLE"
echo "Error: No option for '$TEMP_VALUE' is available for your system."
exit 1
}
# Description: Initialise this input menu
# Arguments: $1 - the name of the input menu
menu_init_input() {
local MENU TEMP_VALUE TEMP_DEFAULT
MENU="$1"
eval TEMP_VALUE="\$INPUT_${MENU}_VALUE"
if [ -z "$TEMP_VALUE" ]; then
eval TEMP_VALUE="\$INPUT_${MENU}_DEFAULT"
eval INPUT_${MENU}_VALUE="\$TEMP_VALUE"
fi
eval INPUT_${MENU}_OLD_VALUE="\$TEMP_VALUE"
}
# Description: Print the string describing the value of a menu item.
# Arguments: $1 - the type of menu item
# $2 - the name of the menu item
# Outputs: The string describing the value of the menu item
menu_print_value() {
local PRINT_VALUE
eval PRINT_VALUE="\$MENU_ITEM_TYPE_$1_PRINT_VALUE"
"$PRINT_VALUE" "$2"
}
# Description: Print the string describing the value this menu
# Arguments: $1 - the name of the menu item
# Outputs: The string describing the value of this menu
menu_print_value_menu() {
echo "[...]"
}
# Description: Print the string describing the value this choice menu
# Arguments: $1 - the name of the choice menu item
# Outputs: The string describing the value of this choice menu
menu_print_value_choice() {
local TEMP_VALUE TEMP_TITLE
eval TEMP_VALUE="\$CHOICE_$1_VALUE"
eval TEMP_TITLE=\"\$CHOICE_$1_OPTION_${TEMP_VALUE}_TITLE\"
cat << EOF
$TEMP_TITLE
EOF
}
# Description: Print the value of this input menu
# Arguments: $1 - the name of the input menu item
# Outputs: The value of the given input menu
menu_print_value_input() {
local TEMP_VALUE TEMP_TITLE
eval TEMP_VALUE="\$INPUT_$1_VALUE"
cat << EOF
$TEMP_VALUE
EOF
}
# Description: Print the string describing the value of a menu item.
# Arguments: $1 - the type of menu item
# $2 - the name of the menu item
# Outputs: The string describing the value of the menu item
menu_handle() {
local HANDLER
eval HANDLER="\$MENU_ITEM_TYPE_$1_HANDLER"
"$HANDLER" "$2"
}
# Description: Process a menu-type menu item
# Arguments: $1 - The name of the menu
menu_handle_menu() {
local TEMP_ITEMS I CHOICE NUM_ITEMS TEMP_TYPE MENU ITEM TEMP_TITLE
eval TEMP_ITEMS="\$MENU_$1_ITEMS"
MENU="$1"
while :; do
echo
eval TEMP_TITLE="\$MENU_${MENU}_TITLE"
cat << EOF
$ANSI_BOLD-= $TEMP_TITLE =-$ANSI_NORMAL
EOF
I=0
for ITEM in $TEMP_ITEMS; do
I=$(($I + 1))
eval TEMP_TYPE="\$MENU_${MENU}_ITEM_${ITEM}_TYPE"
eval TEMP_TITLE="\$${TEMP_TYPE}_${ITEM}_TITLE"
printf " %i. %-36s %s\n" $I "$TEMP_TITLE" \
"$(menu_print_value $TEMP_TYPE $ITEM)"
done
NUM_ITEMS="$I"
echo
echo "Press a number plus <ENTER> if you want to change something, "
echo -n "or just <ENTER> if everything is ok: "
read CHOICE
# Check if the choice was empty
if [ -z "$CHOICE" ]; then
# We're done
return
fi
# Check if what the user entered was a number
egrep -q "^[0-9]+$" << EOF
$CHOICE
EOF
if [ $? -ne 0 ]; then
echo "Invalid choice."
continue
fi
# Check if the number the user entered if valid
if [ "$CHOICE" -lt 1 -o "$CHOICE" -gt "$NUM_ITEMS" ]; then
echo "Invalid choice."
continue
fi
# Now look up the choice
I=0
for ITEM in $TEMP_ITEMS; do
I=$(($I + 1))
if [ "$I" -eq "$CHOICE" ]; then
eval TEMP_TYPE="\$MENU_${MENU}_ITEM_${ITEM}_TYPE"
menu_handle "$TEMP_TYPE" "$ITEM"
break
fi
done
done
}
# Description: Process a choice-type menu item
# Arguments: $1 - The name of the menu
menu_handle_choice() {
local TEMP_OPTIONS I CHOICE NUM_OPTIONS TEMP_TYPE MENU OPTION \
TEMP_VALUE TEMP_TITLE SELECTED
eval TEMP_OPTIONS="\$CHOICE_$1_OPTIONS"
MENU="$1"
while :; do
echo
eval TEMP_TITLE="\$CHOICE_${MENU}_TITLE"
cat << EOF
$ANSI_BOLD-= $TEMP_TITLE =-$ANSI_NORMAL
EOF
eval TEMP_VALUE="\$CHOICE_${MENU}_VALUE"
# Check in advance which options are present, so that that
# is echoed before the menu is printed.
# menu_have_choice caches results.
# Also, count the number of options
I=0
for OPTION in $TEMP_OPTIONS; do
menu_have_choice "$MENU" "$OPTION"
done
NUM_OPTIONS="$I"
I=0
for OPTION in $TEMP_OPTIONS; do
I=$(($I + 1))
eval TEMP_TITLE="\$CHOICE_${MENU}_OPTION_${OPTION}_TITLE"
if [ "$TEMP_VALUE" = "$OPTION" ]; then
SELECTED="-->"
else
SELECTED=" "
fi
if menu_have_choice "$MENU" "$OPTION"; then
printf " %*i. %s %s\n" "${#NUM_OPTIONS}" "$I" \
"$SELECTED" "$TEMP_TITLE"
else
printf " %-*s %s (N/A) %s\n" "${#NUM_OPTIONS}" "-" \
"$SELECTED" "$TEMP_TITLE"
fi
done
echo
echo "Select the option you want by typing a number plus <ENTER>"
echo -n "or just <ENTER> if everything is ok: "
read CHOICE
echo
# Check if the choice was empty
if [ -z "$CHOICE" ]; then
# We're done
return
fi
# Check if what the user entered was a number
egrep -q "^[0-9]+$" << EOF
$CHOICE
EOF
if [ $? -ne 0 ]; then
echo "Invalid choice."
continue
fi
# Check if the number the user entered if valid
if [ "$CHOICE" -lt 1 -o "$CHOICE" -gt "$NUM_ITEMS" ]; then
echo "Invalid choice."
continue
fi
# Now look up the choice
I=0
for OPTION in $TEMP_OPTIONS; do
I=$(($I + 1))
if [ "$I" -eq "$CHOICE" ]; then
if menu_have_choice "$MENU" "$OPTION"; then
eval "CHOICE_${MENU}_VALUE"="$OPTION"
return
else
echo "That option is unavailable on your system."
fi
fi
done
done
}
# Description: Process an input-type menu item
# Arguments: $1 - The name of the menu
menu_handle_input() {
local ITEM TEMP_TITLE TEMP_VALUE TEMP_DEFAULT NEW_VALUE TEMP_VALIDATOR
ITEM="$1"
eval TEMP_TITLE="\$INPUT_${ITEM}_TITLE"
while :; do
echo
cat << EOF
$ANSI_BOLD-= $TEMP_TITLE =-$ANSI_NORMAL
EOF
eval TEMP_VALUE="\$INPUT_${ITEM}_VALUE"
eval TEMP_DEFAULT="\$INPUT_${ITEM}_DEFAULT"
echo " Default value: $TEMP_DEFAULT"
echo " Current value: $TEMP_VALUE"
echo -n " New value: "
read NEW_VALUE
# If no new value is entered, keep the old one.
if [ -z "$NEW_VALUE" ]; then
return
fi
# If a validator function is present, validate the new value
eval TEMP_VALIDATOR="\$INPUT_${ITEM}_VALIDATOR"
if [ -n "$TEMP_VALIDATOR" ]; then
NEW_VALUE=`$TEMP_VALIDATOR "$NEW_VALUE"`
if [ $? -ne 0 ]; then
echo "Invalid value"
continue
fi
fi
break
done
eval "INPUT_${ITEM}_VALUE"=\"\$NEW_VALUE\"
}
# Description: echo the current state of a menu item in a form that can be
# executed to restore the state.
# Arguments: $1 - the type of menu item
# $2 - the name of the menu item
# Outputs: The string describing the value of the menu item
menu_save() {
local SAVE_FUN
eval SAVE_FUN="\$MENU_ITEM_TYPE_$1_SAVE"
"$SAVE_FUN" "$2"
}
# Description: echo the current state of a menu in a form that can be
# executed to restore the state.
# Arguments: $1 - the name of the menu
# Outputs: The string describing the value of the menu
menu_save_menu() {
local MENU TEMP_ITEMS ITEM TEMP_TYPE
MENU="$1"
eval TEMP_ITEMS="\$MENU_${MENU}_ITEMS"
for ITEM in $TEMP_ITEMS; do
eval TEMP_TYPE="\$MENU_${MENU}_ITEM_${ITEM}_TYPE"
menu_save "$TEMP_TYPE" "$ITEM"
done
}
# Description: echo the current state of a choice menu in a form that can be
# executed to restore the state.
# Arguments: $1 - the name of the choice menu
# Outputs: The string describing the value of the choice menu
menu_save_choice() {
local MENU TEMP_VALUE
MENU="$1"
eval TEMP_VALUE="\$CHOICE_${MENU}_VALUE"
cat << EOF
CHOICE_${MENU}_VALUE='$TEMP_VALUE'
EOF
}
# Description: echo the current state of an input menu in a form that can be
# executed to restore the state.
# Arguments: $1 - the name of the input menu
# Outputs: The string describing the value of the input menu
menu_save_input() {
local MENU TEMP_VALUE
MENU="$1"
eval TEMP_VALUE="\$INPUT_${MENU}_VALUE"
cat << EOF
INPUT_${MENU}_VALUE='$TEMP_VALUE'
EOF
}
# Description: Perform the actions associated with the choice made for a
# menu items.
# Arguments: $1 - the type of menu item
# $2 - the name of the menu item
menu_process() {
local PROCESS_FUN
eval PROCESS_FUN="\$MENU_ITEM_TYPE_$1_PROCESS"
"$PROCESS_FUN" "$2"
}
# Description: Perform the actions associated with the chosen menu items
# for a menu.
# Arguments: $1 - the name of the menu
menu_process_menu() {
local MENU TEMP_ITEMS ITEM TEMP_TYPE
MENU="$1"
eval TEMP_ITEMS="\$MENU_${MENU}_ITEMS"
for ITEM in $TEMP_ITEMS; do
eval TEMP_TYPE="\$MENU_${MENU}_ITEM_${ITEM}_TYPE"
menu_process "$TEMP_TYPE" "$ITEM"
done
}
# Description: Perform the actions associated with the choice made for
# a choice menu.
# Arguments: $1 - the name of the choice menu
menu_process_choice() {
local MENU TEMP_VALUE TEMP_ACTION
MENU="$1"
eval TEMP_VALUE="\$CHOICE_${MENU}_VALUE"
eval TEMP_ACTION="\$CHOICE_${MENU}_OPTION_${TEMP_VALUE}_ACTION"
if [ -n "$TEMP_ACTION" ]; then
$TEMP_ACTION
fi
}
# Description: Perform the actions associated with the input menu.
# Arguments: $1 - the name of the input menu
menu_process_input() {
# Nothing to do
:
}
do_menu() {
if [ -e config.state ]; then
. config.state
fi
menu_init MENU "$@"
menu_handle MENU "$@"
echo
echo "Saving configuration..."
menu_save MENU "$@" > config.state
echo "Propagating configuration..."
menu_process MENU "$@"
echo "Configuration complete."
}