# HG changeset patch # User Mike Becker # Date 1696620070 -7200 # Node ID 593b604581570b537e3085393b7001505d4fb4cf initial commit diff -r 000000000000 -r 593b60458157 .hgignore --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/.hgignore Fri Oct 06 21:21:10 2023 +0200 @@ -0,0 +1,4 @@ +.idea/ +nbproject/ +build/ +config.mk diff -r 000000000000 -r 593b60458157 DEPENDENCIES --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DEPENDENCIES Fri Oct 06 21:21:10 2023 +0200 @@ -0,0 +1,3 @@ +Fedora: dnf install SDL2-devel SDL2_ttf-devel glew-devel +Arch: pacman -Sy sdl2 sdl2_ttf glew pkgconf +FreeBSD: pkg install sdl2 sdl2_ttf glew pkgconf diff -r 000000000000 -r 593b60458157 LICENSE --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/LICENSE Fri Oct 06 21:21:10 2023 +0200 @@ -0,0 +1,23 @@ +Copyright 2023 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. diff -r 000000000000 -r 593b60458157 Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Makefile Fri Oct 06 21:21:10 2023 +0200 @@ -0,0 +1,51 @@ +# Copyright 2023 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: build/test/sandbox + +build/test/sandbox: build/test build/lib/libascension.a config.mk FORCE + @cd test && $(MAKE) + +build/lib/libascension.a: build/lib config.mk FORCE + @cd src && $(MAKE) + +build/test: + mkdir -p build/test + +build/lib: + mkdir -p build/lib + +clean: + rm -f -R build + +install: + @echo "Not supported at the moment" + +config.mk: + @echo "create config" + @./configure + +FORCE: + diff -r 000000000000 -r 593b60458157 configure --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/configure Fri Oct 06 21:21:10 2023 +0200 @@ -0,0 +1,423 @@ +#!/bin/sh + +# 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 +PREFIX=/usr +EPREFIX= +BINDIR= +SBINDIR= +LIBDIR= +LIBEXECDIR= +DATADIR= +SYSCONFDIR= +SHAREDSTATEDIR= +LOCALSTATEDIR= +INCLUDEDIR= +INFODIR= +MANDIR= + +# custom variables + +# features + +# clean abort +abort_configure() +{ + rm -Rf "$TEMP_DIR" + exit 1 +} + +# help text +printhelp() +{ + echo "Usage: $0 [OPTIONS]..." + cat << __EOF__ +Installation directories: + --prefix=PREFIX path prefix for architecture-independent files + [/usr] + --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] + --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] + +__EOF__ +} + +# +# parse arguments +# +BUILD_TYPE="default" +for ARG in "$@" +do + case "$ARG" in + "--prefix="*) PREFIX=${ARG#--prefix=} ;; + "--exec-prefix="*) EPREFIX=${ARG#--exec-prefix=} ;; + "--bindir="*) BINDIR=${ARG#----bindir=} ;; + "--sbindir="*) SBINDIR=${ARG#--sbindir=} ;; + "--libdir="*) LIBDIR=${ARG#--libdir=} ;; + "--libexecdir="*) LIBEXECDIR=${ARG#--libexecdir=} ;; + "--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} ;; + "--help"*) printhelp; abort_configure ;; + "--debug") BUILD_TYPE="debug" ;; + "--release") BUILD_TYPE="release" ;; + "-"*) echo "unknown option: $ARG"; abort_configure ;; + esac +done + + +# set dir variables +: ${EPREFIX:="$PREFIX"} +: ${BINDIR:="$EPREFIX/bin"} +: ${SBINDIR:="$EPREFIX/sbin"} +: ${LIBDIR:="$EPREFIX/lib"} +: ${LIBEXECDIR:="$EPREFIX/libexec"} +: ${DATADIR:="$PREFIX/share"} +: ${SYSCONFDIR:="$PREFIX/etc"} +: ${SHAREDSTATEDIR:="$PREFIX/com"} +: ${LOCALSTATEDIR:="$PREFIX/var"} +: ${INCLUDEDIR:="$PREFIX/include"} +: ${INFODIR:="$PREFIX/info"} +: ${MANDIR:="$PREFIX/man"} + +# 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" +fi +if [ "$OS" = "Linux" ]; then + PLATFORM="linux unix" +fi +if [ "$OS" = "FreeBSD" ]; then + PLATFORM="freebsd bsd unix" +fi +if [ "$OS" = "Darwin" ]; then + PLATFORM="macos osx bsd unix" +fi +if echo "$OS" | grep -i "MINGW" > /dev/null; then + PLATFORM="windows mingw" +fi +: ${PLATFORM:="unix"} + +PLATFORM_NAME=`echo "$PLATFORM" | cut -f1 -d' ' -` +echo "$PLATFORM_NAME" + +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 +} + + +# generate vars.mk +cat > "$TEMP_DIR/vars.mk" << __EOF__ +PREFIX="$PREFIX" +EPREFIX="$EPREFIX" +BINDIR="$BINDIR" +SBINDIR="$SBINDIR" +LIBDIR="$LIBDIR" +LIBEXECDIR="$LIBEXECDIR" +DATADIR="$DATADIR" +SYSCONFDIR="$SYSCONFDIR" +SHAREDSTATEDIR="$SHAREDSTATEDIR" +LOCALSTATEDIR="$LOCALSTATEDIR" +INCLUDEDIR="$INCLUDEDIR" +INFODIR="$INFODIR" +MANDIR="$MANDIR" +__EOF__ +sort -u -o "$TEMP_DIR/vars.mk" "$TEMP_DIR/vars.mk" + + +# toolchain detection utilities +. make/toolchain.sh + +# +# DEPENDENCIES +# + +# check languages +lang_c= +lang_cpp= +if detect_c_compiler ; then + lang_c=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 +} + +dependency_error_sdl2_ttf() +{ + printf "checking for sdl2_ttf... " + # dependency sdl2_ttf + while true + do + if [ -z "$PKG_CONFIG" ]; then + break + fi + if test_pkg_config "SDL2_ttf" "" "" "" ; then + TEMP_CFLAGS="$TEMP_CFLAGS `"$PKG_CONFIG" --cflags SDL2_ttf`" + TEMP_LDFLAGS="$TEMP_LDFLAGS `"$PKG_CONFIG" --libs SDL2_ttf`" + else + break + fi + echo yes + return 1 + done + + echo no + return 0 +} +dependency_error_sdl2() +{ + printf "checking for sdl2... " + # dependency sdl2 + while true + do + if [ -z "$PKG_CONFIG" ]; then + break + fi + if test_pkg_config "sdl2" "" "" "" ; then + TEMP_CFLAGS="$TEMP_CFLAGS `"$PKG_CONFIG" --cflags sdl2`" + TEMP_LDFLAGS="$TEMP_LDFLAGS `"$PKG_CONFIG" --libs sdl2`" + else + break + fi + echo yes + return 1 + done + + echo no + return 0 +} +dependency_error_glew() +{ + printf "checking for glew... " + # dependency glew + while true + do + if [ -z "$PKG_CONFIG" ]; then + break + fi + if test_pkg_config "glew" "" "" "" ; then + TEMP_CFLAGS="$TEMP_CFLAGS `"$PKG_CONFIG" --cflags glew`" + TEMP_LDFLAGS="$TEMP_LDFLAGS `"$PKG_CONFIG" --libs glew`" + else + break + fi + echo yes + return 1 + done + + echo no + return 0 +} +dependency_error_ucx() +{ + printf "checking for ucx... " + # dependency ucx + while true + do + if check_lib ucx cx/common.h > /dev/null ; then + : + else + break + fi + TEMP_LDFLAGS="$TEMP_LDFLAGS -lucx" + echo yes + return 1 + done + + echo no + return 0 +} + + + + +# start collecting dependency information +echo > "$TEMP_DIR/flags.mk" + +DEPENDENCIES_FAILED= +ERROR=0 +# unnamed dependencies +TEMP_CFLAGS= +TEMP_CXXFLAGS= +TEMP_LDFLAGS= +while true +do + while true + do + if [ -z "$lang_c" ] ; 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}" -a -n "$lang_c" ]; then + echo "CFLAGS += $TEMP_CFLAGS" >> "$TEMP_DIR/flags.mk" +fi +if [ -n "${TEMP_CXXFLAGS}" -a -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= + +if dependency_error_sdl2_ttf; then + DEPENDENCIES_FAILED="$DEPENDENCIES_FAILED sdl2_ttf " + ERROR=1 +fi +if dependency_error_sdl2; then + DEPENDENCIES_FAILED="$DEPENDENCIES_FAILED sdl2 " + ERROR=1 +fi +if dependency_error_glew; then + DEPENDENCIES_FAILED="$DEPENDENCIES_FAILED glew " + ERROR=1 +fi +if dependency_error_ucx; then + DEPENDENCIES_FAILED="$DEPENDENCIES_FAILED ucx " + ERROR=1 +fi + +# Features + + +if [ -n "${TEMP_CFLAGS}" -a -n "$lang_c" ]; then + echo "CFLAGS += $TEMP_CFLAGS" >> "$TEMP_DIR/flags.mk" +fi +if [ -n "${TEMP_CXXFLAGS}" -a -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" + + diff -r 000000000000 -r 593b60458157 make/cc.mk --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/cc.mk Fri Oct 06 21:21:10 2023 +0200 @@ -0,0 +1,11 @@ +# +# cc toolchain config +# + +CFLAGS = +DEBUG_CC_FLAGS = -g +RELEASE_CC_FLAGS = -O3 -DNDEBUG +LDFLAGS = + +SHLIB_CFLAGS = -fPIC +SHLIB_LDFLAGS = -shared \ No newline at end of file diff -r 000000000000 -r 593b60458157 make/configure.vm --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/configure.vm Fri Oct 06 21:21:10 2023 +0200 @@ -0,0 +1,609 @@ +#!/bin/sh + +# 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 +PREFIX=/usr +EPREFIX= +BINDIR= +SBINDIR= +LIBDIR= +LIBEXECDIR= +DATADIR= +SYSCONFDIR= +SHAREDSTATEDIR= +LOCALSTATEDIR= +INCLUDEDIR= +INFODIR= +MANDIR= + +# custom variables +#foreach( $var in $vars ) +#if( $var.exec ) +${var.varName}=`${var.value}` +#else +${var.varName}="${var.value}" +#end +#end + +# features +#foreach( $feature in $features ) +#if( ${feature.auto} ) +${feature.varName}=auto +#end +#end + +# clean abort +abort_configure() +{ + rm -Rf "$TEMP_DIR" + exit 1 +} + +# help text +printhelp() +{ + echo "Usage: $0 [OPTIONS]..." + cat << __EOF__ +Installation directories: + --prefix=PREFIX path prefix for architecture-independent files + [/usr] + --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] + --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] + +#if( $options.size() > 0 ) +Options: + --debug add extra compile flags for debug builds + --release add extra compile flags for release builds +#foreach( $opt in $options ) + --${opt.argument}=${opt.valuesString} +#end + +#end +#if( $features.size() > 0 ) +Optional Features: +#foreach( $feature in $features ) +#if( $feature.auto ) + --disable-${feature.arg} +#else + --enable-${feature.arg} +#end +#end + +#end +__EOF__ +} + +# +# parse arguments +# +BUILD_TYPE="default" +#set( $D = '$' ) +for ARG in "$@" +do + case "$ARG" in + "--prefix="*) PREFIX=${D}{ARG#--prefix=} ;; + "--exec-prefix="*) EPREFIX=${D}{ARG#--exec-prefix=} ;; + "--bindir="*) BINDIR=${D}{ARG#----bindir=} ;; + "--sbindir="*) SBINDIR=${D}{ARG#--sbindir=} ;; + "--libdir="*) LIBDIR=${D}{ARG#--libdir=} ;; + "--libexecdir="*) LIBEXECDIR=${D}{ARG#--libexecdir=} ;; + "--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} ;; + "--help"*) printhelp; abort_configure ;; + "--debug") BUILD_TYPE="debug" ;; + "--release") BUILD_TYPE="release" ;; + #foreach( $opt in $options ) + "--${opt.argument}="*) ${opt.varName}=${D}{ARG#--${opt.argument}=} ;; + #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 dir variables +: ${EPREFIX:="$PREFIX"} +: ${BINDIR:="$EPREFIX/bin"} +: ${SBINDIR:="$EPREFIX/sbin"} +: ${LIBDIR:="$EPREFIX/lib"} +: ${LIBEXECDIR:="$EPREFIX/libexec"} +: ${DATADIR:="$PREFIX/share"} +: ${SYSCONFDIR:="$PREFIX/etc"} +: ${SHAREDSTATEDIR:="$PREFIX/com"} +: ${LOCALSTATEDIR:="$PREFIX/var"} +: ${INCLUDEDIR:="$PREFIX/include"} +: ${INFODIR:="$PREFIX/info"} +: ${MANDIR:="$PREFIX/man"} + +# 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" +fi +if [ "$OS" = "Linux" ]; then + PLATFORM="linux unix" +fi +if [ "$OS" = "FreeBSD" ]; then + PLATFORM="freebsd bsd unix" +fi +if [ "$OS" = "Darwin" ]; then + PLATFORM="macos osx bsd unix" +fi +if echo "$OS" | grep -i "MINGW" > /dev/null; then + PLATFORM="windows mingw" +fi +: ${PLATFORM:="unix"} + +PLATFORM_NAME=`echo "$PLATFORM" | cut -f1 -d' ' -` +echo "$PLATFORM_NAME" + +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 +} +]]# +## End of unparsed content ** + +# generate vars.mk +cat > "$TEMP_DIR/vars.mk" << __EOF__ +PREFIX="$PREFIX" +EPREFIX="$EPREFIX" +BINDIR="$BINDIR" +SBINDIR="$SBINDIR" +LIBDIR="$LIBDIR" +LIBEXECDIR="$LIBEXECDIR" +DATADIR="$DATADIR" +SYSCONFDIR="$SYSCONFDIR" +SHAREDSTATEDIR="$SHAREDSTATEDIR" +LOCALSTATEDIR="$LOCALSTATEDIR" +INCLUDEDIR="$INCLUDEDIR" +INFODIR="$INFODIR" +MANDIR="$MANDIR" +#foreach( $var in $vars ) +${var.varName}="${D}${var.varName}" +#end +__EOF__ +sort -u -o "$TEMP_DIR/vars.mk" "$TEMP_DIR/vars.mk" + + +# 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 +} + +#foreach( $dependency in $namedDependencies ) +dependency_error_${dependency.id}() +{ + printf "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 + #foreach( $np in $sub.notList ) + if isplatform "${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 + echo yes + return 1 + done + + #end + echo no + return 0 +} +#end + + + + +# start collecting dependency information +echo > "$TEMP_DIR/flags.mk" + +DEPENDENCIES_FAILED= +ERROR=0 +#if( $dependencies.size() > 0 ) +# unnamed dependencies +TEMP_CFLAGS= +TEMP_CXXFLAGS= +TEMP_LDFLAGS= +#foreach( $dependency in $dependencies ) +while true +do + #if( $dependency.platform ) + if notisplatform "${dependency.platform}"; then + break + fi + #end + #foreach( $np in $dependency.notList ) + if isplatform "${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 ) + printf "checking for pkg-config package $pkg.name... " + if test_pkg_config "$pkg.name" "$pkg.atleast" "$pkg.exact" "$pkg.max" ; then + echo yes + TEMP_CFLAGS="$TEMP_CFLAGS `"$PKG_CONFIG" --cflags $pkg.name`" + TEMP_LDFLAGS="$TEMP_LDFLAGS `"$PKG_CONFIG" --libs $pkg.name`" + else + echo no + 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}" -a -n "$lang_c" ]; then + echo "CFLAGS += $TEMP_CFLAGS" >> "$TEMP_DIR/flags.mk" +fi +if [ -n "${TEMP_CXXFLAGS}" -a -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 +#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 + fi +fi +#end + +if [ -n "${TEMP_CFLAGS}" -a -n "$lang_c" ]; then + echo "${target.cFlags} += $TEMP_CFLAGS" >> "$TEMP_DIR/flags.mk" +fi +if [ -n "${TEMP_CXXFLAGS}" -a -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" + + diff -r 000000000000 -r 593b60458157 make/project.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/project.xml Fri Oct 06 21:21:10 2023 +0200 @@ -0,0 +1,24 @@ + + + + c + + + + check_lib ucx cx/common.h + -lucx + + + + sdl2 + + + + SDL2_ttf + + + + glew + + + diff -r 000000000000 -r 593b60458157 make/toolchain.sh --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/toolchain.sh Fri Oct 06 21:21:10 2023 +0200 @@ -0,0 +1,186 @@ +#!/bin/sh +# +# toolchain detection +# + +C_COMPILERS="gcc clang suncc cc" +CPP_COMPILERS="g++ clang++ sunCC CC" +unset TOOLCHAIN_NAME +unset TOOLCHAIN_CC +unset TOOLCHAIN_CXX + +check_c_compiler() +{ + cat > "$TEMP_DIR/test.c" << __EOF__ +/* test file */ +#include +int main(int argc, char **argv) { +#if defined(__clang__) + printf("clang\n"); +#elif defined(__GNUC__) + printf("gcc\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 +int main(int argc, char **argv) { +#if defined(__clang__) + std::cout << "clang" << std::endl; +#elif defined(__GNUC__) + std::cout << "gcc" << 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_NAME=`"$TEMP_DIR/checkcc"` + 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_NAME=`"$TEMP_DIR/checkcc"` + 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_NAME=`"$TEMP_DIR/checkcc"` + 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_NAME=`"$TEMP_DIR/checkcc"` + 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 +} diff -r 000000000000 -r 593b60458157 make/uwproj.xsd --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/uwproj.xsd Fri Oct 06 21:21:10 2023 +0200 @@ -0,0 +1,131 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff -r 000000000000 -r 593b60458157 src/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/Makefile Fri Oct 06 21:21:10 2023 +0200 @@ -0,0 +1,46 @@ +# Copyright 2023 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 + +BUILD_DIR=../build/lib + +SRC = core.c + +OBJ = $(SRC:%.c=$(BUILD_DIR)/%.o) + +all: $(BUILD_DIR)/libascension.a FORCE + echo "You have successfully ascended." + +$(BUILD_DIR)/libascension.a: $(OBJ) + echo "Creating library..." + $(AR) $(ARFLAGS) $@ $^ + +FORCE: + +$(BUILD_DIR)/core.o: core.c ascension/core.h ascension/utils.h + echo "Compiling $<" + $(CC) -o $@ $(CFLAGS) -c $< + diff -r 000000000000 -r 593b60458157 src/ascension/core.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/ascension/core.h Fri Oct 06 21:21:10 2023 +0200 @@ -0,0 +1,157 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * Copyright 2023 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. + */ + +#ifndef ASCENSION_CORE_H +#define ASCENSION_CORE_H + +#include +#include +#include + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** The flag for the overall initialized state. */ +#define ASC_FLAG_INITILIZED 0x01u + +/** Flag is set, when error buffer contains new error information. */ +#define ASC_FLAG_HAS_ERROR 0x02u + +/** Flag is set, when SDL wants to quit the application. */ +#define ASC_FLAG_QUIT 0x80000000u + +typedef struct AscContext { + CxBuffer error_buffer; + CxList *windows; + unsigned int flags; +} AscContext; + +/** Global ascension context. */ +extern AscContext asc_context; + +typedef struct AscWindowSettings { + int depth_size; + int vsync; + int width; + int height; + int fullscreen; + int gl_major_version; + int gl_minor_version; + char const* title; +} AscWindowSettings; + +typedef struct AscWindow { + SDL_Window* window; + SDL_GLContext glctx; + Uint32 id; + int width; + int height; +} AscWindow; + +void asc_context_initialize(void); +void asc_context_destroy(void); + +static inline bool asc_test_flag(unsigned int reg, int flag) { + return (reg & flag) == flag; +} + +static inline void asc_set_flag(unsigned int *reg, int flag) { + *reg |= flag; +} + +static inline void asc_clear_flag(unsigned int *reg, int flag) { + *reg &= ~flag; +} + +void asc_error_cxstr(cxstring text); +void asc_error_cchar(char const* text); +void asc_error_cuchar(unsigned char const* text); + +#define asc_error(text) _Generic((text), \ + char const*: asc_error_cchar, \ + unsigned char const*: asc_error_cuchar, \ + char*: asc_error_cchar, \ + unsigned char*: asc_error_cuchar, \ + cxstring: asc_error_cxstr)(text) + +bool asc_has_error(void); +char const* asc_get_error(void); +void asc_clear_error(void); + +/** + * Dispatches events and synchronizes all initialized windows. + * + * @return false, if one of the events is a QUIT event, true otherwise + */ +bool asc_loop_next(void); + +/** + * Initializes the settings structure with default values. + * + * @param settings an uninitialized settings object + */ +void asc_window_settings_init_defaults(AscWindowSettings* settings); + +/** + * Creates and initializes a new window and a corresponding OpenGL context. + * + * @param window the window structure + * @param settings the settings to be used for initialization + */ +void asc_window_initialize(AscWindow* window, AscWindowSettings const* settings); + +/** + * Destroys the window and its OpenGL context. + * + * Still alive windows will also be destroyed by asc_context_destroy() + * automatically. + * + * @param window the window + */ +void asc_window_destroy(AscWindow* window); + +/** + * Swaps buffers and adjusts the viewport to the current window size. + * + * This function is automatically invoked for all initialized windows + * by asc_loop_next(). You usually do not need to call this function manually. + * + * @param window the window + */ +void asc_window_sync(AscWindow const *window); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif /* ASCENSION_CORE_H */ + diff -r 000000000000 -r 593b60458157 src/ascension/utils.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/ascension/utils.h Fri Oct 06 21:21:10 2023 +0200 @@ -0,0 +1,48 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * Copyright 2023 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. + */ + +#ifndef ASCENSION_UTILS_H +#define ASCENSION_UTILS_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef NDEBUG +#define asc_dprintf(...) +#else +#define asc_dprintf(...) printf(__VA_ARGS__); putchar('\n') +#endif + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // ASCENSION_UTILS_H \ No newline at end of file diff -r 000000000000 -r 593b60458157 src/core.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/core.c Fri Oct 06 21:21:10 2023 +0200 @@ -0,0 +1,285 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * Copyright 2023 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 "ascension/core.h" +#include "ascension/utils.h" + +#include +#include + +static void asc_gl_debug_callback( + GLenum source, GLenum type, GLuint id, GLenum severity, + GLsizei length, const GLchar* message, + const void* userParam +) { + cxmutstr buf = cx_asprintf( + "source = %d, id = %u, type = %d, severity= %d, message = %.*s", + source, id, type, severity, length, message); + if (type == GL_DEBUG_TYPE_ERROR) { + asc_error(buf.ptr); + } else { + asc_dprintf("GL debug: %*.s", (int)buf.length, buf.ptr); + } + cx_strfree(&buf); +} + +AscContext asc_context; + +// forward declarations +static void asc_window_destroy_impl(AscWindow* window); + +void asc_context_initialize(void) { + if (asc_test_flag(asc_context.flags, ASC_FLAG_INITILIZED)) + return; + asc_clear_flag(&asc_context.flags, ASC_FLAG_HAS_ERROR); + + // initialize error buffer + cxBufferInit( + &asc_context.error_buffer, + NULL, + 256, + NULL, + CX_BUFFER_AUTO_EXTEND + ); + + // initialize lists + asc_context.windows = cxLinkedListCreateSimple(CX_STORE_POINTERS); + asc_context.windows->simple_destructor = + (cx_destructor_func)asc_window_destroy_impl; + + // initialize SDL + if (SDL_Init(SDL_INIT_VIDEO) < 0) { + asc_error(SDL_GetError()); + } else { + if (TTF_Init() < 0) { + asc_error(TTF_GetError()); + } + } + SDL_ClearError(); + asc_set_flag(&asc_context.flags, ASC_FLAG_INITILIZED); + asc_dprintf("Ascension context initialized."); +} + +void asc_context_destroy(void) { + // destroy lists + cxListDestroy(asc_context.windows); + + // quit SDL + if (TTF_WasInit()) + TTF_Quit(); + SDL_Quit(); + + // destroy the error buffer + cxBufferDestroy(&asc_context.error_buffer); + asc_context.flags = 0; + asc_dprintf("Ascension context destroyed."); +} + +void asc_error_cchar(char const* text) { + asc_error_cxstr(cx_str(text)); +} + +void asc_error_cuchar(unsigned char const* text) { + asc_error_cxstr(cx_str((char const*)text)); +} + +void asc_error_cxstr(cxstring text) { + if (text.length == 0) return; + + // write error to debug output + asc_dprintf("ERROR: %*.s", (int)text.length, text.ptr); + + // write error to buffer + CxBuffer* buf = &asc_context.error_buffer; + cxBufferWrite(text.ptr, 1, text.length, buf); + cxBufferPut(buf, '\n'); + + asc_set_flag(&asc_context.flags, ASC_FLAG_HAS_ERROR); +} + +bool asc_has_error(void) { + return asc_test_flag(asc_context.flags, ASC_FLAG_HAS_ERROR); +} + +char const* asc_get_error(void) { + // we zero-terminate the current buffer contents before providing them + cxBufferPut(&asc_context.error_buffer, 0); + --asc_context.error_buffer.pos; + --asc_context.error_buffer.size; + return asc_context.error_buffer.space; +} + +void asc_clear_error(void) { + cxBufferClear(&asc_context.error_buffer); + asc_clear_flag(&asc_context.flags, ASC_FLAG_HAS_ERROR); +} + +static void asc_event_window_resized(Uint32 id, Sint32 width, Sint32 height) { + CxIterator iter = cxListIterator(asc_context.windows); + cx_foreach(AscWindow*, w, iter) { + if (w->id == id) { + w->width = width; + w->height = height; + return; + } + } +} + +bool asc_loop_next(void) { + // dispatch SDL events + SDL_Event event; + while (SDL_PollEvent(&event)) { + switch (event.type) { + case SDL_QUIT:return false; + case SDL_WINDOWEVENT: { + if (event.window.type == SDL_WINDOWEVENT_RESIZED) + asc_event_window_resized( + event.window.windowID, + event.window.data1, + event.window.data2 + ); + break; + } + case SDL_KEYDOWN: + // TODO: remove this code and implement key press map instead + if (event.key.keysym.sym == SDLK_ESCAPE) + return false; + break; + case SDL_KEYUP: + // TODO: implement key press map + break; + } + } + + // sync the windows + CxMutIterator windows = cxListMutIterator(asc_context.windows); + cx_foreach(AscWindow*, w, windows) { + asc_window_sync(w); + } + return true; +} + +void asc_window_settings_init_defaults(AscWindowSettings* settings) { + settings->depth_size = 24; + settings->vsync = 1; + settings->width = 800; + settings->height = 600; + settings->fullscreen = 0; + settings->gl_major_version = 3; + settings->gl_minor_version = 3; + settings->title = "Ascended Window"; +} + +void asc_window_initialize(AscWindow* window, AscWindowSettings const* settings) { + Uint32 flags = SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN; + flags |= settings->fullscreen ? SDL_WINDOW_FULLSCREEN_DESKTOP : SDL_WINDOW_RESIZABLE; + + window->window = SDL_CreateWindow( + settings->title, + SDL_WINDOWPOS_CENTERED, + SDL_WINDOWPOS_CENTERED, + settings->width, + settings->height, + flags + ); + if (window->window == NULL) { + asc_error(SDL_GetError()); + return; + } + + window->id = SDL_GetWindowID(window->window); + SDL_GetWindowSize(window->window, &window->width, &window->height); + + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, settings->gl_major_version); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, settings->gl_minor_version); + SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, settings->depth_size); + SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); + window->glctx = SDL_GL_CreateContext(window->window); + if (window->glctx == NULL) { + asc_dprintf("Creating GL context failed for window %u", window->id); + } else { + glewExperimental = GL_TRUE; + GLenum err = glewInit(); + if (err == GLEW_OK) { + SDL_GL_SetSwapInterval(settings->vsync); + glEnable(GL_DEPTH_TEST); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_DEBUG_OUTPUT); + glDebugMessageCallback(asc_gl_debug_callback, NULL); + asc_dprintf("Window %u initialized", window->id); + cxListAdd(asc_context.windows, window); + return; + } else { + asc_error(glewGetErrorString(err)); + } + } + + // cleanup on error + if (window->glctx != NULL) { + SDL_GL_DeleteContext(window->glctx); + } + window->glctx = NULL; + SDL_DestroyWindow(window->window); + window->window = NULL; + window->id = 0; +} + +void asc_window_destroy_impl(AscWindow* window) { + // destory the GL context and the window + if (window->glctx != NULL) { + SDL_GL_DeleteContext(window->glctx); + } + if (window->window != NULL) { + SDL_DestroyWindow(window->window); + } + + // clean the data + asc_dprintf("Window %u and its OpenGL context destroyed.", window->id); + memset(window, 0, sizeof(AscWindow)); +} + +void asc_window_destroy(AscWindow* window) { + // find the window in the context and remove it + CxMutIterator iter = cxListMutIterator(asc_context.windows); + cx_foreach(AscWindow*, w, iter) { + if (w == window) { + asc_dprintf("Window %u removed from context.", window->id); + cxIteratorFlagRemoval(iter); + } + } + asc_window_destroy_impl(window); +} + +void asc_window_sync(AscWindow const* window) { + SDL_GL_MakeCurrent(window->window, window->glctx); + SDL_GL_SwapWindow(window->window); + glViewport(0, 0, window->width, window->height); + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); +} diff -r 000000000000 -r 593b60458157 test/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/Makefile Fri Oct 06 21:21:10 2023 +0200 @@ -0,0 +1,43 @@ +# Copyright 2023 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 + +BUILD_DIR=../build/test +LIB_ASCENSION=../build/lib/libascension.a +CFLAGS += -I../src + +all: $(BUILD_DIR)/sandbox FORCE + @echo "Sandbox demo successfully built." + +$(BUILD_DIR)/sandbox: $(BUILD_DIR)/sandbox.o $(LIB_ASCENSION) + echo "Linking executable..." + $(CC) $(LDFLAGS) -o $@ $^ + +$(BUILD_DIR)/sandbox.o: sandbox.c ../src/ascension/core.h + echo "Compiling $<" + $(CC) -o $@ $(CFLAGS) -c $< + +FORCE: diff -r 000000000000 -r 593b60458157 test/sandbox.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/sandbox.c Fri Oct 06 21:21:10 2023 +0200 @@ -0,0 +1,66 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * Copyright 2023 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 "ascension/core.h" + +#include + +static bool show_message_box_on_error(SDL_Window* window) { + if (asc_has_error()) { + SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, + "Fatal Error", + asc_get_error(), + window); + asc_clear_error(); + return true; + } else { + return false; + } +} + +int main(int argc, char** argv) { + asc_context_initialize(); + if (show_message_box_on_error(NULL)) return 1; + + AscWindowSettings settings; + asc_window_settings_init_defaults(&settings); + settings.title = "Sandbox Application"; + + AscWindow window; + asc_window_initialize(&window, &settings); + + while (asc_loop_next()) { + // quit application on any error + if (show_message_box_on_error(window.window)) break; + + + } + + asc_context_destroy(); + return 0; +} +