mirror of
https://github.com/ldericher/autodoc.git
synced 2025-12-06 15:43:01 +00:00
Merge branch 'develop' into feature/Pandocfile
This commit is contained in:
commit
39ed226199
11 changed files with 319 additions and 165 deletions
|
|
@ -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
|
|
||||||
|
|
@ -1,4 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# $WATCHROOT (default: ".")
|
|
||||||
g_watchroot="$(readlink -f "${1:-.}")"
|
|
||||||
|
|
@ -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}
|
|
||||||
}
|
|
||||||
|
|
@ -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
|
|
||||||
}
|
|
||||||
|
|
@ -9,11 +9,11 @@ services:
|
||||||
|
|
||||||
image: ldericher/autodoc
|
image: ldericher/autodoc
|
||||||
build:
|
build:
|
||||||
context: ./build
|
context: ./src
|
||||||
|
|
||||||
command: "bash"
|
command: "bash"
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
- "${PWD}/build/usr/local/bin/autodoc:/usr/local/bin/autodoc:ro"
|
- "${PWD}/src/usr/local/bin/autodoc:/usr/local/bin/autodoc:ro"
|
||||||
- "${PWD}/build/usr/local/lib/autodoc:/usr/local/lib/autodoc:ro"
|
- "${PWD}/src/usr/local/lib/autodoc:/usr/local/lib/autodoc:ro"
|
||||||
- "${PWD}/examples:/docs"
|
- "${PWD}/examples:/docs"
|
||||||
|
|
|
||||||
|
|
@ -6,4 +6,4 @@ RUN apt-get update && apt-get -y install \
|
||||||
|
|
||||||
COPY usr /usr
|
COPY usr /usr
|
||||||
|
|
||||||
CMD ["autodoc"]
|
CMD ["autodoc", "-bw"]
|
||||||
45
src/usr/local/bin/autodoc
Executable file
45
src/usr/local/bin/autodoc
Executable 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."
|
||||||
67
src/usr/local/lib/autodoc/globals
Normal file
67
src/usr/local/lib/autodoc/globals
Normal 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:-.}")"
|
||||||
146
src/usr/local/lib/autodoc/main
Normal file
146
src/usr/local/lib/autodoc/main
Normal 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
|
||||||
|
}
|
||||||
57
src/usr/local/lib/autodoc/plugins/make.sh
Normal file
57
src/usr/local/lib/autodoc/plugins/make.sh
Normal 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."
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue