blob: d92717a8cf334fb1c9facc1ba9429c80aa1ca35c [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.
Patrick Williams31607392025-01-02 18:12:36 -050030 registry <intf> - Generate the Redfish registry from a YAML interface.
Patrick Williams847a0c32020-06-24 15:18:10 -050031 version - Display this tool's version string.
32
33EOF
34}
35
36## The version is somewhat arbitrary but is used to create a warning message
37## if a repository contains old copies of the generated meson.build files and
38## needs an update. We should increment the version number whenever the
39## resulting meson.build would change.
Patrick Williams31607392025-01-02 18:12:36 -050040tool_version="sdbus++-gen-meson version 10"
Patrick Williams018b8ff2022-12-05 16:03:46 -060041function show_version() {
Patrick Williamsd77548a2022-04-29 14:43:15 -050042 echo "${tool_version}"
Patrick Williams847a0c32020-06-24 15:18:10 -050043}
44
45# Set up defaults.
46sdbuspp="sdbus++"
47outputdir="."
48cmd="meson"
49rootdir="."
50
51# Parse options.
52options="$(getopt -o hc:d:o:t:v --long help,command:,directory:,output:,tool:,version -- "$@")"
Patrick Williamsd77548a2022-04-29 14:43:15 -050053eval set -- "${options}"
Patrick Williams847a0c32020-06-24 15:18:10 -050054
Patrick Williams9ede18b2022-03-12 07:55:36 -060055while true; do
Patrick Williams847a0c32020-06-24 15:18:10 -050056 case "$1" in
57 -h | --help)
58 show_usage
59 exit
60 ;;
61
62 -c | --command)
63 shift
64 cmd="$1"
65 shift
66 ;;
67
68 -d | --directory)
69 shift
70 rootdir="$1"
71 shift
72 ;;
73
74 -o | --output)
75 shift
76 outputdir="$1"
77 shift
78 ;;
79
80 -t | --tool)
81 shift
82 sdbuspp="$1"
83 shift
84 ;;
85
86 -v | --version)
87 show_version
88 exit
89 ;;
90
91 --)
92 shift
93 break
94 ;;
Patrick Williamsd77548a2022-04-29 14:43:15 -050095
96 *)
97 echo "Invalid argument $1"
98 exit 1
99 ;;
Patrick Williams847a0c32020-06-24 15:18:10 -0500100 esac
101done
102
103## Create an initially empty meson.build file.
104## $1 - path to create meson.build at.
Patrick Williams018b8ff2022-12-05 16:03:46 -0600105function meson_empty_file() {
Patrick Williams847a0c32020-06-24 15:18:10 -0500106 mkdir -p "$1"
107 echo "# Generated file; do not modify." > "$1/meson.build"
108}
109
110## Create the root-level meson.build
111##
112## Inserts rules to run the available version of this tool to ensure the
113## version has not changed.
Patrick Williams018b8ff2022-12-05 16:03:46 -0600114function meson_create_root() {
Patrick Williamsd77548a2022-04-29 14:43:15 -0500115 meson_empty_file "${outputdir}"
Patrick Williams847a0c32020-06-24 15:18:10 -0500116
Patrick Williamsd77548a2022-04-29 14:43:15 -0500117 cat >> "${outputdir}/meson.build" \
Patrick Williams9ede18b2022-03-12 07:55:36 -0600118 << EOF
Patrick Williams847a0c32020-06-24 15:18:10 -0500119sdbuspp_gen_meson_ver = run_command(
120 sdbuspp_gen_meson_prog,
121 '--version',
Ed Tanous60a94302023-01-06 13:52:45 -0800122 check: true,
Patrick Williams847a0c32020-06-24 15:18:10 -0500123).stdout().strip().split('\n')[0]
124
Patrick Williamsd77548a2022-04-29 14:43:15 -0500125if sdbuspp_gen_meson_ver != '${tool_version}'
Patrick Williams847a0c32020-06-24 15:18:10 -0500126 warning('Generated meson files from wrong version of sdbus++-gen-meson.')
127 warning(
Patrick Williamsd77548a2022-04-29 14:43:15 -0500128 'Expected "${tool_version}", got:',
Patrick Williams847a0c32020-06-24 15:18:10 -0500129 sdbuspp_gen_meson_ver
130 )
131endif
132
133EOF
134}
135
136## hash-tables to store:
137## meson_paths - list of subdirectory paths for which an empty meson.build
138## has already been created.
139## interfaces - list of interface paths which a YAML has been found and
140## which YAML types (interface, errors, etc.).
141declare -A meson_paths
142declare -A interfaces
143
144## Ensure the meson.build files to a path have been created.
145## $1 - The path requiring to be created.
Patrick Williams018b8ff2022-12-05 16:03:46 -0600146function meson_create_path() {
Patrick Williams847a0c32020-06-24 15:18:10 -0500147
Patrick Williamsd77548a2022-04-29 14:43:15 -0500148 meson_path="${outputdir}"
Patrick Williams847a0c32020-06-24 15:18:10 -0500149 prev_meson_path=""
150
151 # Split the path into segments.
Patrick Williams9ede18b2022-03-12 07:55:36 -0600152 for part in $(echo "$1" | tr '/' '\n'); do
Patrick Williamsd77548a2022-04-29 14:43:15 -0500153 prev_meson_path="${meson_path}"
154 meson_path="${meson_path}/${part}"
Patrick Williams847a0c32020-06-24 15:18:10 -0500155
156 # Create the meson.build for this segment if it doesn't already exist.
Patrick Williamsd77548a2022-04-29 14:43:15 -0500157 if [[ "" == "${meson_paths[${meson_path}]}" ]]; then
158 meson_paths["${meson_path}"]="1"
159 meson_empty_file "${meson_path}"
Patrick Williams847a0c32020-06-24 15:18:10 -0500160
161 # Add the 'subdir' link into the parent's meson.build.
162 # We need to skip adding the links into the 'root' meson.build
163 # because most repositories want to selectively add TLDs based
164 # on config flags. Let them figure out their own logic for that.
Patrick Williamsd77548a2022-04-29 14:43:15 -0500165 if [[ ${outputdir} != "${prev_meson_path}" ]]; then
166 echo "subdir('${part}')" >> "${prev_meson_path}/meson.build"
Patrick Williams847a0c32020-06-24 15:18:10 -0500167 fi
168 fi
169 done
170}
171
172## Generate the meson target for the source files (.cpp/.hpp) from a YAML
173## interface.
174##
175## $1 - The interface to generate a target for.
Patrick Williams018b8ff2022-12-05 16:03:46 -0600176function meson_cpp_target() {
Patrick Williamsd77548a2022-04-29 14:43:15 -0500177 mesondir="${outputdir}/$1"
178 yamldir="$(realpath --relative-to="${mesondir}" "${rootdir}")"
Patrick Williams847a0c32020-06-24 15:18:10 -0500179
180 # Determine the source and output files based on the YAMLs present.
181 sources=""
182 outputs=""
Patrick Williams9ede18b2022-03-12 07:55:36 -0600183 for s in ${interfaces[$1]}; do
Patrick Williams0ac157a2024-09-23 21:57:39 -0400184 sources="${sources}'${yamldir}/$1.${s}', "
Patrick Williams847a0c32020-06-24 15:18:10 -0500185
Patrick Williamsd77548a2022-04-29 14:43:15 -0500186 case "${s}" in
Patrick Williams847a0c32020-06-24 15:18:10 -0500187 errors.yaml)
188 outputs="${outputs}'error.cpp', 'error.hpp', "
189 ;;
190
Patrick Williams0336a2f2024-09-05 21:41:07 -0400191 events.yaml)
192 outputs="${outputs}'event.cpp', 'event.hpp', "
193 ;;
194
Patrick Williams847a0c32020-06-24 15:18:10 -0500195 interface.yaml)
Patrick Williams1caa5e82023-04-19 16:24:38 -0500196 outputs="${outputs}'common.hpp', "
Patrick Williams847a0c32020-06-24 15:18:10 -0500197 outputs="${outputs}'server.cpp', 'server.hpp', "
Patrick Williams6403d562023-08-18 11:34:43 -0500198 outputs="${outputs}'aserver.hpp', "
Patrick Williams847a0c32020-06-24 15:18:10 -0500199 outputs="${outputs}'client.hpp', "
200 ;;
Patrick Williamsd77548a2022-04-29 14:43:15 -0500201
202 *)
203 echo "Unknown interface type: ${s}"
204 exit 1
205 ;;
Patrick Williams847a0c32020-06-24 15:18:10 -0500206 esac
207 done
208
209 # Create the target to generate the 'outputs'.
Patrick Williamsd77548a2022-04-29 14:43:15 -0500210 cat >> "${mesondir}/meson.build" \
Patrick Williams9ede18b2022-03-12 07:55:36 -0600211 << EOF
Patrick Williams847a0c32020-06-24 15:18:10 -0500212generated_sources += custom_target(
213 '$1__cpp'.underscorify(),
Patrick Williamsd77548a2022-04-29 14:43:15 -0500214 input: [ ${sources} ],
215 output: [ ${outputs} ],
William A. Kennington III293c8a22022-09-02 14:35:54 -0700216 depend_files: sdbusplusplus_depfiles,
Patrick Williams847a0c32020-06-24 15:18:10 -0500217 command: [
218 sdbuspp_gen_meson_prog, '--command', 'cpp',
219 '--output', meson.current_build_dir(),
220 '--tool', sdbusplusplus_prog,
Patrick Williamsd77548a2022-04-29 14:43:15 -0500221 '--directory', meson.current_source_dir() / '${yamldir}',
Patrick Williams847a0c32020-06-24 15:18:10 -0500222 '$1',
223 ],
224)
225
226EOF
227}
228
229## Generate the meson target for the markdown files from a YAML interface.
230## $1 - The interface to generate a target for.
Patrick Williams018b8ff2022-12-05 16:03:46 -0600231function meson_md_target() {
Patrick Williamsd77548a2022-04-29 14:43:15 -0500232 mesondir="${outputdir}/$(dirname "$1")"
233 yamldir="$(realpath --relative-to="${mesondir}" "${rootdir}")"
Patrick Williams847a0c32020-06-24 15:18:10 -0500234
235 # Determine the source files based on the YAMLs present.
236 sources=""
Patrick Williams9ede18b2022-03-12 07:55:36 -0600237 for s in ${interfaces[$1]}; do
Patrick Williams5800d072024-09-16 22:28:18 -0400238 sources="${sources}'${yamldir}/$1.${s}', "
Patrick Williams847a0c32020-06-24 15:18:10 -0500239 done
240
241 # Create the target to generate the interface.md file.
Patrick Williamsd77548a2022-04-29 14:43:15 -0500242 cat >> "${mesondir}/meson.build" \
Patrick Williams9ede18b2022-03-12 07:55:36 -0600243 << EOF
Patrick Williams847a0c32020-06-24 15:18:10 -0500244generated_others += custom_target(
245 '$1__markdown'.underscorify(),
Patrick Williamsd77548a2022-04-29 14:43:15 -0500246 input: [ ${sources} ],
Patrick Williams847a0c32020-06-24 15:18:10 -0500247 output: [ '$(basename "$1").md' ],
William A. Kennington III293c8a22022-09-02 14:35:54 -0700248 depend_files: sdbusplusplus_depfiles,
Patrick Williams847a0c32020-06-24 15:18:10 -0500249 command: [
250 sdbuspp_gen_meson_prog, '--command', 'markdown',
251 '--output', meson.current_build_dir(),
252 '--tool', sdbusplusplus_prog,
Patrick Williamsd77548a2022-04-29 14:43:15 -0500253 '--directory', meson.current_source_dir() / '${yamldir}',
Patrick Williams847a0c32020-06-24 15:18:10 -0500254 '$1',
255 ],
Patrick Williams847a0c32020-06-24 15:18:10 -0500256)
257
258EOF
259}
260
Patrick Williams31607392025-01-02 18:12:36 -0500261## Generate the meson target for the registry files from a YAML interface.
262## $1 - The interface to generate a target for.
263function meson_registry_target() {
264 mesondir="${outputdir}/$(dirname "$1")"
265 yamldir="$(realpath --relative-to="${mesondir}" "${rootdir}")"
266
267 # Determine the source and output files based on the YAMLs present.
268 sources=""
269 outputs=""
270 for s in ${interfaces[$1]}; do
271 case "${s}" in
272 errors.yaml)
273 ;;
274
275 events.yaml)
276 sources="${sources}'${yamldir}/$1.${s}', "
277 outputs="${outputs}'event.cpp', 'event.hpp', "
278 ;;
279
280 interface.yaml)
281 ;;
282
283 *)
284 echo "Unknown interface type: ${s}"
285 exit 1
286 ;;
287 esac
288 done
289
290 if [[ -z "${sources}" ]]; then
291 return
292 fi
293
294 # Create the target to generate the interface.md file.
295 cat >> "${mesondir}/meson.build" \
296 << EOF
297generated_others += custom_target(
298 '$1__registry'.underscorify(),
299 input: [ ${sources} ],
300 output: [ '$(basename "$1").json' ],
301 depend_files: sdbusplusplus_depfiles,
302 command: [
303 sdbuspp_gen_meson_prog, '--command', 'registry',
304 '--output', meson.current_build_dir(),
305 '--tool', sdbusplusplus_prog,
306 '--directory', meson.current_source_dir() / '${yamldir}',
307 '$1',
308 ],
309)
310
311EOF
312}
313
314
Patrick Williams847a0c32020-06-24 15:18:10 -0500315## Handle command=meson by generating the tree of meson.build files.
Patrick Williams018b8ff2022-12-05 16:03:46 -0600316function cmd_meson() {
Willam A. Kennington IIIce8d16d2022-09-07 15:46:40 -0700317 # Find and sort all the YAML files
Patrick Williams0336a2f2024-09-05 21:41:07 -0400318 yamls="$(find "${rootdir}" -name '*.interface.yaml' -o -name '*.errors.yaml' -o -name '*.events.yaml')"
Willam A. Kennington IIIce8d16d2022-09-07 15:46:40 -0700319 yamls="$(echo "${yamls}" | sort)"
Patrick Williams847a0c32020-06-24 15:18:10 -0500320
321 # Assign the YAML files into the hash-table by interface name.
Patrick Williamsd77548a2022-04-29 14:43:15 -0500322 for y in ${yamls}; do
323 rel="$(realpath "--relative-to=${rootdir}" "${y}")"
324 dir="$(dirname "${rel}")"
Patrick Williams847a0c32020-06-24 15:18:10 -0500325 ext="${rel#*.}"
Patrick Williamsd77548a2022-04-29 14:43:15 -0500326 base="$(basename "${rel}" ".${ext}")"
327 key="${dir}/${base}"
Patrick Williams847a0c32020-06-24 15:18:10 -0500328
Patrick Williamsd77548a2022-04-29 14:43:15 -0500329 interfaces["${key}"]="${interfaces[${key}]} ${ext}"
Patrick Williams847a0c32020-06-24 15:18:10 -0500330 done
331
332 # Create the meson.build files.
333 meson_create_root
Patrick Williamsd77548a2022-04-29 14:43:15 -0500334 # shellcheck disable=SC2312
Patrick Williams847a0c32020-06-24 15:18:10 -0500335 sorted_ifaces="$(echo "${!interfaces[@]}" | tr " " "\n" | sort)"
Patrick Williams9ede18b2022-03-12 07:55:36 -0600336 for i in ${sorted_ifaces}; do
Patrick Williamsd77548a2022-04-29 14:43:15 -0500337 meson_create_path "${i}"
338 meson_cpp_target "${i}"
339 meson_md_target "${i}"
Patrick Williams31607392025-01-02 18:12:36 -0500340 meson_registry_target "${i}"
Patrick Williams847a0c32020-06-24 15:18:10 -0500341 done
342}
343
344## Handle command=cpp by calling sdbus++ as appropriate.
345## $1 - interface to generate.
346##
347## For an interface foo/bar, the outputdir is expected to be foo/bar.
Patrick Williams018b8ff2022-12-05 16:03:46 -0600348function cmd_cpp() {
Patrick Williams847a0c32020-06-24 15:18:10 -0500349
Patrick Williamsd77548a2022-04-29 14:43:15 -0500350 if [[ "" == "$1" ]]; then
Patrick Williams847a0c32020-06-24 15:18:10 -0500351 show_usage
352 exit 1
353 fi
354
Patrick Williamsd77548a2022-04-29 14:43:15 -0500355 if [[ ! -e "${rootdir}/$1.interface.yaml" ]] &&
Patrick Williams0336a2f2024-09-05 21:41:07 -0400356 [[ ! -e "${rootdir}/$1.errors.yaml" ]] &&
357 [[ ! -e "${rootdir}/$1.events.yaml" ]]; then
Patrick Williams847a0c32020-06-24 15:18:10 -0500358 echo "Missing YAML for $1."
359 exit 1
360 fi
361
Patrick Williamsd77548a2022-04-29 14:43:15 -0500362 mkdir -p "${outputdir}"
Patrick Williams847a0c32020-06-24 15:18:10 -0500363
Patrick Williamsd77548a2022-04-29 14:43:15 -0500364 sdbusppcmd="${sdbuspp} -r ${rootdir}"
Patrick Williams847a0c32020-06-24 15:18:10 -0500365 intf="${1//\//.}"
366
Patrick Williamsd77548a2022-04-29 14:43:15 -0500367 if [[ -e "${rootdir}/$1.interface.yaml" ]]; then
Patrick Williams1caa5e82023-04-19 16:24:38 -0500368 ${sdbusppcmd} interface common-header "${intf}" > "${outputdir}/common.hpp"
Patrick Williamsd77548a2022-04-29 14:43:15 -0500369 ${sdbusppcmd} interface server-header "${intf}" > "${outputdir}/server.hpp"
370 ${sdbusppcmd} interface server-cpp "${intf}" > "${outputdir}/server.cpp"
371 ${sdbusppcmd} interface client-header "${intf}" > "${outputdir}/client.hpp"
Patrick Williams6403d562023-08-18 11:34:43 -0500372 ${sdbusppcmd} interface aserver-header "${intf}" > "${outputdir}/aserver.hpp"
Patrick Williams847a0c32020-06-24 15:18:10 -0500373 fi
374
Patrick Williamsd77548a2022-04-29 14:43:15 -0500375 if [[ -e "${rootdir}/$1.errors.yaml" ]]; then
376 ${sdbusppcmd} error exception-header "${intf}" > "${outputdir}/error.hpp"
377 ${sdbusppcmd} error exception-cpp "${intf}" > "${outputdir}/error.cpp"
Patrick Williams847a0c32020-06-24 15:18:10 -0500378 fi
Patrick Williams0336a2f2024-09-05 21:41:07 -0400379
380 if [[ -e "${rootdir}/$1.events.yaml" ]]; then
381 ${sdbusppcmd} event exception-header "${intf}" > "${outputdir}/event.hpp"
382 ${sdbusppcmd} event exception-cpp "${intf}" > "${outputdir}/event.cpp"
383 fi
Patrick Williams847a0c32020-06-24 15:18:10 -0500384}
385
386## Handle command=markdown by calling sdbus++ as appropriate.
387## $1 - interface to generate.
388##
389## For an interface foo/bar, the outputdir is expected to be foo.
Patrick Williams018b8ff2022-12-05 16:03:46 -0600390function cmd_markdown() {
Patrick Williams847a0c32020-06-24 15:18:10 -0500391
Patrick Williamsd77548a2022-04-29 14:43:15 -0500392 if [[ "" == "$1" ]]; then
Patrick Williams847a0c32020-06-24 15:18:10 -0500393 show_usage
394 exit 1
395 fi
396
Patrick Williamsd77548a2022-04-29 14:43:15 -0500397 if [[ ! -e "${rootdir}/$1.interface.yaml" ]] &&
Patrick Williams0336a2f2024-09-05 21:41:07 -0400398 [[ ! -e "${rootdir}/$1.errors.yaml" ]] &&
399 [[ ! -e "${rootdir}/$1.events.yaml" ]]; then
Patrick Williams847a0c32020-06-24 15:18:10 -0500400 echo "Missing YAML for $1."
401 exit 1
402 fi
403
Patrick Williamsd77548a2022-04-29 14:43:15 -0500404 mkdir -p "${outputdir}"
Patrick Williams847a0c32020-06-24 15:18:10 -0500405
Patrick Williamsd77548a2022-04-29 14:43:15 -0500406 sdbusppcmd="${sdbuspp} -r ${rootdir}"
Patrick Williams847a0c32020-06-24 15:18:10 -0500407 intf="${1//\//.}"
408 base="$(basename "$1")"
409
Patrick Williamsd77548a2022-04-29 14:43:15 -0500410 echo -n > "${outputdir}/${base}.md"
411 if [[ -e "${rootdir}/$1.interface.yaml" ]]; then
412 ${sdbusppcmd} interface markdown "${intf}" >> "${outputdir}/${base}.md"
Patrick Williams847a0c32020-06-24 15:18:10 -0500413 fi
414
Patrick Williamsd77548a2022-04-29 14:43:15 -0500415 if [[ -e "${rootdir}/$1.errors.yaml" ]]; then
416 ${sdbusppcmd} error markdown "${intf}" >> "${outputdir}/${base}.md"
Patrick Williams847a0c32020-06-24 15:18:10 -0500417 fi
Patrick Williams0336a2f2024-09-05 21:41:07 -0400418
419 if [[ -e "${rootdir}/$1.events.yaml" ]]; then
420 ${sdbusppcmd} event markdown "${intf}" >> "${outputdir}/${base}.md"
421 fi
Patrick Williams847a0c32020-06-24 15:18:10 -0500422}
423
Patrick Williams31607392025-01-02 18:12:36 -0500424## Handle command=registry by calling sdbus++ as appropriate.
425## $1 - interface to generate.
426##
427## For an interface foo/bar, the outputdir is expected to be foo.
428function cmd_registry() {
429
430 if [[ "" == "$1" ]]; then
431 show_usage
432 exit 1
433 fi
434
435 if [[ ! -e "${rootdir}/$1.events.yaml" ]]; then
436 echo "Missing YAML for $1."
437 exit 1
438 fi
439
440 mkdir -p "${outputdir}"
441
442 sdbusppcmd="${sdbuspp} -r ${rootdir}"
443 intf="${1//\//.}"
444 base="$(basename "$1")"
445
446 if [[ -e "${rootdir}/$1.events.yaml" ]]; then
447 ${sdbusppcmd} event exception-registry "${intf}" > "${outputdir}/${base}.json"
448 fi
449}
450
451
Patrick Williams847a0c32020-06-24 15:18:10 -0500452## Handle command=version.
Patrick Williams018b8ff2022-12-05 16:03:46 -0600453function cmd_version() {
Patrick Williams847a0c32020-06-24 15:18:10 -0500454 show_version
455}
456
Patrick Williamsd77548a2022-04-29 14:43:15 -0500457"cmd_${cmd}" "$*"