blob: 4d0658f4af8babaf1a4d7e6be6045b0705e8e789 [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 Williams847a0c32020-06-24 15:18:10 -05009function show_usage {
10 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.
William A. Kennington IIIa42e97a2021-05-17 18:33:14 -070039tool_version="sdbus++-gen-meson version 3"
Patrick Williams847a0c32020-06-24 15:18:10 -050040function show_version {
41 echo "$tool_version"
42}
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 -- "$@")"
52eval set -- "$options"
53
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 ;;
94 esac
95done
96
97## Create an initially empty meson.build file.
98## $1 - path to create meson.build at.
99function meson_empty_file {
100 mkdir -p "$1"
101 echo "# Generated file; do not modify." > "$1/meson.build"
102}
103
104## Create the root-level meson.build
105##
106## Inserts rules to run the available version of this tool to ensure the
107## version has not changed.
108function meson_create_root {
109 meson_empty_file "$outputdir"
110
111 cat >> "$outputdir/meson.build" \
Patrick Williams9ede18b2022-03-12 07:55:36 -0600112 << EOF
Patrick Williams847a0c32020-06-24 15:18:10 -0500113sdbuspp_gen_meson_ver = run_command(
114 sdbuspp_gen_meson_prog,
115 '--version',
116).stdout().strip().split('\n')[0]
117
118if sdbuspp_gen_meson_ver != '$tool_version'
119 warning('Generated meson files from wrong version of sdbus++-gen-meson.')
120 warning(
121 'Expected "$tool_version", got:',
122 sdbuspp_gen_meson_ver
123 )
124endif
125
126EOF
127}
128
129## hash-tables to store:
130## meson_paths - list of subdirectory paths for which an empty meson.build
131## has already been created.
132## interfaces - list of interface paths which a YAML has been found and
133## which YAML types (interface, errors, etc.).
134declare -A meson_paths
135declare -A interfaces
136
137## Ensure the meson.build files to a path have been created.
138## $1 - The path requiring to be created.
139function meson_create_path {
140
141 meson_path="$outputdir"
142 prev_meson_path=""
143
144 # Split the path into segments.
Patrick Williams9ede18b2022-03-12 07:55:36 -0600145 for part in $(echo "$1" | tr '/' '\n'); do
Patrick Williams847a0c32020-06-24 15:18:10 -0500146 prev_meson_path="$meson_path"
147 meson_path="$meson_path/$part"
148
149 # Create the meson.build for this segment if it doesn't already exist.
Patrick Williams9ede18b2022-03-12 07:55:36 -0600150 if [ "" == "${meson_paths[$meson_path]}" ]; then
Patrick Williams847a0c32020-06-24 15:18:10 -0500151 meson_paths["$meson_path"]="1"
152 meson_empty_file "$meson_path"
153
154 # Add the 'subdir' link into the parent's meson.build.
155 # We need to skip adding the links into the 'root' meson.build
156 # because most repositories want to selectively add TLDs based
157 # on config flags. Let them figure out their own logic for that.
Patrick Williams9ede18b2022-03-12 07:55:36 -0600158 if [ "$outputdir" != "$prev_meson_path" ]; then
Patrick Williams847a0c32020-06-24 15:18:10 -0500159 echo "subdir('$part')" >> "$prev_meson_path/meson.build"
160 fi
161 fi
162 done
163}
164
165## Generate the meson target for the source files (.cpp/.hpp) from a YAML
166## interface.
167##
168## $1 - The interface to generate a target for.
169function meson_cpp_target {
William A. Kennington III56eb1772021-05-18 20:41:26 -0700170 mesondir="$outputdir/$1"
171 yamldir="$(realpath --relative-to="$mesondir" "$rootdir")"
Patrick Williams847a0c32020-06-24 15:18:10 -0500172
173 # Determine the source and output files based on the YAMLs present.
174 sources=""
175 outputs=""
Patrick Williams9ede18b2022-03-12 07:55:36 -0600176 for s in ${interfaces[$1]}; do
177 sources="'$yamldir/$1.$s', "
Patrick Williams847a0c32020-06-24 15:18:10 -0500178
179 case "$s" in
180 errors.yaml)
181 outputs="${outputs}'error.cpp', 'error.hpp', "
182 ;;
183
184 interface.yaml)
185 outputs="${outputs}'server.cpp', 'server.hpp', "
186 outputs="${outputs}'client.hpp', "
187 ;;
188 esac
189 done
190
191 # Create the target to generate the 'outputs'.
William A. Kennington III56eb1772021-05-18 20:41:26 -0700192 cat >> "$mesondir/meson.build" \
Patrick Williams9ede18b2022-03-12 07:55:36 -0600193 << EOF
Patrick Williams847a0c32020-06-24 15:18:10 -0500194generated_sources += custom_target(
195 '$1__cpp'.underscorify(),
196 input: [ $sources ],
197 output: [ $outputs ],
198 command: [
199 sdbuspp_gen_meson_prog, '--command', 'cpp',
200 '--output', meson.current_build_dir(),
201 '--tool', sdbusplusplus_prog,
William A. Kennington III56eb1772021-05-18 20:41:26 -0700202 '--directory', meson.current_source_dir() / '$yamldir',
Patrick Williams847a0c32020-06-24 15:18:10 -0500203 '$1',
204 ],
205)
206
207EOF
208}
209
210## Generate the meson target for the markdown files from a YAML interface.
211## $1 - The interface to generate a target for.
212function meson_md_target {
William A. Kennington III56eb1772021-05-18 20:41:26 -0700213 mesondir="$outputdir/$(dirname "$1")"
214 yamldir="$(realpath --relative-to="$mesondir" "$rootdir")"
Patrick Williams847a0c32020-06-24 15:18:10 -0500215
216 # Determine the source files based on the YAMLs present.
217 sources=""
Patrick Williams9ede18b2022-03-12 07:55:36 -0600218 for s in ${interfaces[$1]}; do
William A. Kennington III56eb1772021-05-18 20:41:26 -0700219 sources="'$yamldir/$1.$s', "
Patrick Williams847a0c32020-06-24 15:18:10 -0500220 done
221
222 # Create the target to generate the interface.md file.
William A. Kennington III56eb1772021-05-18 20:41:26 -0700223 cat >> "$mesondir/meson.build" \
Patrick Williams9ede18b2022-03-12 07:55:36 -0600224 << EOF
Patrick Williams847a0c32020-06-24 15:18:10 -0500225generated_others += custom_target(
226 '$1__markdown'.underscorify(),
227 input: [ $sources ],
228 output: [ '$(basename "$1").md' ],
229 command: [
230 sdbuspp_gen_meson_prog, '--command', 'markdown',
231 '--output', meson.current_build_dir(),
232 '--tool', sdbusplusplus_prog,
William A. Kennington III56eb1772021-05-18 20:41:26 -0700233 '--directory', meson.current_source_dir() / '$yamldir',
Patrick Williams847a0c32020-06-24 15:18:10 -0500234 '$1',
235 ],
Patrick Williams847a0c32020-06-24 15:18:10 -0500236)
237
238EOF
239}
240
241## Handle command=meson by generating the tree of meson.build files.
242function cmd_meson {
243 TLDs="com net org xyz"
244 yamls=""
245
246 # Find all the YAML files in the TLD subdirectories.
Patrick Williams9ede18b2022-03-12 07:55:36 -0600247 for d in $TLDs; do
Patrick Williams847a0c32020-06-24 15:18:10 -0500248 dir="$rootdir/$d"
Patrick Williams9ede18b2022-03-12 07:55:36 -0600249 if [ ! -d "$dir" ]; then
Patrick Williams847a0c32020-06-24 15:18:10 -0500250 continue
251 fi
252
253 yamls="\
254 $yamls \
255 $(find "$dir" -name '*.interface.yaml' -o -name '*.errors.yaml') \
256 "
257 done
258
259 # Sort YAMLs
260 yamls="$(echo "$yamls" | tr " " "\n" | sort)"
261
262 # Assign the YAML files into the hash-table by interface name.
Patrick Williams9ede18b2022-03-12 07:55:36 -0600263 for y in $yamls; do
Patrick Williams847a0c32020-06-24 15:18:10 -0500264 rel="$(realpath "--relative-to=$rootdir" "$y")"
265 dir="$(dirname "$rel")"
266 ext="${rel#*.}"
267 base="$(basename "$rel" ".$ext")"
Patrick Williamse4096f82022-03-14 16:07:50 -0500268 key="$dir/$base"
Patrick Williams847a0c32020-06-24 15:18:10 -0500269
Patrick Williamse4096f82022-03-14 16:07:50 -0500270 interfaces["$key"]="${interfaces[$key]} $ext"
Patrick Williams847a0c32020-06-24 15:18:10 -0500271 done
272
273 # Create the meson.build files.
274 meson_create_root
275 sorted_ifaces="$(echo "${!interfaces[@]}" | tr " " "\n" | sort)"
Patrick Williams9ede18b2022-03-12 07:55:36 -0600276 for i in ${sorted_ifaces}; do
Patrick Williams847a0c32020-06-24 15:18:10 -0500277 meson_create_path "$i"
278 meson_cpp_target "$i"
279 meson_md_target "$i"
280 done
281}
282
283## Handle command=cpp by calling sdbus++ as appropriate.
284## $1 - interface to generate.
285##
286## For an interface foo/bar, the outputdir is expected to be foo/bar.
287function cmd_cpp {
288
Patrick Williams9ede18b2022-03-12 07:55:36 -0600289 if [ "" == "$1" ]; then
Patrick Williams847a0c32020-06-24 15:18:10 -0500290 show_usage
291 exit 1
292 fi
293
Patrick Williams9ede18b2022-03-12 07:55:36 -0600294 if [ ! -e "$rootdir/$1.interface.yaml" ] &&
295 [ ! -e "$rootdir/$1.errors.yaml" ]; then
Patrick Williams847a0c32020-06-24 15:18:10 -0500296 echo "Missing YAML for $1."
297 exit 1
298 fi
299
300 mkdir -p "$outputdir"
301
302 sdbusppcmd="$sdbuspp -r $rootdir"
303 intf="${1//\//.}"
304
Patrick Williams9ede18b2022-03-12 07:55:36 -0600305 if [ -e "$rootdir/$1.interface.yaml" ]; then
Patrick Williams847a0c32020-06-24 15:18:10 -0500306 $sdbusppcmd interface server-header "$intf" > "$outputdir/server.hpp"
307 $sdbusppcmd interface server-cpp "$intf" > "$outputdir/server.cpp"
308 $sdbusppcmd interface client-header "$intf" > "$outputdir/client.hpp"
309 fi
310
Patrick Williams9ede18b2022-03-12 07:55:36 -0600311 if [ -e "$rootdir/$1.errors.yaml" ]; then
Patrick Williams847a0c32020-06-24 15:18:10 -0500312 $sdbusppcmd error exception-header "$intf" > "$outputdir/error.hpp"
313 $sdbusppcmd error exception-cpp "$intf" > "$outputdir/error.cpp"
314 fi
315}
316
317## Handle command=markdown by calling sdbus++ as appropriate.
318## $1 - interface to generate.
319##
320## For an interface foo/bar, the outputdir is expected to be foo.
321function cmd_markdown {
322
Patrick Williams9ede18b2022-03-12 07:55:36 -0600323 if [ "" == "$1" ]; then
Patrick Williams847a0c32020-06-24 15:18:10 -0500324 show_usage
325 exit 1
326 fi
327
Patrick Williams9ede18b2022-03-12 07:55:36 -0600328 if [ ! -e "$rootdir/$1.interface.yaml" ] &&
329 [ ! -e "$rootdir/$1.errors.yaml" ]; then
Patrick Williams847a0c32020-06-24 15:18:10 -0500330 echo "Missing YAML for $1."
331 exit 1
332 fi
333
334 mkdir -p "$outputdir"
335
336 sdbusppcmd="$sdbuspp -r $rootdir"
337 intf="${1//\//.}"
338 base="$(basename "$1")"
339
340 echo -n > "$outputdir/$base.md"
Patrick Williams9ede18b2022-03-12 07:55:36 -0600341 if [ -e "$rootdir/$1.interface.yaml" ]; then
Patrick Williams847a0c32020-06-24 15:18:10 -0500342 $sdbusppcmd interface markdown "$intf" >> "$outputdir/$base.md"
343 fi
344
Patrick Williams9ede18b2022-03-12 07:55:36 -0600345 if [ -e "$rootdir/$1.errors.yaml" ]; then
Patrick Williams847a0c32020-06-24 15:18:10 -0500346 $sdbusppcmd error markdown "$intf" >> "$outputdir/$base.md"
347 fi
348}
349
350## Handle command=version.
351function cmd_version {
352 show_version
353}
354
355"cmd_$cmd" "$*"