blob: 5b6138260a579e407f150242e53feebe5c519afd [file] [log] [blame]
Patrick Williams847a0c32020-06-24 15:18:10 -05001#!/usr/bin/env bash
2
3set -e
4
Patrick Williamsa4c9edc2020-12-17 21:02:36 -06005# Locale can change behavior of utilities like 'sort' but we want the output
6# to be stable on all machines. Force the locale to 'C' for consistency.
7export LC_ALL=C
8
Patrick Williams018b8ff2022-12-05 16:03:46 -06009function show_usage() {
Patrick Williams847a0c32020-06-24 15:18:10 -050010 cat \
Patrick Williams9ede18b2022-03-12 07:55:36 -060011 << EOF
Patrick Williams847a0c32020-06-24 15:18:10 -050012Usage: $(basename "$0") [options] <command-args>*
13
14Generate meson.build files from a directory tree containing YAML files and
15facilitate building the sdbus++ sources.
16
17Options:
18 --help - Display this message
19 --command <cmd> - Command mode to execute (default 'meson').
20 --directory <path> - Root directory of the YAML source (default '.').
21 --output <path> - Root directory of the output (default '.').
22 --tool <path> - Path to the processing tool (default 'sdbus++').
23 --version - Display this tool's version string.
24
25Commands:
26 meson - Generate a tree of meson.build files corresponding
27 to the source YAML files.
28 cpp <intf> - Generate the source files from a YAML interface.
29 markdown <intf> - Generate the markdown files from a YAML interface.
30 version - Display this tool's version string.
31
32EOF
33}
34
35## The version is somewhat arbitrary but is used to create a warning message
36## if a repository contains old copies of the generated meson.build files and
37## needs an update. We should increment the version number whenever the
38## resulting meson.build would change.
Patrick Williams0ac157a2024-09-23 21:57:39 -040039tool_version="sdbus++-gen-meson version 9"
Patrick Williams018b8ff2022-12-05 16:03:46 -060040function show_version() {
Patrick Williamsd77548a2022-04-29 14:43:15 -050041 echo "${tool_version}"
Patrick Williams847a0c32020-06-24 15:18:10 -050042}
43
44# Set up defaults.
45sdbuspp="sdbus++"
46outputdir="."
47cmd="meson"
48rootdir="."
49
50# Parse options.
51options="$(getopt -o hc:d:o:t:v --long help,command:,directory:,output:,tool:,version -- "$@")"
Patrick Williamsd77548a2022-04-29 14:43:15 -050052eval set -- "${options}"
Patrick Williams847a0c32020-06-24 15:18:10 -050053
Patrick Williams9ede18b2022-03-12 07:55:36 -060054while true; do
Patrick Williams847a0c32020-06-24 15:18:10 -050055 case "$1" in
56 -h | --help)
57 show_usage
58 exit
59 ;;
60
61 -c | --command)
62 shift
63 cmd="$1"
64 shift
65 ;;
66
67 -d | --directory)
68 shift
69 rootdir="$1"
70 shift
71 ;;
72
73 -o | --output)
74 shift
75 outputdir="$1"
76 shift
77 ;;
78
79 -t | --tool)
80 shift
81 sdbuspp="$1"
82 shift
83 ;;
84
85 -v | --version)
86 show_version
87 exit
88 ;;
89
90 --)
91 shift
92 break
93 ;;
Patrick Williamsd77548a2022-04-29 14:43:15 -050094
95 *)
96 echo "Invalid argument $1"
97 exit 1
98 ;;
Patrick Williams847a0c32020-06-24 15:18:10 -050099 esac
100done
101
102## Create an initially empty meson.build file.
103## $1 - path to create meson.build at.
Patrick Williams018b8ff2022-12-05 16:03:46 -0600104function meson_empty_file() {
Patrick Williams847a0c32020-06-24 15:18:10 -0500105 mkdir -p "$1"
106 echo "# Generated file; do not modify." > "$1/meson.build"
107}
108
109## Create the root-level meson.build
110##
111## Inserts rules to run the available version of this tool to ensure the
112## version has not changed.
Patrick Williams018b8ff2022-12-05 16:03:46 -0600113function meson_create_root() {
Patrick Williamsd77548a2022-04-29 14:43:15 -0500114 meson_empty_file "${outputdir}"
Patrick Williams847a0c32020-06-24 15:18:10 -0500115
Patrick Williamsd77548a2022-04-29 14:43:15 -0500116 cat >> "${outputdir}/meson.build" \
Patrick Williams9ede18b2022-03-12 07:55:36 -0600117 << EOF
Patrick Williams847a0c32020-06-24 15:18:10 -0500118sdbuspp_gen_meson_ver = run_command(
119 sdbuspp_gen_meson_prog,
120 '--version',
Ed Tanous60a94302023-01-06 13:52:45 -0800121 check: true,
Patrick Williams847a0c32020-06-24 15:18:10 -0500122).stdout().strip().split('\n')[0]
123
Patrick Williamsd77548a2022-04-29 14:43:15 -0500124if sdbuspp_gen_meson_ver != '${tool_version}'
Patrick Williams847a0c32020-06-24 15:18:10 -0500125 warning('Generated meson files from wrong version of sdbus++-gen-meson.')
126 warning(
Patrick Williamsd77548a2022-04-29 14:43:15 -0500127 'Expected "${tool_version}", got:',
Patrick Williams847a0c32020-06-24 15:18:10 -0500128 sdbuspp_gen_meson_ver
129 )
130endif
131
132EOF
133}
134
135## hash-tables to store:
136## meson_paths - list of subdirectory paths for which an empty meson.build
137## has already been created.
138## interfaces - list of interface paths which a YAML has been found and
139## which YAML types (interface, errors, etc.).
140declare -A meson_paths
141declare -A interfaces
142
143## Ensure the meson.build files to a path have been created.
144## $1 - The path requiring to be created.
Patrick Williams018b8ff2022-12-05 16:03:46 -0600145function meson_create_path() {
Patrick Williams847a0c32020-06-24 15:18:10 -0500146
Patrick Williamsd77548a2022-04-29 14:43:15 -0500147 meson_path="${outputdir}"
Patrick Williams847a0c32020-06-24 15:18:10 -0500148 prev_meson_path=""
149
150 # Split the path into segments.
Patrick Williams9ede18b2022-03-12 07:55:36 -0600151 for part in $(echo "$1" | tr '/' '\n'); do
Patrick Williamsd77548a2022-04-29 14:43:15 -0500152 prev_meson_path="${meson_path}"
153 meson_path="${meson_path}/${part}"
Patrick Williams847a0c32020-06-24 15:18:10 -0500154
155 # Create the meson.build for this segment if it doesn't already exist.
Patrick Williamsd77548a2022-04-29 14:43:15 -0500156 if [[ "" == "${meson_paths[${meson_path}]}" ]]; then
157 meson_paths["${meson_path}"]="1"
158 meson_empty_file "${meson_path}"
Patrick Williams847a0c32020-06-24 15:18:10 -0500159
160 # Add the 'subdir' link into the parent's meson.build.
161 # We need to skip adding the links into the 'root' meson.build
162 # because most repositories want to selectively add TLDs based
163 # on config flags. Let them figure out their own logic for that.
Patrick Williamsd77548a2022-04-29 14:43:15 -0500164 if [[ ${outputdir} != "${prev_meson_path}" ]]; then
165 echo "subdir('${part}')" >> "${prev_meson_path}/meson.build"
Patrick Williams847a0c32020-06-24 15:18:10 -0500166 fi
167 fi
168 done
169}
170
171## Generate the meson target for the source files (.cpp/.hpp) from a YAML
172## interface.
173##
174## $1 - The interface to generate a target for.
Patrick Williams018b8ff2022-12-05 16:03:46 -0600175function meson_cpp_target() {
Patrick Williamsd77548a2022-04-29 14:43:15 -0500176 mesondir="${outputdir}/$1"
177 yamldir="$(realpath --relative-to="${mesondir}" "${rootdir}")"
Patrick Williams847a0c32020-06-24 15:18:10 -0500178
179 # Determine the source and output files based on the YAMLs present.
180 sources=""
181 outputs=""
Patrick Williams9ede18b2022-03-12 07:55:36 -0600182 for s in ${interfaces[$1]}; do
Patrick Williams0ac157a2024-09-23 21:57:39 -0400183 sources="${sources}'${yamldir}/$1.${s}', "
Patrick Williams847a0c32020-06-24 15:18:10 -0500184
Patrick Williamsd77548a2022-04-29 14:43:15 -0500185 case "${s}" in
Patrick Williams847a0c32020-06-24 15:18:10 -0500186 errors.yaml)
187 outputs="${outputs}'error.cpp', 'error.hpp', "
188 ;;
189
Patrick Williams0336a2f2024-09-05 21:41:07 -0400190 events.yaml)
191 outputs="${outputs}'event.cpp', 'event.hpp', "
192 ;;
193
Patrick Williams847a0c32020-06-24 15:18:10 -0500194 interface.yaml)
Patrick Williams1caa5e82023-04-19 16:24:38 -0500195 outputs="${outputs}'common.hpp', "
Patrick Williams847a0c32020-06-24 15:18:10 -0500196 outputs="${outputs}'server.cpp', 'server.hpp', "
Patrick Williams6403d562023-08-18 11:34:43 -0500197 outputs="${outputs}'aserver.hpp', "
Patrick Williams847a0c32020-06-24 15:18:10 -0500198 outputs="${outputs}'client.hpp', "
199 ;;
Patrick Williamsd77548a2022-04-29 14:43:15 -0500200
201 *)
202 echo "Unknown interface type: ${s}"
203 exit 1
204 ;;
Patrick Williams847a0c32020-06-24 15:18:10 -0500205 esac
206 done
207
208 # Create the target to generate the 'outputs'.
Patrick Williamsd77548a2022-04-29 14:43:15 -0500209 cat >> "${mesondir}/meson.build" \
Patrick Williams9ede18b2022-03-12 07:55:36 -0600210 << EOF
Patrick Williams847a0c32020-06-24 15:18:10 -0500211generated_sources += custom_target(
212 '$1__cpp'.underscorify(),
Patrick Williamsd77548a2022-04-29 14:43:15 -0500213 input: [ ${sources} ],
214 output: [ ${outputs} ],
William A. Kennington III293c8a22022-09-02 14:35:54 -0700215 depend_files: sdbusplusplus_depfiles,
Patrick Williams847a0c32020-06-24 15:18:10 -0500216 command: [
217 sdbuspp_gen_meson_prog, '--command', 'cpp',
218 '--output', meson.current_build_dir(),
219 '--tool', sdbusplusplus_prog,
Patrick Williamsd77548a2022-04-29 14:43:15 -0500220 '--directory', meson.current_source_dir() / '${yamldir}',
Patrick Williams847a0c32020-06-24 15:18:10 -0500221 '$1',
222 ],
223)
224
225EOF
226}
227
228## Generate the meson target for the markdown files from a YAML interface.
229## $1 - The interface to generate a target for.
Patrick Williams018b8ff2022-12-05 16:03:46 -0600230function meson_md_target() {
Patrick Williamsd77548a2022-04-29 14:43:15 -0500231 mesondir="${outputdir}/$(dirname "$1")"
232 yamldir="$(realpath --relative-to="${mesondir}" "${rootdir}")"
Patrick Williams847a0c32020-06-24 15:18:10 -0500233
234 # Determine the source files based on the YAMLs present.
235 sources=""
Patrick Williams9ede18b2022-03-12 07:55:36 -0600236 for s in ${interfaces[$1]}; do
Patrick Williams5800d072024-09-16 22:28:18 -0400237 sources="${sources}'${yamldir}/$1.${s}', "
Patrick Williams847a0c32020-06-24 15:18:10 -0500238 done
239
240 # Create the target to generate the interface.md file.
Patrick Williamsd77548a2022-04-29 14:43:15 -0500241 cat >> "${mesondir}/meson.build" \
Patrick Williams9ede18b2022-03-12 07:55:36 -0600242 << EOF
Patrick Williams847a0c32020-06-24 15:18:10 -0500243generated_others += custom_target(
244 '$1__markdown'.underscorify(),
Patrick Williamsd77548a2022-04-29 14:43:15 -0500245 input: [ ${sources} ],
Patrick Williams847a0c32020-06-24 15:18:10 -0500246 output: [ '$(basename "$1").md' ],
William A. Kennington III293c8a22022-09-02 14:35:54 -0700247 depend_files: sdbusplusplus_depfiles,
Patrick Williams847a0c32020-06-24 15:18:10 -0500248 command: [
249 sdbuspp_gen_meson_prog, '--command', 'markdown',
250 '--output', meson.current_build_dir(),
251 '--tool', sdbusplusplus_prog,
Patrick Williamsd77548a2022-04-29 14:43:15 -0500252 '--directory', meson.current_source_dir() / '${yamldir}',
Patrick Williams847a0c32020-06-24 15:18:10 -0500253 '$1',
254 ],
Patrick Williams847a0c32020-06-24 15:18:10 -0500255)
256
257EOF
258}
259
260## Handle command=meson by generating the tree of meson.build files.
Patrick Williams018b8ff2022-12-05 16:03:46 -0600261function cmd_meson() {
Willam A. Kennington IIIce8d16d2022-09-07 15:46:40 -0700262 # Find and sort all the YAML files
Patrick Williams0336a2f2024-09-05 21:41:07 -0400263 yamls="$(find "${rootdir}" -name '*.interface.yaml' -o -name '*.errors.yaml' -o -name '*.events.yaml')"
Willam A. Kennington IIIce8d16d2022-09-07 15:46:40 -0700264 yamls="$(echo "${yamls}" | sort)"
Patrick Williams847a0c32020-06-24 15:18:10 -0500265
266 # Assign the YAML files into the hash-table by interface name.
Patrick Williamsd77548a2022-04-29 14:43:15 -0500267 for y in ${yamls}; do
268 rel="$(realpath "--relative-to=${rootdir}" "${y}")"
269 dir="$(dirname "${rel}")"
Patrick Williams847a0c32020-06-24 15:18:10 -0500270 ext="${rel#*.}"
Patrick Williamsd77548a2022-04-29 14:43:15 -0500271 base="$(basename "${rel}" ".${ext}")"
272 key="${dir}/${base}"
Patrick Williams847a0c32020-06-24 15:18:10 -0500273
Patrick Williamsd77548a2022-04-29 14:43:15 -0500274 interfaces["${key}"]="${interfaces[${key}]} ${ext}"
Patrick Williams847a0c32020-06-24 15:18:10 -0500275 done
276
277 # Create the meson.build files.
278 meson_create_root
Patrick Williamsd77548a2022-04-29 14:43:15 -0500279 # shellcheck disable=SC2312
Patrick Williams847a0c32020-06-24 15:18:10 -0500280 sorted_ifaces="$(echo "${!interfaces[@]}" | tr " " "\n" | sort)"
Patrick Williams9ede18b2022-03-12 07:55:36 -0600281 for i in ${sorted_ifaces}; do
Patrick Williamsd77548a2022-04-29 14:43:15 -0500282 meson_create_path "${i}"
283 meson_cpp_target "${i}"
284 meson_md_target "${i}"
Patrick Williams847a0c32020-06-24 15:18:10 -0500285 done
286}
287
288## Handle command=cpp by calling sdbus++ as appropriate.
289## $1 - interface to generate.
290##
291## For an interface foo/bar, the outputdir is expected to be foo/bar.
Patrick Williams018b8ff2022-12-05 16:03:46 -0600292function cmd_cpp() {
Patrick Williams847a0c32020-06-24 15:18:10 -0500293
Patrick Williamsd77548a2022-04-29 14:43:15 -0500294 if [[ "" == "$1" ]]; then
Patrick Williams847a0c32020-06-24 15:18:10 -0500295 show_usage
296 exit 1
297 fi
298
Patrick Williamsd77548a2022-04-29 14:43:15 -0500299 if [[ ! -e "${rootdir}/$1.interface.yaml" ]] &&
Patrick Williams0336a2f2024-09-05 21:41:07 -0400300 [[ ! -e "${rootdir}/$1.errors.yaml" ]] &&
301 [[ ! -e "${rootdir}/$1.events.yaml" ]]; then
Patrick Williams847a0c32020-06-24 15:18:10 -0500302 echo "Missing YAML for $1."
303 exit 1
304 fi
305
Patrick Williamsd77548a2022-04-29 14:43:15 -0500306 mkdir -p "${outputdir}"
Patrick Williams847a0c32020-06-24 15:18:10 -0500307
Patrick Williamsd77548a2022-04-29 14:43:15 -0500308 sdbusppcmd="${sdbuspp} -r ${rootdir}"
Patrick Williams847a0c32020-06-24 15:18:10 -0500309 intf="${1//\//.}"
310
Patrick Williamsd77548a2022-04-29 14:43:15 -0500311 if [[ -e "${rootdir}/$1.interface.yaml" ]]; then
Patrick Williams1caa5e82023-04-19 16:24:38 -0500312 ${sdbusppcmd} interface common-header "${intf}" > "${outputdir}/common.hpp"
Patrick Williamsd77548a2022-04-29 14:43:15 -0500313 ${sdbusppcmd} interface server-header "${intf}" > "${outputdir}/server.hpp"
314 ${sdbusppcmd} interface server-cpp "${intf}" > "${outputdir}/server.cpp"
315 ${sdbusppcmd} interface client-header "${intf}" > "${outputdir}/client.hpp"
Patrick Williams6403d562023-08-18 11:34:43 -0500316 ${sdbusppcmd} interface aserver-header "${intf}" > "${outputdir}/aserver.hpp"
Patrick Williams847a0c32020-06-24 15:18:10 -0500317 fi
318
Patrick Williamsd77548a2022-04-29 14:43:15 -0500319 if [[ -e "${rootdir}/$1.errors.yaml" ]]; then
320 ${sdbusppcmd} error exception-header "${intf}" > "${outputdir}/error.hpp"
321 ${sdbusppcmd} error exception-cpp "${intf}" > "${outputdir}/error.cpp"
Patrick Williams847a0c32020-06-24 15:18:10 -0500322 fi
Patrick Williams0336a2f2024-09-05 21:41:07 -0400323
324 if [[ -e "${rootdir}/$1.events.yaml" ]]; then
325 ${sdbusppcmd} event exception-header "${intf}" > "${outputdir}/event.hpp"
326 ${sdbusppcmd} event exception-cpp "${intf}" > "${outputdir}/event.cpp"
327 fi
Patrick Williams847a0c32020-06-24 15:18:10 -0500328}
329
330## Handle command=markdown by calling sdbus++ as appropriate.
331## $1 - interface to generate.
332##
333## For an interface foo/bar, the outputdir is expected to be foo.
Patrick Williams018b8ff2022-12-05 16:03:46 -0600334function cmd_markdown() {
Patrick Williams847a0c32020-06-24 15:18:10 -0500335
Patrick Williamsd77548a2022-04-29 14:43:15 -0500336 if [[ "" == "$1" ]]; then
Patrick Williams847a0c32020-06-24 15:18:10 -0500337 show_usage
338 exit 1
339 fi
340
Patrick Williamsd77548a2022-04-29 14:43:15 -0500341 if [[ ! -e "${rootdir}/$1.interface.yaml" ]] &&
Patrick Williams0336a2f2024-09-05 21:41:07 -0400342 [[ ! -e "${rootdir}/$1.errors.yaml" ]] &&
343 [[ ! -e "${rootdir}/$1.events.yaml" ]]; then
Patrick Williams847a0c32020-06-24 15:18:10 -0500344 echo "Missing YAML for $1."
345 exit 1
346 fi
347
Patrick Williamsd77548a2022-04-29 14:43:15 -0500348 mkdir -p "${outputdir}"
Patrick Williams847a0c32020-06-24 15:18:10 -0500349
Patrick Williamsd77548a2022-04-29 14:43:15 -0500350 sdbusppcmd="${sdbuspp} -r ${rootdir}"
Patrick Williams847a0c32020-06-24 15:18:10 -0500351 intf="${1//\//.}"
352 base="$(basename "$1")"
353
Patrick Williamsd77548a2022-04-29 14:43:15 -0500354 echo -n > "${outputdir}/${base}.md"
355 if [[ -e "${rootdir}/$1.interface.yaml" ]]; then
356 ${sdbusppcmd} interface markdown "${intf}" >> "${outputdir}/${base}.md"
Patrick Williams847a0c32020-06-24 15:18:10 -0500357 fi
358
Patrick Williamsd77548a2022-04-29 14:43:15 -0500359 if [[ -e "${rootdir}/$1.errors.yaml" ]]; then
360 ${sdbusppcmd} error markdown "${intf}" >> "${outputdir}/${base}.md"
Patrick Williams847a0c32020-06-24 15:18:10 -0500361 fi
Patrick Williams0336a2f2024-09-05 21:41:07 -0400362
363 if [[ -e "${rootdir}/$1.events.yaml" ]]; then
364 ${sdbusppcmd} event markdown "${intf}" >> "${outputdir}/${base}.md"
365 fi
Patrick Williams847a0c32020-06-24 15:18:10 -0500366}
367
368## Handle command=version.
Patrick Williams018b8ff2022-12-05 16:03:46 -0600369function cmd_version() {
Patrick Williams847a0c32020-06-24 15:18:10 -0500370 show_version
371}
372
Patrick Williamsd77548a2022-04-29 14:43:15 -0500373"cmd_${cmd}" "$*"