Merge branch 'develop' into feature/Pandocfile

This commit is contained in:
Jörn-Michael Miehe 2020-02-18 10:50:22 +01:00
commit 39ed226199
11 changed files with 319 additions and 165 deletions

View file

@ -1,40 +0,0 @@
#!/bin/bash
#
# hard globals
#
g_bin="$(readlink -f "$(which "$0")")"
g_lib=${g_bin/"bin"/"lib"}
declare -a g_build_systems
declare -A g_build_systems_glob
#
# load base program
#
source "${g_lib}/globals"
source "${g_lib}/logging"
source "${g_lib}/handle_inotify"
for plugin in "${g_lib}/plugins/"*".sh"; do
source "${plugin}"
done
#
# MAIN
#
echo "Booting '${g_bin}' in '${g_watchroot}'."
# setup inotify:
# -mrq monitor, recursive, quiet
# -e events
# --format %e eventlist csv, %w workdir, %f filename
inotifywait -mrq \
-e create -e delete -e moved_to -e close_write \
--format '%e %w%f' \
"${g_watchroot}" | \
\
while read NOTIFICATION; do
do_handle ${NOTIFICATION}
done

View file

@ -1,4 +0,0 @@
#!/bin/bash
# $WATCHROOT (default: ".")
g_watchroot="$(readlink -f "${1:-.}")"

View file

@ -1,72 +0,0 @@
#!/bin/bash
# process an inotify event
do_handle() { # $FLAGS $OBJECT
# extract params
local flags="$1"
shift 1
local dir="$(dirname "$*")"
local object="$(basename "$*")"
if [[ "${flags}" =~ "ISDIR" ]]; then
# object refers to directory
local dir="${dir}/${object}"
local object="."
fi
# start using toolchain
logline_append "'${object}': '${flags}' in '${dir}'."
do_compile "${dir}" "${object}"
logline_flush
}
# compile an OBJECT using build instructions found in DIRectory
do_compile() { # $DIR $OBJECT $DONE
# extract params
local dir="$1"
local object="$2"
local done="${3:-0}"
# build systems
for build_system in ${g_build_systems[@]}; do
do_build_system "${dir}" "${object}" "${build_system}" \
&& local done="1"
done
# never leave $g_watchroot
if [ "${dir}" != "${g_watchroot}" ]; then
# search parent dir for more build instructions
do_compile "$(dirname "${dir}")" "${object}" "${done}"
elif [ "${done}" == "0" ]; then
# hit $g_watchroot
logline_append "Not a source file."
fi
}
# use given BUILD_SYSTEM to process an OBJECT from a DIRectory
do_build_system() { # $DIR $OBJECT $BUILD_SYSTEM
# extract params
local dir="$1"
local object="$2"
local build_system="$3"
# not done yet
local result=1
# get glob pattern for plugin
for glob in ${g_build_systems_glob[${build_system}]}; do
# match glob in directory
for file in "${dir}"/${glob}; do
# check file readability
if [ -r "${file}" ]; then
# actually call into build system
logline_append "Found '${file}':"
do_${build_system} "${dir}" "${object}" "$(basename "${file}")" \
&& local result=0
fi
done
done
return ${result}
}

View file

@ -1,45 +0,0 @@
#!/bin/bash
# plugin name
g_build_systems+=(make)
# build instruction file globs for this plugin
g_build_systems_glob[make]="Makefile *.mk"
# compile using bare make command
do_make() { # $DIR $OBJECT $MAKEFILE
# extract params
local dir="$1"
local object="$2"
local makefile="$3"
# check Makefile 'source pattern'
local srcpat="$(grep -E "^#%SRCPAT%" "${dir}/${makefile}" | tail -n 1 | sed -r "s/^#%SRCPAT%\s+//")"
if [ -z "${srcpat}" ]; then
logline_append "Empty source pattern, check '#%SRCPAT%' annotation!"
return 1
elif [[ "${object}" =~ ${srcpat} ]]; then
# check for autodoc target
local target="$(grep -E "^autodoc:" "${dir}/${makefile}" | sed -r "s/:.*$//")"
if [ -z "${target}" ]; then
logline_append "Running 'make'!"
else
logline_append "Making '${target}'!"
fi
# actually run "make" and save (truncated) output
local makelog="$(make --no-print-directory -C "${dir}" -f "${makefile}" -j ${target})"
logline_append "$(echo "${makelog}" | head -n 10 | sed 's/$/;/g' | tr '\n' ' ' | sed 's/ *$//')"
logline_append "Done."
else
logline_append "SRCPAT '${srcpat}' mismatch."
return 1
fi
return 0
}

