| #!/usr/bin/env bash |
| |
| set -e |
| |
| function show_usage { |
| echo "Usage: $0 [options] <dirs>+" |
| echo |
| echo "Generate the sdbus++ sources from a directory path." |
| echo |
| echo "Options:" |
| echo " --tool <path> - path to processing tool (default 'sdbus++')." |
| echo " --output <path> - directory to place output files (default '.')." |
| echo " --list-all - include all generated files in stdout list." |
| echo " --jobs <N> - number to run in parallel (default: $(nproc))." |
| echo " <dirs>+ - any number of subdirectories to generate." |
| echo |
| echo "The output on stdout is a list of generated files, which is intended" |
| echo "to be consumed by build systems, such as Meson." |
| echo |
| echo "This tool, by default, generates all files that are able to be" |
| echo "created by sdbus++. The output is a list of compilable sources that" |
| echo "were generated by the tool. The tool may generate outputs which are" |
| echo "not able to be compiled, such as documentation, but it does not put" |
| echo "them into stdout unless --list-all is given." |
| } |
| |
| sdbuspp="sdbus++" |
| outputdir="." |
| listall="no" |
| parallel=$(nproc || grep -c ^processor < /proc/cpuinfo) |
| |
| options="$(getopt -o ho:t:j: --long help,list-all,output:,tool:,jobs: -- "$@")" |
| eval set -- "$options" |
| |
| while true; do |
| case "$1" in |
| -h | --help) |
| show_usage |
| exit |
| ;; |
| |
| -j | --jobs) |
| shift |
| parallel="$1" |
| shift |
| ;; |
| |
| --list-all) |
| listall="yes" |
| shift |
| ;; |
| |
| -o | --output) |
| shift |
| outputdir="$1" |
| shift |
| ;; |
| |
| -t | --tool) |
| shift |
| sdbuspp="$1" |
| shift |
| ;; |
| |
| --) |
| shift |
| break |
| ;; |
| esac |
| done |
| |
| if [ $# -eq 0 ]; then |
| show_usage |
| exit 1 |
| fi |
| |
| all_jobs="" |
| |
| declare -A emitted_file_names |
| # generate_single -- make a single call to sdbus++. |
| # $1: sdbus++ TYPE |
| # $2: sdbus++ PROCESS |
| # $3: sdbus++ ITEM |
| # $4: relative output file |
| # $5: 'append-mode' if present. |
| function generate_single { |
| |
| if [ "empty" == "$1" ]; then |
| echo -n > "$outputdir/$4" |
| elif [ "" == "$5" ]; then |
| $sdbuspp "$1" "$2" "$3" > "$outputdir/$4" & |
| all_jobs="$all_jobs $!" |
| else |
| $sdbuspp "$1" "$2" "$3" >> "$outputdir/$4" & |
| all_jobs="$all_jobs $!" |
| fi |
| |
| # Emit filename as needed. |
| filename=$outputdir/$4 |
| if [ "x1" != "x${emitted_file_names[$filename]}" ]; then |
| emitted_file_names[$filename]="1" |
| |
| # Always emit generated file name for foo-cpp and foo-header. |
| # Conditionally emit for everything else depending on $listall. |
| case "$2" in |
| *-cpp | *-header) |
| echo "$filename" |
| ;; |
| |
| *) |
| if [ "yes" == "$listall" ]; then |
| echo "$filename" |
| fi |
| ;; |
| esac |
| fi |
| |
| # Ensure that no more than ${parallel} jobs are running at a time and if so |
| # wait for them to finish. |
| if [[ $(echo "$all_jobs" | wc -w) -ge $parallel ]]; then |
| waitall |
| fi |
| } |
| |
| function waitall { |
| for job in $all_jobs; do |
| wait "$job" |
| done |
| all_jobs="" |
| } |
| |
| for d in "$@"; do |
| interfaces="$(find "$d" -name '*.interface.yaml')" |
| errors="$(find "$d" -name '*.errors.yaml')" |
| |
| # Some files are created from multiple YAML sources, but we don't know |
| # which YAML sources are present. For these files, we need to first |
| # create an empty file to ensure the file does not carry old data from |
| # a previous run. |
| for y in $interfaces $errors; do |
| path="${y%.interface.yaml}" |
| path="${path%.errors.yaml}" |
| iface="${path//\//.}" |
| |
| mkdir -p "$outputdir/$path" |
| generate_single empty markdown "$iface" "$path.md" |
| done |
| |
| for i in $interfaces; do |
| path="${i%.interface.yaml}" |
| iface="${path//\//.}" |
| |
| generate_single interface server-header "$iface" "$path/server.hpp" |
| generate_single interface server-cpp "$iface" "$path/server.cpp" |
| generate_single interface client-header "$iface" "$path/client.hpp" |
| generate_single interface markdown "$iface" "$path.md" append |
| |
| done |
| waitall # finish all before continuing |
| |
| for e in $errors; do |
| path="${e%.errors.yaml}" |
| iface="${path//\//.}" |
| |
| generate_single error exception-header "$iface" "$path/error.hpp" |
| generate_single error exception-cpp "$iface" "$path/error.cpp" |
| generate_single error markdown "$iface" "$path.md" append |
| |
| done |
| waitall # finish all before continuing |
| done |