1847a0c37SPatrick Williams#!/usr/bin/env bash 2847a0c37SPatrick Williams 3847a0c37SPatrick Williamsset -e 4847a0c37SPatrick Williams 5a4c9edc1SPatrick Williams# Locale can change behavior of utilities like 'sort' but we want the output 6a4c9edc1SPatrick Williams# to be stable on all machines. Force the locale to 'C' for consistency. 7a4c9edc1SPatrick Williamsexport LC_ALL=C 8a4c9edc1SPatrick Williams 9018b8ff1SPatrick Williamsfunction show_usage() { 10847a0c37SPatrick Williams cat \ 11847a0c37SPatrick Williams << EOF 12847a0c37SPatrick WilliamsUsage: $(basename "$0") [options] <command-args>* 13847a0c37SPatrick Williams 14847a0c37SPatrick WilliamsGenerate meson.build files from a directory tree containing YAML files and 15847a0c37SPatrick Williamsfacilitate building the sdbus++ sources. 16847a0c37SPatrick Williams 17847a0c37SPatrick WilliamsOptions: 18847a0c37SPatrick Williams --help - Display this message 19847a0c37SPatrick Williams --command <cmd> - Command mode to execute (default 'meson'). 20847a0c37SPatrick Williams --directory <path> - Root directory of the YAML source (default '.'). 21847a0c37SPatrick Williams --output <path> - Root directory of the output (default '.'). 22847a0c37SPatrick Williams --tool <path> - Path to the processing tool (default 'sdbus++'). 23847a0c37SPatrick Williams --version - Display this tool's version string. 24847a0c37SPatrick Williams 25847a0c37SPatrick WilliamsCommands: 26847a0c37SPatrick Williams meson - Generate a tree of meson.build files corresponding 27847a0c37SPatrick Williams to the source YAML files. 28847a0c37SPatrick Williams cpp <intf> - Generate the source files from a YAML interface. 29847a0c37SPatrick Williams markdown <intf> - Generate the markdown files from a YAML interface. 30847a0c37SPatrick Williams version - Display this tool's version string. 31847a0c37SPatrick Williams 32847a0c37SPatrick WilliamsEOF 33847a0c37SPatrick Williams} 34847a0c37SPatrick Williams 35847a0c37SPatrick Williams## The version is somewhat arbitrary but is used to create a warning message 36847a0c37SPatrick Williams## if a repository contains old copies of the generated meson.build files and 37847a0c37SPatrick Williams## needs an update. We should increment the version number whenever the 38847a0c37SPatrick Williams## resulting meson.build would change. 39*0ac157a0SPatrick Williamstool_version="sdbus++-gen-meson version 9" 40018b8ff1SPatrick Williamsfunction show_version() { 41d77548a1SPatrick Williams echo "${tool_version}" 42847a0c37SPatrick Williams} 43847a0c37SPatrick Williams 44847a0c37SPatrick Williams# Set up defaults. 45847a0c37SPatrick Williamssdbuspp="sdbus++" 46847a0c37SPatrick Williamsoutputdir="." 47847a0c37SPatrick Williamscmd="meson" 48847a0c37SPatrick Williamsrootdir="." 49847a0c37SPatrick Williams 50847a0c37SPatrick Williams# Parse options. 51847a0c37SPatrick Williamsoptions="$(getopt -o hc:d:o:t:v --long help,command:,directory:,output:,tool:,version -- "$@")" 52d77548a1SPatrick Williamseval set -- "${options}" 53847a0c37SPatrick Williams 549ede18b4SPatrick Williamswhile true; do 55847a0c37SPatrick Williams case "$1" in 56847a0c37SPatrick Williams -h | --help) 57847a0c37SPatrick Williams show_usage 58847a0c37SPatrick Williams exit 59847a0c37SPatrick Williams ;; 60847a0c37SPatrick Williams 61847a0c37SPatrick Williams -c | --command) 62847a0c37SPatrick Williams shift 63847a0c37SPatrick Williams cmd="$1" 64847a0c37SPatrick Williams shift 65847a0c37SPatrick Williams ;; 66847a0c37SPatrick Williams 67847a0c37SPatrick Williams -d | --directory) 68847a0c37SPatrick Williams shift 69847a0c37SPatrick Williams rootdir="$1" 70847a0c37SPatrick Williams shift 71847a0c37SPatrick Williams ;; 72847a0c37SPatrick Williams 73847a0c37SPatrick Williams -o | --output) 74847a0c37SPatrick Williams shift 75847a0c37SPatrick Williams outputdir="$1" 76847a0c37SPatrick Williams shift 77847a0c37SPatrick Williams ;; 78847a0c37SPatrick Williams 79847a0c37SPatrick Williams -t | --tool) 80847a0c37SPatrick Williams shift 81847a0c37SPatrick Williams sdbuspp="$1" 82847a0c37SPatrick Williams shift 83847a0c37SPatrick Williams ;; 84847a0c37SPatrick Williams 85847a0c37SPatrick Williams -v | --version) 86847a0c37SPatrick Williams show_version 87847a0c37SPatrick Williams exit 88847a0c37SPatrick Williams ;; 89847a0c37SPatrick Williams 90847a0c37SPatrick Williams --) 91847a0c37SPatrick Williams shift 92847a0c37SPatrick Williams break 93847a0c37SPatrick Williams ;; 94d77548a1SPatrick Williams 95d77548a1SPatrick Williams *) 96d77548a1SPatrick Williams echo "Invalid argument $1" 97d77548a1SPatrick Williams exit 1 98d77548a1SPatrick Williams ;; 99847a0c37SPatrick Williams esac 100847a0c37SPatrick Williamsdone 101847a0c37SPatrick Williams 102847a0c37SPatrick Williams## Create an initially empty meson.build file. 103847a0c37SPatrick Williams## $1 - path to create meson.build at. 104018b8ff1SPatrick Williamsfunction meson_empty_file() { 105847a0c37SPatrick Williams mkdir -p "$1" 106847a0c37SPatrick Williams echo "# Generated file; do not modify." > "$1/meson.build" 107847a0c37SPatrick Williams} 108847a0c37SPatrick Williams 109847a0c37SPatrick Williams## Create the root-level meson.build 110847a0c37SPatrick Williams## 111847a0c37SPatrick Williams## Inserts rules to run the available version of this tool to ensure the 112847a0c37SPatrick Williams## version has not changed. 113018b8ff1SPatrick Williamsfunction meson_create_root() { 114d77548a1SPatrick Williams meson_empty_file "${outputdir}" 115847a0c37SPatrick Williams 116d77548a1SPatrick Williams cat >> "${outputdir}/meson.build" \ 117847a0c37SPatrick Williams << EOF 118847a0c37SPatrick Williamssdbuspp_gen_meson_ver = run_command( 119847a0c37SPatrick Williams sdbuspp_gen_meson_prog, 120847a0c37SPatrick Williams '--version', 12160a94305SEd Tanous check: true, 122847a0c37SPatrick Williams).stdout().strip().split('\n')[0] 123847a0c37SPatrick Williams 124d77548a1SPatrick Williamsif sdbuspp_gen_meson_ver != '${tool_version}' 125847a0c37SPatrick Williams warning('Generated meson files from wrong version of sdbus++-gen-meson.') 126847a0c37SPatrick Williams warning( 127d77548a1SPatrick Williams 'Expected "${tool_version}", got:', 128847a0c37SPatrick Williams sdbuspp_gen_meson_ver 129847a0c37SPatrick Williams ) 130847a0c37SPatrick Williamsendif 131847a0c37SPatrick Williams 132847a0c37SPatrick WilliamsEOF 133847a0c37SPatrick Williams} 134847a0c37SPatrick Williams 135847a0c37SPatrick Williams## hash-tables to store: 136847a0c37SPatrick Williams## meson_paths - list of subdirectory paths for which an empty meson.build 137847a0c37SPatrick Williams## has already been created. 138847a0c37SPatrick Williams## interfaces - list of interface paths which a YAML has been found and 139847a0c37SPatrick Williams## which YAML types (interface, errors, etc.). 140847a0c37SPatrick Williamsdeclare -A meson_paths 141847a0c37SPatrick Williamsdeclare -A interfaces 142847a0c37SPatrick Williams 143847a0c37SPatrick Williams## Ensure the meson.build files to a path have been created. 144847a0c37SPatrick Williams## $1 - The path requiring to be created. 145018b8ff1SPatrick Williamsfunction meson_create_path() { 146847a0c37SPatrick Williams 147d77548a1SPatrick Williams meson_path="${outputdir}" 148847a0c37SPatrick Williams prev_meson_path="" 149847a0c37SPatrick Williams 150847a0c37SPatrick Williams # Split the path into segments. 1519ede18b4SPatrick Williams for part in $(echo "$1" | tr '/' '\n'); do 152d77548a1SPatrick Williams prev_meson_path="${meson_path}" 153d77548a1SPatrick Williams meson_path="${meson_path}/${part}" 154847a0c37SPatrick Williams 155847a0c37SPatrick Williams # Create the meson.build for this segment if it doesn't already exist. 156d77548a1SPatrick Williams if [[ "" == "${meson_paths[${meson_path}]}" ]]; then 157d77548a1SPatrick Williams meson_paths["${meson_path}"]="1" 158d77548a1SPatrick Williams meson_empty_file "${meson_path}" 159847a0c37SPatrick Williams 160847a0c37SPatrick Williams # Add the 'subdir' link into the parent's meson.build. 161847a0c37SPatrick Williams # We need to skip adding the links into the 'root' meson.build 162847a0c37SPatrick Williams # because most repositories want to selectively add TLDs based 163847a0c37SPatrick Williams # on config flags. Let them figure out their own logic for that. 164d77548a1SPatrick Williams if [[ ${outputdir} != "${prev_meson_path}" ]]; then 165d77548a1SPatrick Williams echo "subdir('${part}')" >> "${prev_meson_path}/meson.build" 166847a0c37SPatrick Williams fi 167847a0c37SPatrick Williams fi 168847a0c37SPatrick Williams done 169847a0c37SPatrick Williams} 170847a0c37SPatrick Williams 171847a0c37SPatrick Williams## Generate the meson target for the source files (.cpp/.hpp) from a YAML 172847a0c37SPatrick Williams## interface. 173847a0c37SPatrick Williams## 174847a0c37SPatrick Williams## $1 - The interface to generate a target for. 175018b8ff1SPatrick Williamsfunction meson_cpp_target() { 176d77548a1SPatrick Williams mesondir="${outputdir}/$1" 177d77548a1SPatrick Williams yamldir="$(realpath --relative-to="${mesondir}" "${rootdir}")" 178847a0c37SPatrick Williams 179847a0c37SPatrick Williams # Determine the source and output files based on the YAMLs present. 180847a0c37SPatrick Williams sources="" 181847a0c37SPatrick Williams outputs="" 1829ede18b4SPatrick Williams for s in ${interfaces[$1]}; do 183*0ac157a0SPatrick Williams sources="${sources}'${yamldir}/$1.${s}', " 184847a0c37SPatrick Williams 185d77548a1SPatrick Williams case "${s}" in 186847a0c37SPatrick Williams errors.yaml) 187847a0c37SPatrick Williams outputs="${outputs}'error.cpp', 'error.hpp', " 188847a0c37SPatrick Williams ;; 189847a0c37SPatrick Williams 1900336a2fcSPatrick Williams events.yaml) 1910336a2fcSPatrick Williams outputs="${outputs}'event.cpp', 'event.hpp', " 1920336a2fcSPatrick Williams ;; 1930336a2fcSPatrick Williams 194847a0c37SPatrick Williams interface.yaml) 1951caa5e8aSPatrick Williams outputs="${outputs}'common.hpp', " 196847a0c37SPatrick Williams outputs="${outputs}'server.cpp', 'server.hpp', " 1976403d56fSPatrick Williams outputs="${outputs}'aserver.hpp', " 198847a0c37SPatrick Williams outputs="${outputs}'client.hpp', " 199847a0c37SPatrick Williams ;; 200d77548a1SPatrick Williams 201d77548a1SPatrick Williams *) 202d77548a1SPatrick Williams echo "Unknown interface type: ${s}" 203d77548a1SPatrick Williams exit 1 204d77548a1SPatrick Williams ;; 205847a0c37SPatrick Williams esac 206847a0c37SPatrick Williams done 207847a0c37SPatrick Williams 208847a0c37SPatrick Williams # Create the target to generate the 'outputs'. 209d77548a1SPatrick Williams cat >> "${mesondir}/meson.build" \ 210847a0c37SPatrick Williams << EOF 211847a0c37SPatrick Williamsgenerated_sources += custom_target( 212847a0c37SPatrick Williams '$1__cpp'.underscorify(), 213d77548a1SPatrick Williams input: [ ${sources} ], 214d77548a1SPatrick Williams output: [ ${outputs} ], 215293c8a26SWilliam A. Kennington III depend_files: sdbusplusplus_depfiles, 216847a0c37SPatrick Williams command: [ 217847a0c37SPatrick Williams sdbuspp_gen_meson_prog, '--command', 'cpp', 218847a0c37SPatrick Williams '--output', meson.current_build_dir(), 219847a0c37SPatrick Williams '--tool', sdbusplusplus_prog, 220d77548a1SPatrick Williams '--directory', meson.current_source_dir() / '${yamldir}', 221847a0c37SPatrick Williams '$1', 222847a0c37SPatrick Williams ], 223847a0c37SPatrick Williams) 224847a0c37SPatrick Williams 225847a0c37SPatrick WilliamsEOF 226847a0c37SPatrick Williams} 227847a0c37SPatrick Williams 228847a0c37SPatrick Williams## Generate the meson target for the markdown files from a YAML interface. 229847a0c37SPatrick Williams## $1 - The interface to generate a target for. 230018b8ff1SPatrick Williamsfunction meson_md_target() { 231d77548a1SPatrick Williams mesondir="${outputdir}/$(dirname "$1")" 232d77548a1SPatrick Williams yamldir="$(realpath --relative-to="${mesondir}" "${rootdir}")" 233847a0c37SPatrick Williams 234847a0c37SPatrick Williams # Determine the source files based on the YAMLs present. 235847a0c37SPatrick Williams sources="" 2369ede18b4SPatrick Williams for s in ${interfaces[$1]}; do 2375800d079SPatrick Williams sources="${sources}'${yamldir}/$1.${s}', " 238847a0c37SPatrick Williams done 239847a0c37SPatrick Williams 240847a0c37SPatrick Williams # Create the target to generate the interface.md file. 241d77548a1SPatrick Williams cat >> "${mesondir}/meson.build" \ 242847a0c37SPatrick Williams << EOF 243847a0c37SPatrick Williamsgenerated_others += custom_target( 244847a0c37SPatrick Williams '$1__markdown'.underscorify(), 245d77548a1SPatrick Williams input: [ ${sources} ], 246847a0c37SPatrick Williams output: [ '$(basename "$1").md' ], 247293c8a26SWilliam A. Kennington III depend_files: sdbusplusplus_depfiles, 248847a0c37SPatrick Williams command: [ 249847a0c37SPatrick Williams sdbuspp_gen_meson_prog, '--command', 'markdown', 250847a0c37SPatrick Williams '--output', meson.current_build_dir(), 251847a0c37SPatrick Williams '--tool', sdbusplusplus_prog, 252d77548a1SPatrick Williams '--directory', meson.current_source_dir() / '${yamldir}', 253847a0c37SPatrick Williams '$1', 254847a0c37SPatrick Williams ], 255847a0c37SPatrick Williams) 256847a0c37SPatrick Williams 257847a0c37SPatrick WilliamsEOF 258847a0c37SPatrick Williams} 259847a0c37SPatrick Williams 260847a0c37SPatrick Williams## Handle command=meson by generating the tree of meson.build files. 261018b8ff1SPatrick Williamsfunction cmd_meson() { 262ce8d16d9SWillam A. Kennington III # Find and sort all the YAML files 2630336a2fcSPatrick Williams yamls="$(find "${rootdir}" -name '*.interface.yaml' -o -name '*.errors.yaml' -o -name '*.events.yaml')" 264ce8d16d9SWillam A. Kennington III yamls="$(echo "${yamls}" | sort)" 265847a0c37SPatrick Williams 266847a0c37SPatrick Williams # Assign the YAML files into the hash-table by interface name. 267d77548a1SPatrick Williams for y in ${yamls}; do 268d77548a1SPatrick Williams rel="$(realpath "--relative-to=${rootdir}" "${y}")" 269d77548a1SPatrick Williams dir="$(dirname "${rel}")" 270847a0c37SPatrick Williams ext="${rel#*.}" 271d77548a1SPatrick Williams base="$(basename "${rel}" ".${ext}")" 272d77548a1SPatrick Williams key="${dir}/${base}" 273847a0c37SPatrick Williams 274d77548a1SPatrick Williams interfaces["${key}"]="${interfaces[${key}]} ${ext}" 275847a0c37SPatrick Williams done 276847a0c37SPatrick Williams 277847a0c37SPatrick Williams # Create the meson.build files. 278847a0c37SPatrick Williams meson_create_root 279d77548a1SPatrick Williams # shellcheck disable=SC2312 280847a0c37SPatrick Williams sorted_ifaces="$(echo "${!interfaces[@]}" | tr " " "\n" | sort)" 2819ede18b4SPatrick Williams for i in ${sorted_ifaces}; do 282d77548a1SPatrick Williams meson_create_path "${i}" 283d77548a1SPatrick Williams meson_cpp_target "${i}" 284d77548a1SPatrick Williams meson_md_target "${i}" 285847a0c37SPatrick Williams done 286847a0c37SPatrick Williams} 287847a0c37SPatrick Williams 288847a0c37SPatrick Williams## Handle command=cpp by calling sdbus++ as appropriate. 289847a0c37SPatrick Williams## $1 - interface to generate. 290847a0c37SPatrick Williams## 291847a0c37SPatrick Williams## For an interface foo/bar, the outputdir is expected to be foo/bar. 292018b8ff1SPatrick Williamsfunction cmd_cpp() { 293847a0c37SPatrick Williams 294d77548a1SPatrick Williams if [[ "" == "$1" ]]; then 295847a0c37SPatrick Williams show_usage 296847a0c37SPatrick Williams exit 1 297847a0c37SPatrick Williams fi 298847a0c37SPatrick Williams 299d77548a1SPatrick Williams if [[ ! -e "${rootdir}/$1.interface.yaml" ]] && 3000336a2fcSPatrick Williams [[ ! -e "${rootdir}/$1.errors.yaml" ]] && 3010336a2fcSPatrick Williams [[ ! -e "${rootdir}/$1.events.yaml" ]]; then 302847a0c37SPatrick Williams echo "Missing YAML for $1." 303847a0c37SPatrick Williams exit 1 304847a0c37SPatrick Williams fi 305847a0c37SPatrick Williams 306d77548a1SPatrick Williams mkdir -p "${outputdir}" 307847a0c37SPatrick Williams 308d77548a1SPatrick Williams sdbusppcmd="${sdbuspp} -r ${rootdir}" 309847a0c37SPatrick Williams intf="${1//\//.}" 310847a0c37SPatrick Williams 311d77548a1SPatrick Williams if [[ -e "${rootdir}/$1.interface.yaml" ]]; then 3121caa5e8aSPatrick Williams ${sdbusppcmd} interface common-header "${intf}" > "${outputdir}/common.hpp" 313d77548a1SPatrick Williams ${sdbusppcmd} interface server-header "${intf}" > "${outputdir}/server.hpp" 314d77548a1SPatrick Williams ${sdbusppcmd} interface server-cpp "${intf}" > "${outputdir}/server.cpp" 315d77548a1SPatrick Williams ${sdbusppcmd} interface client-header "${intf}" > "${outputdir}/client.hpp" 3166403d56fSPatrick Williams ${sdbusppcmd} interface aserver-header "${intf}" > "${outputdir}/aserver.hpp" 317847a0c37SPatrick Williams fi 318847a0c37SPatrick Williams 319d77548a1SPatrick Williams if [[ -e "${rootdir}/$1.errors.yaml" ]]; then 320d77548a1SPatrick Williams ${sdbusppcmd} error exception-header "${intf}" > "${outputdir}/error.hpp" 321d77548a1SPatrick Williams ${sdbusppcmd} error exception-cpp "${intf}" > "${outputdir}/error.cpp" 322847a0c37SPatrick Williams fi 3230336a2fcSPatrick Williams 3240336a2fcSPatrick Williams if [[ -e "${rootdir}/$1.events.yaml" ]]; then 3250336a2fcSPatrick Williams ${sdbusppcmd} event exception-header "${intf}" > "${outputdir}/event.hpp" 3260336a2fcSPatrick Williams ${sdbusppcmd} event exception-cpp "${intf}" > "${outputdir}/event.cpp" 3270336a2fcSPatrick Williams fi 328847a0c37SPatrick Williams} 329847a0c37SPatrick Williams 330847a0c37SPatrick Williams## Handle command=markdown by calling sdbus++ as appropriate. 331847a0c37SPatrick Williams## $1 - interface to generate. 332847a0c37SPatrick Williams## 333847a0c37SPatrick Williams## For an interface foo/bar, the outputdir is expected to be foo. 334018b8ff1SPatrick Williamsfunction cmd_markdown() { 335847a0c37SPatrick Williams 336d77548a1SPatrick Williams if [[ "" == "$1" ]]; then 337847a0c37SPatrick Williams show_usage 338847a0c37SPatrick Williams exit 1 339847a0c37SPatrick Williams fi 340847a0c37SPatrick Williams 341d77548a1SPatrick Williams if [[ ! -e "${rootdir}/$1.interface.yaml" ]] && 3420336a2fcSPatrick Williams [[ ! -e "${rootdir}/$1.errors.yaml" ]] && 3430336a2fcSPatrick Williams [[ ! -e "${rootdir}/$1.events.yaml" ]]; then 344847a0c37SPatrick Williams echo "Missing YAML for $1." 345847a0c37SPatrick Williams exit 1 346847a0c37SPatrick Williams fi 347847a0c37SPatrick Williams 348d77548a1SPatrick Williams mkdir -p "${outputdir}" 349847a0c37SPatrick Williams 350d77548a1SPatrick Williams sdbusppcmd="${sdbuspp} -r ${rootdir}" 351847a0c37SPatrick Williams intf="${1//\//.}" 352847a0c37SPatrick Williams base="$(basename "$1")" 353847a0c37SPatrick Williams 354d77548a1SPatrick Williams echo -n > "${outputdir}/${base}.md" 355d77548a1SPatrick Williams if [[ -e "${rootdir}/$1.interface.yaml" ]]; then 356d77548a1SPatrick Williams ${sdbusppcmd} interface markdown "${intf}" >> "${outputdir}/${base}.md" 357847a0c37SPatrick Williams fi 358847a0c37SPatrick Williams 359d77548a1SPatrick Williams if [[ -e "${rootdir}/$1.errors.yaml" ]]; then 360d77548a1SPatrick Williams ${sdbusppcmd} error markdown "${intf}" >> "${outputdir}/${base}.md" 361847a0c37SPatrick Williams fi 3620336a2fcSPatrick Williams 3630336a2fcSPatrick Williams if [[ -e "${rootdir}/$1.events.yaml" ]]; then 3640336a2fcSPatrick Williams ${sdbusppcmd} event markdown "${intf}" >> "${outputdir}/${base}.md" 3650336a2fcSPatrick Williams fi 366847a0c37SPatrick Williams} 367847a0c37SPatrick Williams 368847a0c37SPatrick Williams## Handle command=version. 369018b8ff1SPatrick Williamsfunction cmd_version() { 370847a0c37SPatrick Williams show_version 371847a0c37SPatrick Williams} 372847a0c37SPatrick Williams 373d77548a1SPatrick Williams"cmd_${cmd}" "$*" 374