View file

@ -9,11 +9,11 @@ services:
image: ldericher/autodoc
build:
context: ./build
context: ./src
command: "bash"
volumes:
- "${PWD}/build/usr/local/bin/autodoc:/usr/local/bin/autodoc:ro"
- "${PWD}/build/usr/local/lib/autodoc:/usr/local/lib/autodoc:ro"
- "${PWD}/src/usr/local/bin/autodoc:/usr/local/bin/autodoc:ro"
- "${PWD}/src/usr/local/lib/autodoc:/usr/local/lib/autodoc:ro"
- "${PWD}/examples:/docs"

View file

@ -6,4 +6,4 @@ RUN apt-get update && apt-get -y install \
COPY usr /usr
CMD ["autodoc"]
CMD ["autodoc", "-bw"]

45
src/usr/local/bin/autodoc Executable file
View file

@ -0,0 +1,45 @@
#!/bin/bash
#
# hard globals
#
g_bin="$(readlink -f "$(which "$0")")"
g_lib=${g_bin/"bin"/"lib"}
#
# load base program
#
source "${g_lib}/globals"
source "${g_lib}/logging"
source "${g_lib}/main"
for plugin in "${g_lib}/plugins/"*".sh"; do
source "${plugin}"
done
#
# MAIN
#
# show debug info
if [ ${g_verbose} -eq 1 ]; then
logline_append "Variables:"
logline_append "build:${g_build}"
logline_append "watch:${g_watch}"
logline_append "root:${g_root}"
logline_flush
fi
if [ ${g_build} -eq 1 ]; then
echo "Building everything in '${g_root}'."
do_build_all
fi
if [ ${g_watch} -eq 1 ]; then
echo "Watching '${g_root}'."
do_build_watch
fi
echo "Done."

View file

@ -0,0 +1,67 @@
#!/bin/bash
# array of available build systems
declare -a g_build_systems
# map of file globs for build systems
declare -A g_build_systems_glob
# map of annotation patterns for build systems
declare -A g_build_systems_annotations
# simple help page
do_show_help() {
echo "Usage: ${0} [-h?bwv] [-r ROOT] [ROOT]"
echo
echo "Options:"
echo " -h, -? Show this help and exit"
echo " -b Build ROOT directory on startup"
echo " -w Keep watching ROOT directory for changes"
echo " -v Verbose output"
echo " -r ROOT Set ROOT directory"
echo
echo "ROOT directory can be set via '-r' argument or positionally."
echo "If ROOT directory is undefined, it defaults to the current working directory."
exit 0
}
# reset in case getopts has been used previously in the shell
OPTIND=1
# initialize variables
g_build=0
g_watch=0
g_root=""
while getopts "h?bwvr:" opt; do
case "$opt" in
h|\?)
do_show_help
;;
b)
g_build=1
;;
w)
g_watch=1
;;
v)
g_verbose=1
;;
r)
g_root="${OPTARG}"
;;
esac
done
# default to help
[ ${g_build} -eq 0 ] && [ ${g_watch} -eq 0 ] && [ ${g_verbose} -eq 0 ] && do_show_help
# shift off getopts parsed options
shift $((OPTIND-1))
[ "${1:-}" = "--" ] && shift
# if g_root undefined by getopt,
[ -z "${g_root:-}" ] && g_root="$1"
# get actual $ROOT directory (default: ".")
g_root="$(readlink -f "${g_root:-.}")"

View file

