Fri, 19 Jan 2024 20:48:26 +0100
add helptext descriptions for features
fixes #314 and fixes #315
--- a/src/main/java/de/unixwork/uwproj/Feature.java Sun Jan 07 11:05:24 2024 +0100 +++ b/src/main/java/de/unixwork/uwproj/Feature.java Fri Jan 19 20:48:26 2024 +0100 @@ -1,6 +1,8 @@ package de.unixwork.uwproj; import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; import java.util.List; @@ -11,6 +13,7 @@ private String name; private String arg; private boolean auto; + private String desc; private TargetData targetData; @@ -18,22 +21,35 @@ Feature feature = new Feature(); String name = e.getAttribute("name"); String arg = e.getAttribute("arg"); - String auto = e.getAttribute("default"); if (name.isBlank()) { throw new Exception("feature element requires name attribute"); } feature.setName(name); - feature.setAuto(Boolean.parseBoolean(auto)); if (arg.isBlank()) { feature.setArg(name); } else { feature.setArg(arg); } + feature.setAuto(Boolean.parseBoolean(e.getAttribute("default"))); feature.setTargetData(TargetData.parse(e)); project.addFeature(feature); + + // TODO: when Option also receives this feature, we might move this to TargetData.parse() + NodeList nodes = e.getChildNodes(); + for (int i = 0; i < nodes.getLength(); i++) { + Node node = nodes.item(i); + if (node.getNodeType() == Node.ELEMENT_NODE) { + Element elm = (Element) node; + String n = elm.getNodeName(); + if (n.equals("desc")) { + feature.setDesc(Util.getContent(elm)); + } + } + } + return feature; } @@ -73,6 +89,14 @@ this.arg = arg; } + public String getDesc() { + return desc; + } + + public void setDesc(String desc) { + this.desc = desc; + } + public boolean isAuto() { return auto; } @@ -88,4 +112,85 @@ public void setTargetData(TargetData targetData) { this.targetData = targetData; } + + /** + * Generates help text for the feature option. + * <p> + * If {@link #isAuto()} returns true, the option name will be --disable-${@link #getArg()}, otherwise + * it will be --enable-${@link #getArg()}, preceded by two spaces, respectively. + * <p> + * If no description is available via {@link #getDesc()}, only the option name is generated. Otherwise, + * description is added according to the following rules: + * <p> + * When the option name does not consume more than 25 characters, the description starts in the same line. + * Otherwise, a line break is added, first. The description will be placed in a block starting from column + * 27 to 80 and automatically break when necessary. The description must not contain a single word + * that is longer than 54 characters, or it will break the layout. + * + * @return a help text for terminal output + */ + public String getHelpText() { + final var builder = new StringBuilder(); + + // Compute option name + final var opt = (auto ? " --disable-" : " --enable-")+arg; + + // Add option name + builder.append(opt); + + // Stop, if there is no description + if (desc == null || desc.isBlank()) return builder.toString(); + + // Prepare the description by replacing some unwanted spaces + final var hdesc = desc.trim() + .replaceAll("\\r", "") + .replaceAll("\\n", " ") + .replaceAll("\\t", " "); + + // Declare our frame where the description shall be placed + final int startx = 26; + final int endx = 80; + + // Move to startx (break, if we already past that) + if (opt.length() >= startx) { + builder.append("\n"); + builder.append(" ".repeat(startx)); + } else { + builder.append(" ".repeat(startx-opt.length())); + } + + // Append the description keeping the layout intact + int x = startx; + for (int i = 0 ; i < hdesc.length() ;) { + // get the next word and see where we would end + int s = hdesc.indexOf(' ', i); + if (s < 0) s = hdesc.length(); + int l = s-i; + if (x + l > endx) { + // does not fit, break into next line + builder.append('\n'); + builder.append(" ".repeat(startx)); + x = startx; + } + // append the word + builder.append(hdesc, i, s); + x += l; + i += l; + // append the next spaces + while (i < hdesc.length() && hdesc.charAt(i) == ' ') { + i++; + x++; + // as long as we don't need to break, add the spaces + if (x < endx) builder.append(' '); + } + // break to new line, when spaces moved us outside the frame + if (x > endx) { + builder.append('\n'); + builder.append(" ".repeat(startx)); + x = startx; + } + } + + return builder.toString(); + } }
--- a/src/main/resources/make/configure.vm Sun Jan 07 11:05:24 2024 +0100 +++ b/src/main/resources/make/configure.vm Fri Jan 19 20:48:26 2024 +0100 @@ -93,11 +93,7 @@ #if( $features.size() > 0 ) Optional Features: #foreach( $feature in $features ) -#if( $feature.auto ) - --disable-${feature.arg} -#else - --enable-${feature.arg} -#end +${feature.helpText} #end #end @@ -645,5 +641,3 @@ 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" - -
--- a/src/main/resources/make/uwproj.xsd Sun Jan 07 11:05:24 2024 +0100 +++ b/src/main/resources/make/uwproj.xsd Fri Jan 19 20:48:26 2024 +0100 @@ -3,7 +3,7 @@ xmlns="http://unixwork.de/uwproj" targetNamespace="http://unixwork.de/uwproj" elementFormDefault="qualified" - version="0.1" + version="0.2" > <xs:element name="project" type="ProjectType"/> @@ -186,6 +186,8 @@ 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"> @@ -194,6 +196,7 @@ <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:element name="desc" type="xs:string"/> </xs:complexType> <xs:complexType name="OptionType"> @@ -278,4 +281,4 @@ </xs:annotation> <xs:restriction base="xs:string"/> </xs:simpleType> -</xs:schema> \ No newline at end of file +</xs:schema>
--- a/test/configure Sun Jan 07 11:05:24 2024 +0100 +++ b/test/configure Fri Jan 19 20:48:26 2024 +0100 @@ -534,5 +534,3 @@ 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/test/configure2 Fri Jan 19 20:48:26 2024 +0100 @@ -0,0 +1,823 @@ +#!/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 +# 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 +FEATURE_DB=auto + +# 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] + --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] + +Options: + --debug add extra compile flags for debug builds + --release add extra compile flags for release builds + --toolkit=(gtk3|cli|gtk2|wpf) + +Optional Features: + --disable-db Needlessly adds a completely useless SQLite + database. + --enable-gui + +__EOF__ +} + +# +# 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" ;; + "--toolkit="*) OPT_TOOLKIT=${ARG#--toolkit=} ;; + "--enable-db") FEATURE_DB=on ;; + "--disable-db") unset FEATURE_DB ;; + "--enable-gui") FEATURE_GUI=on ;; + "--disable-gui") unset FEATURE_GUI ;; + "-"*) 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 + +# 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" +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_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 +} + +print_check_msg() +{ + if [ -z "$1" ]; then + shift + printf "$@" + fi +} + +dependency_error_qt4() +{ + print_check_msg "$dep_checked_qt4" "checking for qt4... " + # dependency qt4 + while true + do + if which qmake-qt4 > /dev/null ; then + : + else + break + fi + print_check_msg "$dep_checked_qt4" "yes\n" + dep_checked_qt4=1 + return 1 + done + + print_check_msg "$dep_checked_qt4" "no\n" + dep_checked_qt4=1 + return 0 +} +dependency_error_curl() +{ + print_check_msg "$dep_checked_curl" "checking for curl... " + # dependency curl platform="windows" + while true + do + if notisplatform "windows"; then + break + fi + TEMP_CFLAGS="$TEMP_CFLAGS -I/mingw/include" + TEMP_LDFLAGS="$TEMP_LDFLAGS -lcurl" + print_check_msg "$dep_checked_curl" "yes\n" + dep_checked_curl=1 + return 1 + done + + # dependency curl platform="macos" + while true + do + if notisplatform "macos"; then + break + fi + if tmp_flags=`curl-config --cflags` ; then + TEMP_CFLAGS="$TEMP_CFLAGS $tmp_flags" + else + break + fi + if tmp_flags=`curl-config --ldflags` ; then + TEMP_LDFLAGS="$TEMP_LDFLAGS $tmp_flags" + else + break + fi + print_check_msg "$dep_checked_curl" "yes\n" + dep_checked_curl=1 + return 1 + done + + # dependency curl + while true + do + if [ -z "$PKG_CONFIG" ]; then + break + fi + if test_pkg_config "libcurl" "" "" "" ; then + TEMP_CFLAGS="$TEMP_CFLAGS `"$PKG_CONFIG" --cflags libcurl`" + TEMP_LDFLAGS="$TEMP_LDFLAGS `"$PKG_CONFIG" --libs libcurl`" + else + break + fi + print_check_msg "$dep_checked_curl" "yes\n" + dep_checked_curl=1 + return 1 + done + + print_check_msg "$dep_checked_curl" "no\n" + dep_checked_curl=1 + return 0 +} +dependency_error_gtk2() +{ + print_check_msg "$dep_checked_gtk2" "checking for gtk2... " + # dependency gtk2 + while true + do + if [ -z "$PKG_CONFIG" ]; then + break + fi + if test_pkg_config "gtk+-2.0" "" "" "" ; then + TEMP_CFLAGS="$TEMP_CFLAGS `"$PKG_CONFIG" --cflags gtk+-2.0`" + TEMP_LDFLAGS="$TEMP_LDFLAGS `"$PKG_CONFIG" --libs gtk+-2.0`" + else + break + fi + print_check_msg "$dep_checked_gtk2" "yes\n" + dep_checked_gtk2=1 + return 1 + done + + print_check_msg "$dep_checked_gtk2" "no\n" + dep_checked_gtk2=1 + return 0 +} +dependency_error_sqlite() +{ + print_check_msg "$dep_checked_sqlite" "checking for sqlite... " + # dependency sqlite + while true + do + if [ -z "$PKG_CONFIG" ]; then + break + fi + if test_pkg_config "sqlite3" "" "" "" ; then + TEMP_CFLAGS="$TEMP_CFLAGS `"$PKG_CONFIG" --cflags sqlite3`" + TEMP_LDFLAGS="$TEMP_LDFLAGS `"$PKG_CONFIG" --libs sqlite3`" + else + break + fi + print_check_msg "$dep_checked_sqlite" "yes\n" + dep_checked_sqlite=1 + return 1 + done + + print_check_msg "$dep_checked_sqlite" "no\n" + dep_checked_sqlite=1 + return 0 +} +dependency_error_test() +{ + print_check_msg "$dep_checked_test" "checking for test... " + # dependency test platform="bsd" + while true + do + if notisplatform "bsd"; then + break + fi + if isplatform "macos"; then + break + fi + TEMP_CFLAGS="$TEMP_CFLAGS -DBSD" + print_check_msg "$dep_checked_test" "yes\n" + dep_checked_test=1 + return 1 + done + + # dependency test + while true + do + TEMP_CFLAGS="$TEMP_CFLAGS -DTEST" + print_check_msg "$dep_checked_test" "yes\n" + dep_checked_test=1 + return 1 + done + + print_check_msg "$dep_checked_test" "no\n" + dep_checked_test=1 + return 0 +} +dependency_error_gtk3() +{ + print_check_msg "$dep_checked_gtk3" "checking for gtk3... " + # dependency gtk3 + while true + do + if [ -z "$PKG_CONFIG" ]; then + break + fi + if test_pkg_config "gtk+-5.0" "" "" "" ; then + TEMP_CFLAGS="$TEMP_CFLAGS `"$PKG_CONFIG" --cflags gtk+-5.0`" + TEMP_LDFLAGS="$TEMP_LDFLAGS `"$PKG_CONFIG" --libs gtk+-5.0`" + else + break + fi + print_check_msg "$dep_checked_gtk3" "yes\n" + dep_checked_gtk3=1 + return 1 + done + + print_check_msg "$dep_checked_gtk3" "no\n" + dep_checked_gtk3=1 + return 0 +} +dependency_error_deptest() +{ + print_check_msg "$dep_checked_deptest" "checking for deptest... " + # dependency deptest + while true + do + TEMP_CFLAGS="$TEMP_CFLAGS -DDEPTEST" + print_check_msg "$dep_checked_deptest" "yes\n" + dep_checked_deptest=1 + return 1 + done + + print_check_msg "$dep_checked_deptest" "no\n" + dep_checked_deptest=1 + return 0 +} +dependency_error_libxml2() +{ + print_check_msg "$dep_checked_libxml2" "checking for libxml2... " + # dependency libxml2 + while true + do + if [ -z "$PKG_CONFIG" ]; then + break + fi + if test_pkg_config "libxml-2.0" "2.8" "" "" ; then + TEMP_CFLAGS="$TEMP_CFLAGS `"$PKG_CONFIG" --cflags libxml-2.0`" + TEMP_LDFLAGS="$TEMP_LDFLAGS `"$PKG_CONFIG" --libs libxml-2.0`" + else + break + fi + cat >> $TEMP_DIR/make.mk << __EOF__ +# Dependency: libxml2 +xml = libxml2 + +__EOF__ + print_check_msg "$dep_checked_libxml2" "yes\n" + dep_checked_libxml2=1 + return 1 + done + + print_check_msg "$dep_checked_libxml2" "no\n" + dep_checked_libxml2=1 + 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 + + cat >> "$TEMP_DIR/make.mk" << __EOF__ +MVAR = 123 +MVAR += 123 + +__EOF__ + 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 +# +checkopt_toolkit_gtk3() +{ + VERR=0 + if dependency_error_gtk3 ; then + VERR=1 + fi + if [ $VERR -ne 0 ]; then + return 1 + fi + TEMP_CFLAGS="$TEMP_CFLAGS -Da=b" + TEMP_CXXFLAGS="$TEMP_CXXFLAGS -Da=b" + cat >> "$TEMP_DIR/make.mk" << __EOF__ +UIOBJ += graphics_cairo.o + +__EOF__ + return 0 +} +checkopt_toolkit_cli() +{ + VERR=0 + if dependency_error_curl ; then + VERR=1 + fi + if dependency_error_test ; then + VERR=1 + fi + if [ $VERR -ne 0 ]; then + return 1 + fi + return 0 +} +checkopt_toolkit_gtk2() +{ + VERR=0 + if dependency_error_gtk2 ; then + VERR=1 + fi + if [ $VERR -ne 0 ]; then + return 1 + fi + return 0 +} +checkopt_toolkit_wpf() +{ + VERR=0 + if dependency_error_test ; then + VERR=1 + fi + if [ $VERR -ne 0 ]; then + return 1 + fi + return 0 +} + +# +# TARGETS +# + +echo >> "$TEMP_DIR/flags.mk" +echo "configuring target: dav" +echo "# flags for target dav" >> "$TEMP_DIR/flags.mk" +TEMP_CFLAGS= +TEMP_CXXFLAGS= +TEMP_LDFLAGS= + +if dependency_error_curl; then + DEPENDENCIES_FAILED="$DEPENDENCIES_FAILED curl " + ERROR=1 +fi +if dependency_error_libxml2; then + DEPENDENCIES_FAILED="$DEPENDENCIES_FAILED libxml2 " + ERROR=1 +fi +if dependency_error_test; then + DEPENDENCIES_FAILED="$DEPENDENCIES_FAILED test " + ERROR=1 +fi + +# Features +if [ -n "$FEATURE_DB" ]; then + # check dependency + if dependency_error_sqlite ; then + # "auto" features can fail and are just disabled in this case + if [ "$FEATURE_DB" = "auto" ]; then + DISABLE_FEATURE_DB=1 + else + DEPENDENCIES_FAILED="$DEPENDENCIES_FAILED sqlite " + ERROR=1 + fi + fi + if [ -n "$DISABLE_FEATURE_DB" ]; then + unset FEATURE_DB + fi +fi +if [ -n "$FEATURE_GUI" ]; then + # check dependency + if dependency_error_gtk3 ; then + # "auto" features can fail and are just disabled in this case + if [ "$FEATURE_GUI" = "auto" ]; then + DISABLE_FEATURE_GUI=1 + else + DEPENDENCIES_FAILED="$DEPENDENCIES_FAILED gtk3 " + ERROR=1 + fi + fi + if [ -n "$DISABLE_FEATURE_GUI" ]; then + unset FEATURE_GUI + fi +fi + +# Option: --toolkit +if [ -z "$OPT_TOOLKIT" ]; then + echo "auto-detecting option 'toolkit'" + SAVED_ERROR="$ERROR" + SAVED_DEPENDENCIES_FAILED="$DEPENDENCIES_FAILED" + ERROR=1 + while true + do + if isplatform "windows"; then + if checkopt_toolkit_wpf ; then + echo " toolkit: wpf" >> "$TEMP_DIR/options" + ERROR=0 + break + fi + fi + if checkopt_toolkit_gtk3 ; then + echo " toolkit: gtk3" >> "$TEMP_DIR/options" + ERROR=0 + break + fi + if checkopt_toolkit_gtk2 ; then + echo " toolkit: gtk2" >> "$TEMP_DIR/options" + ERROR=0 + break + fi + break + done + if [ $ERROR -ne 0 ]; then + SAVED_ERROR=1 + SAVED_DEPENDENCIES_FAILED="option 'toolkit' $SAVED_DEPENDENCIES_FAILED" + fi + ERROR="$SAVED_ERROR" + DEPENDENCIES_FAILED="$SAVED_DEPENDENCIES_FAILED" +else + echo "checking option toolkit = $OPT_TOOLKIT" + if false; then + false + elif [ "$OPT_TOOLKIT" = "gtk3" ]; then + echo " toolkit: $OPT_TOOLKIT" >> $TEMP_DIR/options + if checkopt_toolkit_gtk3 ; then + : + else + ERROR=1 + DEPENDENCIES_FAILED="option 'toolkit' $DEPENDENCIES_FAILED" + fi + elif [ "$OPT_TOOLKIT" = "cli" ]; then + echo " toolkit: $OPT_TOOLKIT" >> $TEMP_DIR/options + if checkopt_toolkit_cli ; then + : + else + ERROR=1 + DEPENDENCIES_FAILED="option 'toolkit' $DEPENDENCIES_FAILED" + fi + elif [ "$OPT_TOOLKIT" = "gtk2" ]; then + echo " toolkit: $OPT_TOOLKIT" >> $TEMP_DIR/options + if checkopt_toolkit_gtk2 ; then + : + else + ERROR=1 + DEPENDENCIES_FAILED="option 'toolkit' $DEPENDENCIES_FAILED" + fi + elif [ "$OPT_TOOLKIT" = "wpf" ]; then + echo " toolkit: $OPT_TOOLKIT" >> $TEMP_DIR/options + if checkopt_toolkit_wpf ; then + : + else + ERROR=1 + DEPENDENCIES_FAILED="option 'toolkit' $DEPENDENCIES_FAILED" + fi + fi +fi + +if [ -n "${TEMP_CFLAGS}" ] && [ -n "$lang_c" ]; then + echo "DAV_CFLAGS += $TEMP_CFLAGS" >> "$TEMP_DIR/flags.mk" +fi +if [ -n "${TEMP_CXXFLAGS}" ] && [ -n "$lang_cpp" ]; then + echo "DAV_CXXFLAGS += $TEMP_CXXFLAGS" >> "$TEMP_DIR/flags.mk" +fi +if [ "$BUILD_TYPE" = "debug" ]; then + if [ -n "$lang_c" ]; then + echo 'DAV_CFLAGS += ${DEBUG_CC_FLAGS}' >> "$TEMP_DIR/flags.mk" + fi + if [ -n "$lang_cpp" ]; then + echo 'DAV_CXXFLAGS += ${DEBUG_CXX_FLAGS}' >> "$TEMP_DIR/flags.mk" + fi +fi +if [ "$BUILD_TYPE" = "release" ]; then + if [ -n "$lang_c" ]; then + echo 'DAV_CFLAGS += ${RELEASE_CC_FLAGS}' >> "$TEMP_DIR/flags.mk" + fi + if [ -n "$lang_cpp" ]; then + echo 'DAV_CXXFLAGS += ${RELEASE_CXX_FLAGS}' >> "$TEMP_DIR/flags.mk" + fi +fi +if [ -n "${TEMP_LDFLAGS}" ]; then + echo "DAV_LDFLAGS += $TEMP_LDFLAGS" >> "$TEMP_DIR/flags.mk" +fi + +echo >> "$TEMP_DIR/flags.mk" +echo "configuring global target" +echo "# flags for unnamed target" >> "$TEMP_DIR/flags.mk" +TEMP_CFLAGS= +TEMP_CXXFLAGS= +TEMP_LDFLAGS= + +if dependency_error_deptest; then + DEPENDENCIES_FAILED="$DEPENDENCIES_FAILED deptest " + ERROR=1 +fi + +# 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 "Options:" +cat "$TEMP_DIR/options" +echo "Features:" +if [ -n "$FEATURE_DB" ]; then +echo " db: on" +else +echo " db: off" +fi +if [ -n "$FEATURE_GUI" ]; then +echo " gui: on" +else +echo " gui: off" +fi +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"
--- a/test/make/configure.vm Sun Jan 07 11:05:24 2024 +0100 +++ b/test/make/configure.vm Fri Jan 19 20:48:26 2024 +0100 @@ -93,11 +93,7 @@ #if( $features.size() > 0 ) Optional Features: #foreach( $feature in $features ) -#if( $feature.auto ) - --disable-${feature.arg} -#else - --enable-${feature.arg} -#end +${feature.helpText} #end #end @@ -645,5 +641,3 @@ 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" - -
--- a/test/make/project2.xml Sun Jan 07 11:05:24 2024 +0100 +++ b/test/make/project2.xml Fri Jan 19 20:48:26 2024 +0100 @@ -46,6 +46,10 @@ <target name="dav"> <feature name="db" default="true"> + <desc> + Needlessly adds a completely + useless SQLite database. + </desc> <dependencies>sqlite</dependencies> <define name="DATABASE"/> </feature>
--- a/test/make/uwproj.xsd Sun Jan 07 11:05:24 2024 +0100 +++ b/test/make/uwproj.xsd Fri Jan 19 20:48:26 2024 +0100 @@ -3,7 +3,7 @@ xmlns="http://unixwork.de/uwproj" targetNamespace="http://unixwork.de/uwproj" elementFormDefault="qualified" - version="0.1" + version="0.2" > <xs:element name="project" type="ProjectType"/> @@ -186,6 +186,8 @@ 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"> @@ -194,6 +196,7 @@ <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:element name="desc" type="xs:string"/> </xs:complexType> <xs:complexType name="OptionType"> @@ -278,4 +281,4 @@ </xs:annotation> <xs:restriction base="xs:string"/> </xs:simpleType> -</xs:schema> \ No newline at end of file +</xs:schema>