Sat, 11 Jan 2025 13:45:38 +0100
project init
.hgignore | file | annotate | diff | comparison | revisions | |
Makefile | file | annotate | diff | comparison | revisions | |
configure | file | annotate | diff | comparison | revisions | |
make/cc.mk | file | annotate | diff | comparison | revisions | |
make/configure.vm | file | annotate | diff | comparison | revisions | |
make/makefile.mk | file | annotate | diff | comparison | revisions | |
make/project.xml | file | annotate | diff | comparison | revisions | |
make/toolchain.sh | file | annotate | diff | comparison | revisions | |
make/update-rules.sh | file | annotate | diff | comparison | revisions | |
make/uwproj.xsd | file | annotate | diff | comparison | revisions | |
src/Makefile | file | annotate | diff | comparison | revisions | |
src/main.cpp | file | annotate | diff | comparison | revisions |
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/.hgignore Sat Jan 11 13:45:38 2025 +0100 @@ -0,0 +1,4 @@ +syntax:glob +.idea/ +build/ +config.mk
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Makefile Sat Jan 11 13:45:38 2025 +0100 @@ -0,0 +1,42 @@ +# Copyright 2025 Mike Becker. All rights reserved. +# +# 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 COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT HOLDER 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. + +all: compile FORCE + +clean: FORCE + rm -Rf build + +compile: config.mk build FORCE + @cd src && $(MAKE) + +config.mk: + ./configure --release + +build: + mkdir -p $@ + +update-rules: FORCE + make/update-rules.sh src + +FORCE: +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/configure Sat Jan 11 13:45:38 2025 +0100 @@ -0,0 +1,383 @@ +#!/bin/sh + + +# some utility functions +isplatform() +{ + for p in $PLATFORM + do + if [ "$p" = "$1" ]; then + return 0 + fi + done + return 1 +} +notisplatform() +{ + for p in $PLATFORM + do + if [ "$p" = "$1" ]; then + return 1 + fi + done + return 0 +} +istoolchain() +{ + for t in $TOOLCHAIN + do + if [ "$t" = "$1" ]; then + return 0 + fi + done + return 1 +} +notistoolchain() +{ + for t in $TOOLCHAIN + do + if [ "$t" = "$1" ]; then + return 1 + fi + done + return 0 +} + +# clean abort +abort_configure() +{ + rm -Rf "$TEMP_DIR" + exit 1 +} + +# Test for availability of pkg-config +PKG_CONFIG=`command -v pkg-config` +: ${PKG_CONFIG:="false"} + +# Simple uname based platform detection +# $PLATFORM is used for platform dependent dependency selection +OS=`uname -s` +OS_VERSION=`uname -r` +printf "detect platform... " +if [ "$OS" = "SunOS" ]; then + PLATFORM="solaris sunos unix svr4" +elif [ "$OS" = "Linux" ]; then + PLATFORM="linux unix" +elif [ "$OS" = "FreeBSD" ]; then + PLATFORM="freebsd bsd unix" +elif [ "$OS" = "OpenBSD" ]; then + PLATFORM="openbsd bsd unix" +elif [ "$OS" = "NetBSD" ]; then + PLATFORM="netbsd bsd unix" +elif [ "$OS" = "Darwin" ]; then + PLATFORM="macos osx bsd unix" +elif echo "$OS" | grep -i "MINGW" > /dev/null; then + PLATFORM="windows mingw" +fi +: ${PLATFORM:="unix"} + +PLATFORM_NAME=`echo "$PLATFORM" | cut -f1 -d' ' -` +echo "$PLATFORM_NAME" + + +# help text +printhelp() +{ + echo "Usage: $0 [OPTIONS]..." + cat << __EOF__ +Installation directories: + --prefix=PREFIX path prefix for architecture-independent files + [$prefix] + --exec-prefix=EPREFIX path prefix for architecture-dependent files + [PREFIX] + + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --sysconfdir=DIR system configuration files [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --runstatedir=DIR run-time variable data [LOCALSTATEDIR/run] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] + --datadir=DIR read-only architecture-independent data [DATAROOTDIR] + --infodir=DIR info documentation [DATAROOTDIR/info] + --mandir=DIR man documentation [DATAROOTDIR/man] + --localedir=DIR locale-dependent data [DATAROOTDIR/locale] + +Build Types: +--debug add extra compile flags for debug builds +--release add extra compile flags for release builds + +__EOF__ +} + +# create temporary directory +TEMP_DIR=".tmp-`uname -n`" +rm -Rf "$TEMP_DIR" +if mkdir -p "$TEMP_DIR"; then + : +else + echo "Cannot create tmp dir $TEMP_DIR" + echo "Abort" + exit 1 +fi +touch "$TEMP_DIR/options" +touch "$TEMP_DIR/features" + +# define standard variables +# also define standard prefix (this is where we will search for config.site) +prefix=/usr +exec_prefix= +bindir= +sbindir= +libdir= +libexecdir= +datarootdir= +datadir= +sysconfdir= +sharedstatedir= +localstatedir= +runstatedir= +includedir= +infodir= +localedir= +mandir= + +# custom variables + +# features + +# +# parse arguments +# +BUILD_TYPE="default" +for ARG in "$@" +do + case "$ARG" in + "--prefix="*) prefix=${ARG#--prefix=} ;; + "--exec-prefix="*) exec_prefix=${ARG#--exec-prefix=} ;; + "--bindir="*) bindir=${ARG#----bindir=} ;; + "--sbindir="*) sbindir=${ARG#--sbindir=} ;; + "--libdir="*) libdir=${ARG#--libdir=} ;; + "--libexecdir="*) libexecdir=${ARG#--libexecdir=} ;; + "--datarootdir="*) datarootdir=${ARG#--datarootdir=} ;; + "--datadir="*) datadir=${ARG#--datadir=} ;; + "--sysconfdir="*) sysconfdir=${ARG#--sysconfdir=} ;; + "--sharedstatedir="*) sharedstatedir=${ARG#--sharedstatedir=} ;; + "--localstatedir="*) localstatedir=${ARG#--localstatedir=} ;; + "--includedir="*) includedir=${ARG#--includedir=} ;; + "--infodir="*) infodir=${ARG#--infodir=} ;; + "--mandir"*) mandir=${ARG#--mandir} ;; + "--localedir"*) localedir=${ARG#--localedir} ;; + "--help"*) printhelp; abort_configure ;; + "--debug") BUILD_TYPE="debug" ;; + "--release") BUILD_TYPE="release" ;; + "-"*) echo "unknown option: $ARG"; abort_configure ;; + esac +done + + + +# set defaults for dir variables +: ${exec_prefix:="$prefix"} +: ${bindir:='${exec_prefix}/bin'} +: ${sbindir:='${exec_prefix}/sbin'} +: ${libdir:='${exec_prefix}/lib'} +: ${libexecdir:='${exec_prefix}/libexec'} +: ${datarootdir:='${prefix}/share'} +: ${datadir:='${datarootdir}'} +: ${sysconfdir:='${prefix}/etc'} +: ${sharedstatedir:='${prefix}/com'} +: ${localstatedir:='${prefix}/var'} +: ${runstatedir:='${localstatedir}/run'} +: ${includedir:='${prefix}/include'} +: ${infodir:='${datarootdir}/info'} +: ${mandir:='${datarootdir}/man'} +: ${localedir:='${datarootdir}/locale'} + +# check if a config.site exists and load it +if [ -n "$CONFIG_SITE" ]; then + # CONFIG_SITE may contain space separated file names + for cs in $CONFIG_SITE; do + printf "loading defaults from $cs... " + . "$cs" + echo ok + done +elif [ -f "$prefix/share/config.site" ]; then + printf "loading site defaults... " + . "$prefix/share/config.site" + echo ok +elif [ -f "$prefix/etc/config.site" ]; then + printf "loading site defaults... " + . "$prefix/etc/config.site" + echo ok +fi + + +# generate vars.mk +cat > "$TEMP_DIR/vars.mk" << __EOF__ +prefix=$prefix +exec_prefix=$exec_prefix +bindir=$bindir +sbindir=$sbindir +libdir=$libdir +libexecdir=$libexecdir +datarootdir=$datarootdir +datadir=$datadir +sysconfdir=$sysconfdir +sharedstatedir=$sharedstatedir +localstatedir=$localstatedir +runstatedir=$runstatedir +includedir=$includedir +infodir=$infodir +mandir=$mandir +localedir=$localedir +__EOF__ + +# toolchain detection utilities +. make/toolchain.sh + +# +# DEPENDENCIES +# + +# check languages +lang_c= +lang_cpp= +if detect_cpp_compiler ; then + lang_cpp=1 +fi + +# create buffer for make variables required by dependencies +echo > "$TEMP_DIR/make.mk" + +test_pkg_config() +{ + if "$PKG_CONFIG" --exists "$1" ; then : + else return 1 ; fi + if [ -z "$2" ] || "$PKG_CONFIG" --atleast-version="$2" "$1" ; then : + else return 1 ; fi + if [ -z "$3" ] || "$PKG_CONFIG" --exact-version="$3" "$1" ; then : + else return 1 ; fi + if [ -z "$4" ] || "$PKG_CONFIG" --max-version="$4" "$1" ; then : + else return 1 ; fi + return 0 +} + +print_check_msg() +{ + if [ -z "$1" ]; then + shift + printf "$@" + fi +} + + +# start collecting dependency information +echo > "$TEMP_DIR/flags.mk" + +DEPENDENCIES_FAILED= +ERROR=0 +# unnamed dependencies +TEMP_CFLAGS="$CFLAGS" +TEMP_CXXFLAGS="$CXXFLAGS" +TEMP_LDFLAGS="$LDFLAGS" +while true +do + while true + do + if [ -z "$lang_cpp" ] ; then + ERROR=1 + break + fi + + break + done + break +done + +# add general dependency flags to flags.mk +echo "# general flags" >> "$TEMP_DIR/flags.mk" +if [ -n "${TEMP_CFLAGS}" ] && [ -n "$lang_c" ]; then + echo "CFLAGS += $TEMP_CFLAGS" >> "$TEMP_DIR/flags.mk" +fi +if [ -n "${TEMP_CXXFLAGS}" ] && [ -n "$lang_cpp" ]; then + echo "CXXFLAGS += $TEMP_CXXFLAGS" >> "$TEMP_DIR/flags.mk" +fi +if [ -n "${TEMP_LDFLAGS}" ]; then + echo "LDFLAGS += $TEMP_LDFLAGS" >> "$TEMP_DIR/flags.mk" +fi + +# +# OPTION VALUES +# + +# +# TARGETS +# + +echo >> "$TEMP_DIR/flags.mk" +echo "configuring target: default" +echo "# flags for target default" >> "$TEMP_DIR/flags.mk" +TEMP_CFLAGS= +TEMP_CXXFLAGS= +TEMP_LDFLAGS= + + +# Features + + +if [ -n "${TEMP_CFLAGS}" ] && [ -n "$lang_c" ]; then + echo "CFLAGS += $TEMP_CFLAGS" >> "$TEMP_DIR/flags.mk" +fi +if [ -n "${TEMP_CXXFLAGS}" ] && [ -n "$lang_cpp" ]; then + echo "CXXFLAGS += $TEMP_CXXFLAGS" >> "$TEMP_DIR/flags.mk" +fi +if [ "$BUILD_TYPE" = "debug" ]; then + if [ -n "$lang_c" ]; then + echo 'CFLAGS += ${DEBUG_CC_FLAGS}' >> "$TEMP_DIR/flags.mk" + fi + if [ -n "$lang_cpp" ]; then + echo 'CXXFLAGS += ${DEBUG_CXX_FLAGS}' >> "$TEMP_DIR/flags.mk" + fi +fi +if [ "$BUILD_TYPE" = "release" ]; then + if [ -n "$lang_c" ]; then + echo 'CFLAGS += ${RELEASE_CC_FLAGS}' >> "$TEMP_DIR/flags.mk" + fi + if [ -n "$lang_cpp" ]; then + echo 'CXXFLAGS += ${RELEASE_CXX_FLAGS}' >> "$TEMP_DIR/flags.mk" + fi +fi +if [ -n "${TEMP_LDFLAGS}" ]; then + echo "LDFLAGS += $TEMP_LDFLAGS" >> "$TEMP_DIR/flags.mk" +fi + + +# final result +if [ $ERROR -ne 0 ]; then + echo + echo "Error: Unresolved dependencies" + echo "$DEPENDENCIES_FAILED" + abort_configure +fi + +echo "configure finished" +echo +echo "Build Config:" +echo " PREFIX: $prefix" +echo " TOOLCHAIN: $TOOLCHAIN_NAME" +echo + +# generate the config.mk file +cat > "$TEMP_DIR/config.mk" << __EOF__ +# +# config.mk generated by configure +# + +__EOF__ +write_toolchain_defaults "$TEMP_DIR/toolchain.mk" +cat "$TEMP_DIR/vars.mk" "$TEMP_DIR/toolchain.mk" "$TEMP_DIR/flags.mk" "$TEMP_DIR/make.mk" > config.mk +rm -Rf "$TEMP_DIR"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/cc.mk Sat Jan 11 13:45:38 2025 +0100 @@ -0,0 +1,5 @@ +CXXFLAGS = -fno-exceptions -fno-rtti -s +DEBUG_CXX_FLAGS = -g +RELEASE_CXX_FLAGS = -O3 -DNDEBUG +LDFLAGS = +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/configure.vm Sat Jan 11 13:45:38 2025 +0100 @@ -0,0 +1,724 @@ +#!/bin/sh + +#set( $D = '$' ) +#[[ +# some utility functions +isplatform() +{ + for p in $PLATFORM + do + if [ "$p" = "$1" ]; then + return 0 + fi + done + return 1 +} +notisplatform() +{ + for p in $PLATFORM + do + if [ "$p" = "$1" ]; then + return 1 + fi + done + return 0 +} +istoolchain() +{ + for t in $TOOLCHAIN + do + if [ "$t" = "$1" ]; then + return 0 + fi + done + return 1 +} +notistoolchain() +{ + for t in $TOOLCHAIN + do + if [ "$t" = "$1" ]; then + return 1 + fi + done + return 0 +} + +# clean abort +abort_configure() +{ + rm -Rf "$TEMP_DIR" + exit 1 +} + +# Test for availability of pkg-config +PKG_CONFIG=`command -v pkg-config` +: ${PKG_CONFIG:="false"} + +# Simple uname based platform detection +# $PLATFORM is used for platform dependent dependency selection +OS=`uname -s` +OS_VERSION=`uname -r` +printf "detect platform... " +if [ "$OS" = "SunOS" ]; then + PLATFORM="solaris sunos unix svr4" +elif [ "$OS" = "Linux" ]; then + PLATFORM="linux unix" +elif [ "$OS" = "FreeBSD" ]; then + PLATFORM="freebsd bsd unix" +elif [ "$OS" = "OpenBSD" ]; then + PLATFORM="openbsd bsd unix" +elif [ "$OS" = "NetBSD" ]; then + PLATFORM="netbsd bsd unix" +elif [ "$OS" = "Darwin" ]; then + PLATFORM="macos osx bsd unix" +elif echo "$OS" | grep -i "MINGW" > /dev/null; then + PLATFORM="windows mingw" +fi +: ${PLATFORM:="unix"} + +PLATFORM_NAME=`echo "$PLATFORM" | cut -f1 -d' ' -` +echo "$PLATFORM_NAME" +]]# + +# help text +printhelp() +{ + echo "Usage: $0 [OPTIONS]..." + cat << __EOF__ +Installation directories: + --prefix=PREFIX path prefix for architecture-independent files + [${D}prefix] + --exec-prefix=EPREFIX path prefix for architecture-dependent files + [PREFIX] + + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --sysconfdir=DIR system configuration files [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --runstatedir=DIR run-time variable data [LOCALSTATEDIR/run] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] + --datadir=DIR read-only architecture-independent data [DATAROOTDIR] + --infodir=DIR info documentation [DATAROOTDIR/info] + --mandir=DIR man documentation [DATAROOTDIR/man] + --localedir=DIR locale-dependent data [DATAROOTDIR/locale] + +Build Types: +--debug add extra compile flags for debug builds +--release add extra compile flags for release builds +#if( $options.size() > 0 ) + +Options: +#foreach( $opt in $options ) + --${opt.argument}=${opt.valuesString} +#end +#end +#if( $features.size() > 0 ) + +Optional Features: +#foreach( $feature in $features ) +${feature.helpText} +#end +#end + +__EOF__ +} + +# create temporary directory +TEMP_DIR=".tmp-`uname -n`" +rm -Rf "$TEMP_DIR" +if mkdir -p "$TEMP_DIR"; then + : +else + echo "Cannot create tmp dir $TEMP_DIR" + echo "Abort" + exit 1 +fi +touch "$TEMP_DIR/options" +touch "$TEMP_DIR/features" + +# define standard variables +# also define standard prefix (this is where we will search for config.site) +prefix=/usr +exec_prefix= +bindir= +sbindir= +libdir= +libexecdir= +datarootdir= +datadir= +sysconfdir= +sharedstatedir= +localstatedir= +runstatedir= +includedir= +infodir= +localedir= +mandir= + +# custom variables +#foreach( $cfg in $config ) +if true \ +#if( $cfg.platform ) + && isplatform "${cfg.platform}" \ +#end +#foreach( $np in $cfg.notList ) + && notisplatform "${np}" \ +#end + ; then + #foreach( $var in $cfg.vars ) + #if( $var.exec ) + ${var.varName}=`${var.value}` + #else + ${var.varName}="${var.value}" + #end + #end +fi +#end + +# features +#foreach( $feature in $features ) +#if( ${feature.auto} ) +${feature.varName}=auto +#end +#end + +# +# parse arguments +# +BUILD_TYPE="default" +for ARG in "$@" +do + case "$ARG" in + "--prefix="*) prefix=${D}{ARG#--prefix=} ;; + "--exec-prefix="*) exec_prefix=${D}{ARG#--exec-prefix=} ;; + "--bindir="*) bindir=${D}{ARG#----bindir=} ;; + "--sbindir="*) sbindir=${D}{ARG#--sbindir=} ;; + "--libdir="*) libdir=${D}{ARG#--libdir=} ;; + "--libexecdir="*) libexecdir=${D}{ARG#--libexecdir=} ;; + "--datarootdir="*) datarootdir=${D}{ARG#--datarootdir=} ;; + "--datadir="*) datadir=${D}{ARG#--datadir=} ;; + "--sysconfdir="*) sysconfdir=${D}{ARG#--sysconfdir=} ;; + "--sharedstatedir="*) sharedstatedir=${D}{ARG#--sharedstatedir=} ;; + "--localstatedir="*) localstatedir=${D}{ARG#--localstatedir=} ;; + "--includedir="*) includedir=${D}{ARG#--includedir=} ;; + "--infodir="*) infodir=${D}{ARG#--infodir=} ;; + "--mandir"*) mandir=${D}{ARG#--mandir} ;; + "--localedir"*) localedir=${D}{ARG#--localedir} ;; + "--help"*) printhelp; abort_configure ;; + "--debug") BUILD_TYPE="debug" ;; + "--release") BUILD_TYPE="release" ;; + #foreach( $opt in $options ) + "--${opt.argument}="*) ${opt.varName}=${D}{ARG#--${opt.argument}=} ;; + "--${opt.argument}") echo "option '$ARG' needs a value:"; echo " $ARG=${opt.valuesString}"; abort_configure ;; + #end + #foreach( $feature in $features ) + "--enable-${feature.arg}") ${feature.varName}=on ;; + "--disable-${feature.arg}") unset ${feature.varName} ;; + #end + "-"*) echo "unknown option: $ARG"; abort_configure ;; + esac +done + +## Begin unparsed content. ** +#[[ + +# set defaults for dir variables +: ${exec_prefix:="$prefix"} +: ${bindir:='${exec_prefix}/bin'} +: ${sbindir:='${exec_prefix}/sbin'} +: ${libdir:='${exec_prefix}/lib'} +: ${libexecdir:='${exec_prefix}/libexec'} +: ${datarootdir:='${prefix}/share'} +: ${datadir:='${datarootdir}'} +: ${sysconfdir:='${prefix}/etc'} +: ${sharedstatedir:='${prefix}/com'} +: ${localstatedir:='${prefix}/var'} +: ${runstatedir:='${localstatedir}/run'} +: ${includedir:='${prefix}/include'} +: ${infodir:='${datarootdir}/info'} +: ${mandir:='${datarootdir}/man'} +: ${localedir:='${datarootdir}/locale'} + +# check if a config.site exists and load it +if [ -n "$CONFIG_SITE" ]; then + # CONFIG_SITE may contain space separated file names + for cs in $CONFIG_SITE; do + printf "loading defaults from $cs... " + . "$cs" + echo ok + done +elif [ -f "$prefix/share/config.site" ]; then + printf "loading site defaults... " + . "$prefix/share/config.site" + echo ok +elif [ -f "$prefix/etc/config.site" ]; then + printf "loading site defaults... " + . "$prefix/etc/config.site" + echo ok +fi +]]# +## End of unparsed content ** + +# generate vars.mk +cat > "$TEMP_DIR/vars.mk" << __EOF__ +prefix=$prefix +exec_prefix=$exec_prefix +bindir=$bindir +sbindir=$sbindir +libdir=$libdir +libexecdir=$libexecdir +datarootdir=$datarootdir +datadir=$datadir +sysconfdir=$sysconfdir +sharedstatedir=$sharedstatedir +localstatedir=$localstatedir +runstatedir=$runstatedir +includedir=$includedir +infodir=$infodir +mandir=$mandir +localedir=$localedir +#foreach( $var in $vars ) +${var.varName}=${D}${var.varName} +#end +__EOF__ + +# toolchain detection utilities +. make/toolchain.sh + +# +# DEPENDENCIES +# + +# check languages +lang_c= +lang_cpp= +#foreach( $lang in $languages ) +if detect_${lang}_compiler ; then + lang_${lang}=1 +fi +#end + +# create buffer for make variables required by dependencies +echo > "$TEMP_DIR/make.mk" + +test_pkg_config() +{ + if "$PKG_CONFIG" --exists "$1" ; then : + else return 1 ; fi + if [ -z "$2" ] || "$PKG_CONFIG" --atleast-version="$2" "$1" ; then : + else return 1 ; fi + if [ -z "$3" ] || "$PKG_CONFIG" --exact-version="$3" "$1" ; then : + else return 1 ; fi + if [ -z "$4" ] || "$PKG_CONFIG" --max-version="$4" "$1" ; then : + else return 1 ; fi + return 0 +} + +print_check_msg() +{ + if [ -z "$1" ]; then + shift + printf "$@" + fi +} + +#foreach( $dependency in $namedDependencies ) +dependency_error_${dependency.id}() +{ + print_check_msg "${D}dep_checked_${dependency.id}" "checking for ${dependency.name}... " + #foreach( $sub in $dependency.subdependencies ) + # dependency $sub.fullName + while true + do + #if( $sub.platform ) + if notisplatform "${sub.platform}"; then + break + fi + #end + #if( $sub.toolchain ) + if notistoolchain "${sub.toolchain}"; then + break + fi + #end + #foreach( $np in $sub.notList ) + if isplatform "${np}" || istoolchain "${np}"; then + break + fi + #end + #foreach( $lang in $sub.lang ) + if [ -z "$lang_${lang}" ] ; then + break + fi + #end + #if( $sub.pkgconfig.size() > 0 ) + if [ -z "$PKG_CONFIG" ]; then + break + fi + #end + #foreach( $test in $sub.tests ) + if $test > /dev/null ; then + : + else + break + fi + #end + #foreach( $pkg in $sub.pkgconfig ) + if test_pkg_config "$pkg.name" "$pkg.atleast" "$pkg.exact" "$pkg.max" ; then + TEMP_CFLAGS="$TEMP_CFLAGS `"$PKG_CONFIG" --cflags $pkg.name`" + TEMP_LDFLAGS="$TEMP_LDFLAGS `"$PKG_CONFIG" --libs $pkg.name`" + else + break + fi + #end + #foreach( $flags in $sub.flags ) + #if( $flags.exec ) + if tmp_flags=`$flags.value` ; then + TEMP_$flags.varName="$TEMP_$flags.varName $tmp_flags" + else + break + fi + #else + TEMP_$flags.varName="$TEMP_$flags.varName $flags.value" + #end + #end + #if ( $sub.make.length() > 0 ) + cat >> $TEMP_DIR/make.mk << __EOF__ +# Dependency: $dependency.name +$sub.make +__EOF__ + #end + print_check_msg "${D}dep_checked_${dependency.id}" "yes\n" + dep_checked_${dependency.id}=1 + return 1 + done + + #end + print_check_msg "${D}dep_checked_${dependency.id}" "no\n" + dep_checked_${dependency.id}=1 + return 0 +} +#end + +# start collecting dependency information +echo > "$TEMP_DIR/flags.mk" + +DEPENDENCIES_FAILED= +ERROR=0 +#if( $dependencies.size() > 0 ) +# unnamed dependencies +TEMP_CFLAGS="$CFLAGS" +TEMP_CXXFLAGS="$CXXFLAGS" +TEMP_LDFLAGS="$LDFLAGS" +#foreach( $dependency in $dependencies ) +while true +do + #if( $dependency.platform ) + if notisplatform "${dependency.platform}"; then + break + fi + #end + #if( $dependency.toolchain ) + if notistoolchain "${dependency.toolchain}"; then + break + fi + #end + #foreach( $np in $dependency.notList ) + if isplatform "${np}" || istoolchain "${np}"; then + break + fi + #end + while true + do + #foreach( $lang in $dependency.lang ) + if [ -z "$lang_${lang}" ] ; then + ERROR=1 + break + fi + #end + #if( $dependency.pkgconfig.size() > 0 ) + if [ -z "$PKG_CONFIG" ]; then + ERROR=1 + break + fi + #end + #foreach( $pkg in $dependency.pkgconfig ) + print_check_msg "${D}dep_pkgconfig_checked_${pkg.id}" "checking for pkg-config package $pkg.name... " + if test_pkg_config "$pkg.name" "$pkg.atleast" "$pkg.exact" "$pkg.max" ; then + print_check_msg "${D}dep_pkgconfig_checked_${pkg.id}" "yes\n" + dep_pkgconfig_checked_${pkg.id}=1 + TEMP_CFLAGS="$TEMP_CFLAGS `"$PKG_CONFIG" --cflags $pkg.name`" + TEMP_LDFLAGS="$TEMP_LDFLAGS `"$PKG_CONFIG" --libs $pkg.name`" + else + print_check_msg "${D}dep_pkgconfig_checked_${pkg.id}" "no\n" + dep_pkgconfig_checked_${pkg.id}=1 + ERROR=1 + break + fi + #end + + #foreach( $flags in $dependency.flags ) + #if( $flags.exec ) + $flags.value > /dev/null + if tmp_flags=`$flags.value` ; then + TEMP_$flags.varName="$TEMP_$flags.varName $tmp_flags" + else + ERROR=1 + break + fi + #else + TEMP_$flags.varName="$TEMP_$flags.varName $flags.value" + #end + #end + #if ( $dependency.make.length() > 0 ) + cat >> "$TEMP_DIR/make.mk" << __EOF__ +$dependency.make +__EOF__ + #end + break + done + break +done +#end + +# add general dependency flags to flags.mk +echo "# general flags" >> "$TEMP_DIR/flags.mk" +if [ -n "${TEMP_CFLAGS}" ] && [ -n "$lang_c" ]; then + echo "CFLAGS += $TEMP_CFLAGS" >> "$TEMP_DIR/flags.mk" +fi +if [ -n "${TEMP_CXXFLAGS}" ] && [ -n "$lang_cpp" ]; then + echo "CXXFLAGS += $TEMP_CXXFLAGS" >> "$TEMP_DIR/flags.mk" +fi +if [ -n "${TEMP_LDFLAGS}" ]; then + echo "LDFLAGS += $TEMP_LDFLAGS" >> "$TEMP_DIR/flags.mk" +fi +#end + +# +# OPTION VALUES +# +#foreach( $opt in $options ) +#foreach( $val in $opt.values ) +${val.func}() +{ + VERR=0 + #foreach( $dep in $val.dependencies ) + if dependency_error_$dep ; then + VERR=1 + fi + #end + if [ $VERR -ne 0 ]; then + return 1 + fi + #foreach( $def in $val.defines ) + TEMP_CFLAGS="$TEMP_CFLAGS ${def.toFlags()}" + TEMP_CXXFLAGS="$TEMP_CXXFLAGS ${def.toFlags()}" + #end + #if( $val.hasMake() ) + cat >> "$TEMP_DIR/make.mk" << __EOF__ +$val.make +__EOF__ + #end + return 0 +} +#end +#end + +# +# TARGETS +# + +#foreach( $target in $targets ) +echo >> "$TEMP_DIR/flags.mk" +#if ( $target.name ) +echo "configuring target: $target.name" +echo "# flags for target $target.name" >> "$TEMP_DIR/flags.mk" +#else +echo "configuring global target" +echo "# flags for unnamed target" >> "$TEMP_DIR/flags.mk" +#end +TEMP_CFLAGS= +TEMP_CXXFLAGS= +TEMP_LDFLAGS= + +#foreach( $dependency in $target.dependencies ) +if dependency_error_$dependency; then + DEPENDENCIES_FAILED="$DEPENDENCIES_FAILED ${dependency} " + ERROR=1 +fi +#end + +# Features +#foreach( $feature in $target.features ) +if [ -n "${D}${feature.varName}" ]; then +#foreach( $dependency in $feature.dependencies ) + # check dependency + if dependency_error_$dependency ; then + # "auto" features can fail and are just disabled in this case + if [ "${D}${feature.varName}" = "auto" ]; then + DISABLE_${feature.varName}=1 + else + DEPENDENCIES_FAILED="$DEPENDENCIES_FAILED ${dependency} " + ERROR=1 + fi + fi +#end + if [ -n "$DISABLE_${feature.varName}" ]; then + unset ${feature.varName} + fi +fi +if [ -n "${D}${feature.varName}" ]; then + : +#foreach( $def in $feature.defines ) + TEMP_CFLAGS="$TEMP_CFLAGS ${def.toFlags()}" + TEMP_CXXFLAGS="$TEMP_CXXFLAGS ${def.toFlags()}" +#end +#if( $feature.hasMake() ) + cat >> "$TEMP_DIR/make.mk" << __EOF__ +$feature.make +__EOF__ +#end +else + : +#foreach( $def in $feature.disabled.defines ) + TEMP_CFLAGS="$TEMP_CFLAGS ${def.toFlags()}" + TEMP_CXXFLAGS="$TEMP_CXXFLAGS ${def.toFlags()}" +#end +#if( $feature.disabled.hasMake() ) + cat >> "$TEMP_DIR/make.mk" << __EOF__ +$feature.disabled.make +__EOF__ +#end +#foreach( $dependency in $feature.disabled.dependencies ) + if dependency_error_$dependency ; then + DEPENDENCIES_FAILED="$DEPENDENCIES_FAILED ${dependency} " + ERROR=1 + fi +#end +fi +#end + +#foreach( $opt in $target.options ) +# Option: --${opt.argument} +if [ -z "${D}${opt.varName}" ]; then + echo "auto-detecting option '${opt.argument}'" + SAVED_ERROR="$ERROR" + SAVED_DEPENDENCIES_FAILED="$DEPENDENCIES_FAILED" + ERROR=1 + while true + do + #foreach( $optdef in $opt.defaults ) + #if( $optdef.platform ) + if isplatform "$optdef.platform"; then + #end + if $optdef.func ; then + echo " ${opt.argument}: ${optdef.valueName}" >> "$TEMP_DIR/options" + ERROR=0 + break + fi + #if( $optdef.platform ) + fi + #end + #end + break + done + if [ $ERROR -ne 0 ]; then + SAVED_ERROR=1 + SAVED_DEPENDENCIES_FAILED="option '${opt.argument}' $SAVED_DEPENDENCIES_FAILED" + fi + ERROR="$SAVED_ERROR" + DEPENDENCIES_FAILED="$SAVED_DEPENDENCIES_FAILED" +else + echo "checking option ${opt.argument} = ${D}${opt.varName}" + if false; then + false + #foreach( $optval in $opt.values ) + elif [ "${D}${opt.varName}" = "${optval.value}" ]; then + echo " ${opt.argument}: ${D}${opt.varName}" >> $TEMP_DIR/options + if $optval.func ; then + : + else + ERROR=1 + DEPENDENCIES_FAILED="option '${opt.argument}' $DEPENDENCIES_FAILED" + fi + #end + else + echo + echo "Invalid option value - usage:" + echo " --${opt.argument}=${opt.valuesString}" + abort_configure + fi +fi +#end + +if [ -n "${TEMP_CFLAGS}" ] && [ -n "$lang_c" ]; then + echo "${target.cFlags} += $TEMP_CFLAGS" >> "$TEMP_DIR/flags.mk" +fi +if [ -n "${TEMP_CXXFLAGS}" ] && [ -n "$lang_cpp" ]; then + echo "${target.cxxFlags} += $TEMP_CXXFLAGS" >> "$TEMP_DIR/flags.mk" +fi +if [ "$BUILD_TYPE" = "debug" ]; then + if [ -n "$lang_c" ]; then + echo '${target.cFlags} += ${DEBUG_CC_FLAGS}' >> "$TEMP_DIR/flags.mk" + fi + if [ -n "$lang_cpp" ]; then + echo '${target.cxxFlags} += ${DEBUG_CXX_FLAGS}' >> "$TEMP_DIR/flags.mk" + fi +fi +if [ "$BUILD_TYPE" = "release" ]; then + if [ -n "$lang_c" ]; then + echo '${target.cFlags} += ${RELEASE_CC_FLAGS}' >> "$TEMP_DIR/flags.mk" + fi + if [ -n "$lang_cpp" ]; then + echo '${target.cxxFlags} += ${RELEASE_CXX_FLAGS}' >> "$TEMP_DIR/flags.mk" + fi +fi +if [ -n "${TEMP_LDFLAGS}" ]; then + echo "${target.ldFlags} += $TEMP_LDFLAGS" >> "$TEMP_DIR/flags.mk" +fi + +#end + +# final result +if [ $ERROR -ne 0 ]; then + echo + echo "Error: Unresolved dependencies" + echo "$DEPENDENCIES_FAILED" + abort_configure +fi + +echo "configure finished" +echo +echo "Build Config:" +echo " PREFIX: $prefix" +echo " TOOLCHAIN: $TOOLCHAIN_NAME" +#if ( $options.size() > 0 ) +echo "Options:" +cat "$TEMP_DIR/options" +#end +#if ( $features.size() > 0 ) +echo "Features:" +#foreach( $feature in $features ) +if [ -n "${D}${feature.varName}" ]; then +echo " $feature.name: on" +else +echo " $feature.name: off" +fi +#end +#end +echo + +# generate the config.mk file +cat > "$TEMP_DIR/config.mk" << __EOF__ +# +# config.mk generated by configure +# + +__EOF__ +write_toolchain_defaults "$TEMP_DIR/toolchain.mk" +cat "$TEMP_DIR/vars.mk" "$TEMP_DIR/toolchain.mk" "$TEMP_DIR/flags.mk" "$TEMP_DIR/make.mk" > config.mk +rm -Rf "$TEMP_DIR"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/makefile.mk Sat Jan 11 13:45:38 2025 +0100 @@ -0,0 +1,36 @@ +# Copyright 2025 Mike Becker. All rights reserved. +# +# 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 COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT HOLDER 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. + +include config.mk + +clean: FORCE + rm -Rf build + +compile: build FORCE + @cd src && $(MAKE) + +update-rules: FORCE + make/update-rules.sh src + +FORCE: +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/project.xml Sat Jan 11 13:45:38 2025 +0100 @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project version="0.3" xmlns="http://unixwork.de/uwproj"> + <dependency> + <lang>cpp</lang> + </dependency> +</project> +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/toolchain.sh Sat Jan 11 13:45:38 2025 +0100 @@ -0,0 +1,200 @@ +#!/bin/sh +# +# toolchain detection +# + +if isplatform "bsd" && notisplatform "openbsd"; then + C_COMPILERS="clang gcc cc" + CPP_COMPILERS="clang++ g++ CC" +else + C_COMPILERS="gcc clang suncc cc" + CPP_COMPILERS="g++ clang++ sunCC CC" +fi +unset TOOLCHAIN +unset TOOLCHAIN_NAME +unset TOOLCHAIN_CC +unset TOOLCHAIN_CXX + +check_c_compiler() +{ + cat > "$TEMP_DIR/test.c" << __EOF__ +/* test file */ +#include <stdio.h> +int main(int argc, char **argv) { +#if defined(_MSC_VER) + printf("msc\n"); +#elif defined(__clang__) + printf("clang gnuc\n"); +#elif defined(__GNUC__) + printf("gcc gnuc\n"); +#elif defined(__sun) + printf("suncc\n"); +#else + printf("unknown\n"); +#endif + return 0; +} +__EOF__ + rm -f "$TEMP_DIR/checkcc" + $1 -o "$TEMP_DIR/checkcc" $CFLAGS $LDFLAGS "$TEMP_DIR/test.c" 2> /dev/null +} + +check_cpp_compiler() +{ + cat > "$TEMP_DIR/test.cpp" << __EOF__ +/* test file */ +#include <iostream> +int main(int argc, char **argv) { +#if defined(_MSC_VER) + std::cout << "msc" << std::endl; +#elif defined(__clang__) + std::cout << "clang gnuc" << std::endl; +#elif defined(__GNUC__) + std::cout << "gcc gnuc" << std::endl; +#elif defined(__sun) + std::cout << "suncc" << std::endl; +#else + std::cout << "cc" << std::endl; +#endif + return 0; +} +__EOF__ + rm -f "$TEMP_DIR/checkcc" + $1 -o "$TEMP_DIR/checkcc" $CXXFLAGS $LDFLAGS "$TEMP_DIR/test.cpp" 2> /dev/null +} + +create_libtest_source() +{ + # $1: filename + # $2: optional include + cat > "$TEMP_DIR/$1" << __EOF__ +/* libtest file */ +int main(int argc, char **argv) { + return 0; +} +__EOF__ + if [ -n "$2" ]; then + echo "#include <$2>" >> "$TEMP_DIR/$1" + fi +} + +check_c_lib() +{ + # $1: libname + # $2: optional include + if [ -z "$TOOLCHAIN_CC" ]; then + return 1 + fi + create_libtest_source "test.c" "$2" + rm -f "$TEMP_DIR/checklib" + $TOOLCHAIN_CC -o "$TEMP_DIR/checklib" $CFLAGS $LDFLAGS "-l$1" "$TEMP_DIR/test.c" 2> /dev/null +} + +check_cpp_lib() +{ + # $1: libname + # $2: optional include + if [ -z "$TOOLCHAIN_CXX" ]; then + return 1 + fi + create_libtest_source "test.cpp" "$2" + rm -f "$TEMP_DIR/checklib" + $TOOLCHAIN_CXX -o "$TEMP_DIR/checklib" $CXXFLAGS $LDFLAGS "-l$1" "$TEMP_DIR/test.cpp" 2> /dev/null +} + +check_lib() +{ + # $1: libname + # $2: optional include + if [ -n "$TOOLCHAIN_CC" ]; then + check_c_lib "$1" "$2" + elif [ -n "$TOOLCHAIN_CXX" ]; then + check_cpp_lib "$1" "$2" + fi +} + +detect_c_compiler() +{ + if [ -n "$TOOLCHAIN_CC" ]; then + return 0 + fi + printf "detect C compiler... " + if [ -n "$CC" ]; then + if check_c_compiler "$CC"; then + TOOLCHAIN_CC=$CC + TOOLCHAIN=`"$TEMP_DIR/checkcc"` + TOOLCHAIN_NAME=`echo "$TOOLCHAIN" | cut -f1 -d' ' -` + echo "$CC" + return 0 + else + echo "$CC is not a working C compiler" + return 1 + fi + else + for COMP in $C_COMPILERS + do + if check_c_compiler "$COMP"; then + TOOLCHAIN_CC=$COMP + TOOLCHAIN=`"$TEMP_DIR/checkcc"` + TOOLCHAIN_NAME=`echo "$TOOLCHAIN" | cut -f1 -d' ' -` + echo "$COMP" + return 0 + fi + done + echo "not found" + return 1 + fi +} + +detect_cpp_compiler() +{ + if [ -n "$TOOLCHAIN_CXX" ]; then + return 0 + fi + printf "detect C++ compiler... " + + if [ -n "$CXX" ]; then + if check_cpp_compiler "$CXX"; then + TOOLCHAIN_CXX=$CXX + TOOLCHAIN=`"$TEMP_DIR/checkcc"` + TOOLCHAIN_NAME=`echo "$TOOLCHAIN" | cut -f1 -d' ' -` + echo "$CXX" + return 0 + else + echo "$CXX is not a working C++ compiler" + return 1 + fi + else + for COMP in $CPP_COMPILERS + do + if check_cpp_compiler "$COMP"; then + TOOLCHAIN_CXX=$COMP + TOOLCHAIN=`"$TEMP_DIR/checkcc"` + TOOLCHAIN_NAME=`echo "$TOOLCHAIN" | cut -f1 -d' ' -` + echo "$COMP" + return 0 + fi + done + echo "${TOOLCHAIN_CXX:-"not found"}" + return 1 + fi +} + +write_toolchain_defaults() +{ + echo "# toolchain" >> "$1" + if [ -n "$TOOLCHAIN_CC" ]; then + echo "CC = ${TOOLCHAIN_CC}" >> "$1" + fi + if [ -n "$TOOLCHAIN_CXX" ]; then + echo "CXX = ${TOOLCHAIN_CXX}" >> "$1" + fi + echo >> "$1" + if [ -f "make/${TOOLCHAIN_NAME}.mk" ]; then + cat "make/${TOOLCHAIN_NAME}.mk" >> "$1" + elif [ -f "make/cc.mk" ]; then + cat "make/cc.mk" >> "$1" + else + echo "!!! WARNING !!! Default toolchain flags not found. Configuration might be incomplete." + fi +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/update-rules.sh Sat Jan 11 13:45:38 2025 +0100 @@ -0,0 +1,55 @@ +#!/bin/sh + +dir="$1" +target="$2" +extra_flags="$3" + +if [ -z "$dir" ]; then + echo "Usage: $0 <src_dir>" + exit 1 +fi + +if [ -z "$target" ]; then + target='../build' +fi + +if [ -d "$dir" ]; then + : +else + echo "'$dir' is not a directory" + exit 1 +fi + +if [ -z "$CXX" ]; then + for cxx in g++ clang++ ; do + if command -v "$cxx" > /dev/null ; then + CXX="$cxx" + break + fi + done +fi + +if [ -z "$CXX" ]; then + echo "No suitable compiler found to generate make rules" + exit 1 +fi + +if command -v sed > /dev/null ; then + : +else + echo "You need the 'sed' program for this script to work." + exit 1 +fi + +cd "$dir" + +mv Makefile Makefile.old +sed '/FORCE:/q' Makefile.old > Makefile +echo >> Makefile +for file in `ls *.cpp` ; do + "$CXX" -MT "$target/${file/.cpp/\.o}" -MM $CXXFLAGS $extra_flags "$file" + printf '\t@echo "Compiling $<"\n' + printf '\t$(CXX) -o $@ $(CXXFLAGS) %s -c $<\n\n' "$extra_flags" +done >> Makefile +rm Makefile.old +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/uwproj.xsd Sat Jan 11 13:45:38 2025 +0100 @@ -0,0 +1,308 @@ +<?xml version="1.0" encoding="UTF-8"?> +<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" + xmlns="http://unixwork.de/uwproj" + targetNamespace="http://unixwork.de/uwproj" + elementFormDefault="qualified" + version="0.3" +> + <xs:element name="project" type="ProjectType"/> + + <xs:complexType name="ProjectType"> + <xs:annotation> + <xs:documentation> + The root element of an uwproj project. + Consists of an optional <code>config</code> element + and an arbitrary number of <code>dependency</code> + and <code>target</code> elements. + </xs:documentation> + </xs:annotation> + <xs:sequence> + <xs:element name="config" type="ConfigType" minOccurs="0" maxOccurs="unbounded"/> + <xs:element name="dependency" type="DependencyType" minOccurs="0" maxOccurs="unbounded"/> + <xs:element name="target" type="TargetType" minOccurs="0" maxOccurs="unbounded"/> + </xs:sequence> + <xs:attribute name="version" type="xs:string" use="required" /> + </xs:complexType> + + <xs:complexType name="ConfigType"> + <xs:annotation> + <xs:documentation> + <p> + The configuration section. + Consists of an arbitrary number of <code>var</code> elements. + </p> + <p> + The optional <code>platform</code> attribute may specify a <em>single</em> platform identifier and + the optional <code>not</code> attribute may specify a comma-separated list of platform identifiers. + The configure script shall skip this config declaration if the detected platform is not matching + the filter specification of these attributes. + </p> + </xs:documentation> + </xs:annotation> + <xs:sequence> + <xs:element name="var" type="ConfigVarType" minOccurs="0" maxOccurs="unbounded"/> + </xs:sequence> + <xs:attribute name="platform" type="xs:string"/> + <xs:attribute name="not" type="xs:string"/> + </xs:complexType> + + <xs:complexType name="ConfigVarType"> + <xs:annotation> + <xs:documentation> + The definition of a configuration variable. + <p> + Configuration variables are supposed to be used in the configure script and are also + written to the resulting config file (in contrast to make variables, which are only + written to the config file). + The <code>name</code> attribute is mandatory, the value is defined by the text body of the element. + The optional Boolean <code>exec</code> attribute (false by default) controls, whether the entire + definition is automatically executed under command substitution. + </p> + </xs:documentation> + </xs:annotation> + <xs:simpleContent> + <xs:extension base="xs:string"> + <xs:attribute name="name" type="xs:string" use="required"/> + <xs:attribute name="exec" type="xs:boolean" default="false"/> + </xs:extension> + </xs:simpleContent> + </xs:complexType> + + <xs:complexType name="PkgConfigType"> + <xs:annotation> + <xs:documentation> + Instructs configure to invoke <code>pkg-config</code>, if present on the system, to determine + compiler and linker flags. The text body of this element defines the package name to search. + To constrain the allowed versions, use the attributes <code>atleast, exact, max</code>. + </xs:documentation> + </xs:annotation> + <xs:simpleContent> + <xs:extension base="xs:string"> + <xs:attribute name="atleast" type="xs:string"/> + <xs:attribute name="exact" type="xs:string"/> + <xs:attribute name="max" type="xs:string"/> + </xs:extension> + </xs:simpleContent> + </xs:complexType> + + <xs:simpleType name="LangType"> + <xs:annotation> + <xs:documentation> + Requests a compiler for the specified language. Allowed values are + c, cpp. + </xs:documentation> + </xs:annotation> + <xs:restriction base="xs:string"> + <xs:enumeration value="c"/> + <xs:enumeration value="cpp"/> + </xs:restriction> + </xs:simpleType> + + <xs:complexType name="DependencyType"> + <xs:annotation> + <xs:documentation> + Declares a dependency. + <p> + If the optional <code>name</code> attribute is omitted, the dependency is global + and must be satisfied, otherwise configuration shall fail. + A <em>named dependency</em> can be referenced by a target (or is implicitly referenced + by the default target, if no targets are specified). + Multiple declarations for the same named dependency may exist, in which case each declaration + is checked one after another, until one block is satisfied. The result of the first satisfied + dependency declaration is supposed to be applied to the config file. + </p> + <p> + The optional <code>platform</code> attribute may specify a <em>single</em> platform identifier and + the optional <code>toolchain</code> attribute may specify a <em>single</em> toolchain. + The optional <code>not</code> attribute may specify a comma-separated list of platform and/or + toolchain identifiers. + The configure script shall skip this dependency declaration if the detected platform and toolchain + is not matching the filter specification of these attributes. + </p> + </xs:documentation> + </xs:annotation> + <xs:choice minOccurs="0" maxOccurs="unbounded"> + <xs:element name="lang" type="LangType"/> + <xs:element name="cflags" type="FlagsType"/> + <xs:element name="cxxflags" type="FlagsType"/> + <xs:element name="ldflags" type="FlagsType"/> + <xs:element name="pkgconfig" type="PkgConfigType"/> + <xs:element name="test" type="xs:string"> + <xs:annotation> + <xs:documentation> + Specifies a custom command that shall be executed to test whether this dependency is satisfied. + </xs:documentation> + </xs:annotation> + </xs:element> + <xs:element name="make" type="MakeVarType"/> + </xs:choice> + <xs:attribute name="name" type="xs:string"/> + <xs:attribute name="platform" type="xs:string"/> + <xs:attribute name="toolchain" type="xs:string"/> + <xs:attribute name="not" type="xs:string"/> + </xs:complexType> + + <xs:complexType name="FlagsType"> + <xs:annotation> + <xs:documentation> + Instructs configure to append the contents of the element's body to the respective flags variable. + If the optional <code>exec</code> flag is set to <code>true</code>, the contents are supposed to be + executed under command substitution <em>at configuration time</em> before they are applied. + </xs:documentation> + </xs:annotation> + <xs:simpleContent> + <xs:extension base="xs:string"> + <xs:attribute name="exec" type="xs:boolean" default="false"/> + </xs:extension> + </xs:simpleContent> + </xs:complexType> + + <xs:complexType name="TargetType"> + <xs:annotation> + <xs:documentation> + Declares a build target that is supposed to be configured. + <p> + If no build target is declared explicitly, an implicit default + target is generated, which has the <code>alldependencies</code> + flag set. + </p> + <p> + The optional <code>name</code> attribute is also used to generate a prefix + for the compiler and linker flags variables. + Furthermore, a target may consist of an arbitrary number of <code>feature</code>, + <code>option</code>, and <code>define</code> elements. + Named dependencies can be listed (separated by comma) in the <code>dependencies</code> + element. If this target shall use <em>all</em> available named dependencies, the empty + element <code>alldependencies</code> can be used as a shortcut. + </p> + </xs:documentation> + </xs:annotation> + <xs:choice minOccurs="0" maxOccurs="unbounded"> + <xs:element name="feature" type="FeatureType"/> + <xs:element name="option" type="OptionType"/> + <xs:element name="define" type="DefineType"/> + <xs:element name="dependencies" type="DependenciesType"/> + <xs:element name="alldependencies"> + <xs:complexType/> + </xs:element> + </xs:choice> + <xs:attribute name="name" type="xs:string"/> + </xs:complexType> + + <xs:complexType name="FeatureType"> + <xs:annotation> + <xs:documentation> + Declares an optional feature, that can be enabled during configuration, if all + <code>dependencies</code> are satisfied. + If a feature is enabled, all <code>define</code> and <code>make</code> definitions are + supposed to be applied to the config file. + If a feature is disabled, an optional <code>disabled</code> element may specify which + <code>define</code> and <code>make</code> definitions are supposed to be applied. + There might also be <code>dependencies</code> when the feature is disabled (e.g. specifying a fallback). + In case the optional <code>default</code> attribute is set to true, the feature is enabled by default + and is supposed to be automatically disabled (without error) when the dependencies are not satisfied. + The name that is supposed to be used for the --enable and --disable arguments can be optionally + specified with the <code>arg</code> attribute. Otherwise, the <code>name</code> is used by default. + Optionally, a description for the help text of the resulting configure script can be specified by + adding a <code>desc</code> element. + </xs:documentation> + </xs:annotation> + <xs:choice minOccurs="0" maxOccurs="unbounded"> + <xs:group ref="TargetDataGroup"/> + <xs:element name="desc" type="xs:string"/> + <xs:element name="disabled"> + <xs:complexType> + <xs:choice minOccurs="0" maxOccurs="unbounded"> + <xs:group ref="TargetDataGroup"/> + </xs:choice> + </xs:complexType> + </xs:element> + </xs:choice> + <xs:attribute name="name" type="xs:string" use="required"/> + <xs:attribute name="arg" type="xs:string"/> + <xs:attribute name="default" type="xs:boolean" default="false"/> + </xs:complexType> + + <xs:complexType name="OptionType"> + <xs:annotation> + <xs:documentation> + Declares a configuration option. + The option argument name is specified with the <code>arg</code> attribute. + Then, the children of this element specify possible <code>values</code> by defining the conditions + (in terms of dependencies) and effects (in terms of defines and make variables) of each value. + Finally, a set of <code>default</code>s is specified which supposed to automagically select the most + appropriate value for a specific platform under the available dependencies (in case the option is not + explicitly specified by using the command line argument). + </xs:documentation> + </xs:annotation> + <xs:sequence> + <xs:element name="value" type="OptionValueType" minOccurs="0" maxOccurs="unbounded"/> + <xs:element name="default" type="OptionDefaultType" minOccurs="0" maxOccurs="unbounded"/> + </xs:sequence> + <xs:attribute name="arg" type="xs:string" use="required"/> + </xs:complexType> + + <xs:complexType name="OptionValueType"> + <xs:annotation> + <xs:documentation> + Declares a possible value for the option (in the <code>str</code> attribute) and + the conditions (<code>dependencies</code>) and effects, the value has. + </xs:documentation> + </xs:annotation> + <xs:choice minOccurs="0" maxOccurs="unbounded"> + <xs:group ref="TargetDataGroup"/> + </xs:choice> + <xs:attribute name="str" type="xs:string" use="required"/> + </xs:complexType> + + <xs:complexType name="OptionDefaultType"> + <xs:annotation> + <xs:documentation> + Specifies a default value for this option. Multiple default values can be specified, in which case + they are checked one after another for availability. With the optional <code>platform</code> attribute, + the default value can be constrained to a <em>single</em> specific platform and is supposed to be + skipped by configure, when this platform is not detected. + </xs:documentation> + </xs:annotation> + <xs:attribute name="value" type="xs:string" use="required"/> + <xs:attribute name="platform" type="xs:string"/> + </xs:complexType> + + <xs:group name="TargetDataGroup"> + <xs:choice> + <xs:element name="define" type="DefineType" minOccurs="0" maxOccurs="unbounded"/> + <xs:element name="dependencies" type="DependenciesType" minOccurs="0" maxOccurs="unbounded"/> + <xs:element name="make" type="MakeVarType" minOccurs="0" maxOccurs="unbounded"/> + </xs:choice> + </xs:group> + + <xs:complexType name="DefineType"> + <xs:annotation> + <xs:documentation> + Specifies C/C++ pre-processor definitions that are supposed to + be appended to the compiler flags, if supported. + (Note: for example, Fortran also supports C/C++ style pre-processor definitions under + certain circumstances) + </xs:documentation> + </xs:annotation> + <xs:attribute name="name" type="xs:string" use="required"/> + <xs:attribute name="value" type="xs:string"/> + </xs:complexType> + + <xs:simpleType name="DependenciesType"> + <xs:annotation> + <xs:documentation>A comma-separated list of named dependencies.</xs:documentation> + </xs:annotation> + <xs:restriction base="xs:string"/> + </xs:simpleType> + + <xs:simpleType name="MakeVarType"> + <xs:annotation> + <xs:documentation> + The text contents in the body of this element are supposed to be appended literally + to the config file without prior processing. + </xs:documentation> + </xs:annotation> + <xs:restriction base="xs:string"/> + </xs:simpleType> +</xs:schema>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/Makefile Sat Jan 11 13:45:38 2025 +0100 @@ -0,0 +1,46 @@ +# Copyright 2025 Mike Becker. All rights reserved. +# +# 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 COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT HOLDER 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. + +include ../config.mk + +SRC=main.cpp +OBJ=$(SRC:%.cpp=../build/%.o) +OUTPUT=../build/fallusmeter + +all: $(OUTPUT) FORCE + +$(OUTPUT): $(OBJ) + $(CXX) $(LDFLAGS) -o $@ $^ + +clean: FORCE + rm -Rf build + +compile: config.mk build FORCE + @cd src && $(MAKE) + +FORCE: + +../build/main.o: main.cpp + @echo "Compiling $<" + $(CXX) -o $@ $(CXXFLAGS) -c $< +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/main.cpp Sat Jan 11 13:45:38 2025 +0100 @@ -0,0 +1,28 @@ +/* Copyright 2025 Mike Becker. All rights reserved. + * + * 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 COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT HOLDER 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. + */ + +int main() { + return 0; +} +