@ -0,0 +1,146 @@
#!/bin/bash
# process an inotify event
do_handle_inotify() { # $FLAGS $OBJECT
# extract params
local flags="$1"
shift 1
local dir="$(dirname "$*")"
local object="$(basename "$*")"
if [[ "${flags}" =~ "ISDIR" ]]; then
# object refers to directory
local dir="${dir}/${object}"
local object="."
fi
# start using toolchain
logline_append "'${object}': '${flags}' in '${dir}'."
do_compile "${dir}" "${object}"
logline_flush
}
# compile an OBJECT using build instructions found in DIRectory
do_compile() { # $DIR $OBJECT $DONE
# extract params
local dir="$1"
local object="$2"
local done="${3:-0}"
# build systems
for build_system in ${g_build_systems[@]}; do
do_build_system "${dir}" "${build_system}" "${object}" \
&& local done="1"
done
# never leave $g_root
if [ "${dir}" != "${g_root}" ]; then
# search parent dir for more build instructions
do_compile "$(dirname "${dir}")" "${object}" "${done}"
elif [ "${done}" == "0" ]; then
# hit $g_root
logline_append "Not a source file."
fi
}
# check if defined source pattern matches OBJECT
do_check_srcpat() { # $DIR $BUILD_DESC $ANNOTATION $OBJECT
# extract params
local dir="$1"
local build_desc="$2"
local annotation="$3"
local object="$4"
# check 'source pattern'
local srcpat="$(grep -E "^${annotation}" "${dir}/${build_desc}" | tail -n 1 | sed -r "s/^${annotation}\s+//")"
if [ -z "${srcpat}" ]; then
# empty srcpat => fail
logline_append "Empty source pattern, check for '${annotation}' annotation!"
return 1
elif [ -z "${object}" ]; then
# empty object = "no specific object" => success
return 0
elif [[ "${object}" =~ ${srcpat} ]]; then
# nonempty object matches srcpat => success
return 0
else
# nonempty object does not match srcpat => fail
logline_append "SRCPAT '${srcpat}' mismatch."
return 1
fi
}
# use given BUILD_SYSTEM to process an OBJECT from a DIRectory
do_build_system() { # $DIR $BUILD_SYSTEM $OBJECT
# extract params
local dir="$1"
local build_system="$2"
local object="$3"
# not done yet
local result=1
# get glob patterns for plugin
for glob in ${g_build_systems_glob[${build_system}]}; do
# match each glob in directory
for file in "${dir}"/${glob}; do
# check file readability
if [ -r "${file}" ]; then
# actually call into build system
logline_append "Found '${file}':"
local file="$(basename "${file}")"
do_${build_system} "${dir}" "${file}" "${object}" \
&& local result=0
fi
done
done
return ${result}
}
# force build using all systems
do_build_all() { #
# build systems
for build_system in ${g_build_systems[@]}; do
echo "Build system '${build_system}'."
for glob in ${g_build_systems_glob[${build_system}]}; do
# match each glob recursively
find "${g_root}" -iname "${glob}" | \
while read file; do
if [ -r "${file}" ]; then
# force call into build system
logline_append "Found '${file}':"
local dir="$(dirname "${file}")"
local file="$(basename "${file}")"
do_${build_system}_all "${dir}" "$(basename "${file}")"
logline_flush
fi
done
done
done
}
do_build_watch() { #
# setup inotify:
# -mrq monitor, recursive, quiet
# -e events
# --format %e eventlist csv, %w workdir, %f filename
inotifywait -mrq \
-e create -e delete -e moved_to -e close_write \
--format '%e %w%f' \
"${g_root}" | \
\
while read NOTIFICATION; do
do_handle_inotify ${NOTIFICATION}
done
}

View file

@ -0,0 +1,57 @@
#!/bin/bash
# plugin name
g_build_systems+=(make)
# build instruction file globs for this plugin
g_build_systems_glob[make]="Makefile *.mk"
# srcpat annotation prefix for this plugin
g_build_systems_annotations[make]='#%SRCPAT%'
# try to compile file OBJECT
do_make() { # $DIR $OBJECT $MAKEFILE
# extract params
local dir="$1"
local makefile="$2"
local object="$3"
# only run if "object" is source file
if do_check_srcpat "${dir}" "${makefile}" "${g_build_systems_annotations[make]}" "${object}"; then
do_run_make "${dir}" "${makefile}"
fi
}
# try running make for MAKEFILE inside DIRectory
do_make_all() { # $DIR $MAKEFILE
# extract params
local dir="$1"
local makefile="$2"
# only run if "makefile" is relevant for autodoc
if do_check_srcpat "${dir}" "${makefile}" "${g_build_systems_annotations[make]}" ""; then
do_run_make "${dir}" "${makefile}"
fi
}
# actually run GNU Make with MAKEFILE inside DIRectory
do_run_make() { # $DIR $MAKEFILE
# extract params
local dir="$1"
local makefile="$2"
# check for autodoc target
local target="$(grep -E "^autodoc:" "${dir}/${makefile}" | sed -r "s/:.*$//")"
if [ -z "${target}" ]; then
logline_append "Running 'make'!"
else
logline_append "Making '${target}'!"
fi
# actually run "make" and save (truncated) output
local makelog="$(make --no-print-directory -C "${dir}" -f "${makefile}" -j ${target})"
logline_append "$(echo "${makelog}" | head -n 10 | sed 's/$/;/g' | tr '\n' ' ' | sed 's/ *$//')"
logline_append "Done."
}