blob: e2da6ebe26fd3ae4d9ab71826627cc383940dce0 [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 \
11<<EOF
12Usage: $(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
54while true;
55do
56 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 ;;
95 esac
96done
97
98## Create an initially empty meson.build file.
99## $1 - path to create meson.build at.
100function meson_empty_file {
101 mkdir -p "$1"
102 echo "# Generated file; do not modify." > "$1/meson.build"
103}
104
105## Create the root-level meson.build
106##
107## Inserts rules to run the available version of this tool to ensure the
108## version has not changed.
109function meson_create_root {
110 meson_empty_file "$outputdir"
111
112 cat >> "$outputdir/meson.build" \
113<<EOF
114sdbuspp_gen_meson_ver = run_command(
115 sdbuspp_gen_meson_prog,
116 '--version',
117).stdout().strip().split('\n')[0]
118
119if sdbuspp_gen_meson_ver != '$tool_version'
120 warning('Generated meson files from wrong version of sdbus++-gen-meson.')
121 warning(
122 'Expected "$tool_version", got:',
123 sdbuspp_gen_meson_ver
124 )
125endif
126
127EOF
128}
129
130## hash-tables to store:
131## meson_paths - list of subdirectory paths for which an empty meson.build
132## has already been created.
133## interfaces - list of interface paths which a YAML has been found and
134## which YAML types (interface, errors, etc.).
135declare -A meson_paths
136declare -A interfaces
137
138## Ensure the meson.build files to a path have been created.
139## $1 - The path requiring to be created.
140function meson_create_path {
141
142 meson_path="$outputdir"
143 prev_meson_path=""
144
145 # Split the path into segments.
146 for part in $(echo "$1" | tr '/' '\n');
147 do
148 prev_meson_path="$meson_path"
149 meson_path="$meson_path/$part"
150
151 # Create the meson.build for this segment if it doesn't already exist.
152 if [ "x" == "x${meson_paths[$meson_path]}" ];
153 then
154 meson_paths["$meson_path"]="1"
155 meson_empty_file "$meson_path"
156
157 # Add the 'subdir' link into the parent's meson.build.
158 # We need to skip adding the links into the 'root' meson.build
159 # because most repositories want to selectively add TLDs based
160 # on config flags. Let them figure out their own logic for that.
161 if [ "x$outputdir" != "x$prev_meson_path" ];
162 then
163 echo "subdir('$part')" >> "$prev_meson_path/meson.build"
164 fi
165 fi
166 done
167}
168
169## Generate the meson target for the source files (.cpp/.hpp) from a YAML
170## interface.
171##
172## $1 - The interface to generate a target for.
173function meson_cpp_target {
William A. Kennington III56eb1772021-05-18 20:41:26 -0700174 mesondir="$outputdir/$1"
175 yamldir="$(realpath --relative-to="$mesondir" "$rootdir")"
Patrick Williams847a0c32020-06-24 15:18:10 -0500176
177 # Determine the source and output files based on the YAMLs present.
178 sources=""
179 outputs=""
180 for s in ${interfaces[$1]};
181 do
William A. Kennington III56eb1772021-05-18 20:41:26 -0700182 sources="'$yamldir/$1.$s', "
Patrick Williams847a0c32020-06-24 15:18:10 -0500183
184 case "$s" in
185 errors.yaml)
186 outputs="${outputs}'error.cpp', 'error.hpp', "
187 ;;
188
189 interface.yaml)
190 outputs="${outputs}'server.cpp', 'server.hpp', "
191 outputs="${outputs}'client.hpp', "
192 ;;
193 esac
194 done
195
196 # Create the target to generate the 'outputs'.
William A. Kennington III56eb1772021-05-18 20:41:26 -0700197 cat >> "$mesondir/meson.build" \
Patrick Williams847a0c32020-06-24 15:18:10 -0500198<<EOF
199generated_sources += custom_target(
200 '$1__cpp'.underscorify(),
201 input: [ $sources ],
202 output: [ $outputs ],
203 command: [
204 sdbuspp_gen_meson_prog, '--command', 'cpp',
205 '--output', meson.current_build_dir(),
206 '--tool', sdbusplusplus_prog,
William A. Kennington III56eb1772021-05-18 20:41:26 -0700207 '--directory', meson.current_source_dir() / '$yamldir',
Patrick Williams847a0c32020-06-24 15:18:10 -0500208 '$1',
209 ],
210)
211
212EOF
213}
214
215## Generate the meson target for the markdown files from a YAML interface.
216## $1 - The interface to generate a target for.
217function meson_md_target {
William A. Kennington III56eb1772021-05-18 20:41:26 -0700218 mesondir="$outputdir/$(dirname "$1")"
219 yamldir="$(realpath --relative-to="$mesondir" "$rootdir")"
Patrick Williams847a0c32020-06-24 15:18:10 -0500220
221 # Determine the source files based on the YAMLs present.
222 sources=""
223 for s in ${interfaces[$1]};
224 do
William A. Kennington III56eb1772021-05-18 20:41:26 -0700225 sources="'$yamldir/$1.$s', "
Patrick Williams847a0c32020-06-24 15:18:10 -0500226 done
227
228 # Create the target to generate the interface.md file.
William A. Kennington III56eb1772021-05-18 20:41:26 -0700229 cat >> "$mesondir/meson.build" \
Patrick Williams847a0c32020-06-24 15:18:10 -0500230<<EOF
231generated_others += custom_target(
232 '$1__markdown'.underscorify(),
233 input: [ $sources ],
234 output: [ '$(basename "$1").md' ],
235 command: [
236 sdbuspp_gen_meson_prog, '--command', 'markdown',
237 '--output', meson.current_build_dir(),
238 '--tool', sdbusplusplus_prog,
William A. Kennington III56eb1772021-05-18 20:41:26 -0700239 '--directory', meson.current_source_dir() / '$yamldir',
Patrick Williams847a0c32020-06-24 15:18:10 -0500240 '$1',
241 ],
Patrick Williams847a0c32020-06-24 15:18:10 -0500242)
243
244EOF
245}
246
247## Handle command=meson by generating the tree of meson.build files.
248function cmd_meson {
249 TLDs="com net org xyz"
250 yamls=""
251
252 # Find all the YAML files in the TLD subdirectories.
253 for d in $TLDs;
254 do
255 dir="$rootdir/$d"
256 if [ ! -d "$dir" ];
257 then
258 continue
259 fi
260
261 yamls="\
262 $yamls \
263 $(find "$dir" -name '*.interface.yaml' -o -name '*.errors.yaml') \
264 "
265 done
266
267 # Sort YAMLs
268 yamls="$(echo "$yamls" | tr " " "\n" | sort)"
269
270 # Assign the YAML files into the hash-table by interface name.
271 for y in $yamls;
272 do
273 rel="$(realpath "--relative-to=$rootdir" "$y")"
274 dir="$(dirname "$rel")"
275 ext="${rel#*.}"
276 base="$(basename "$rel" ".$ext")"
277
278 interfaces["$dir/$base"]="${interfaces[$dir/$base]} $ext"
279 done
280
281 # Create the meson.build files.
282 meson_create_root
283 sorted_ifaces="$(echo "${!interfaces[@]}" | tr " " "\n" | sort)"
284 for i in ${sorted_ifaces};
285 do
286 meson_create_path "$i"
287 meson_cpp_target "$i"
288 meson_md_target "$i"
289 done
290}
291
292## Handle command=cpp by calling sdbus++ as appropriate.
293## $1 - interface to generate.
294##
295## For an interface foo/bar, the outputdir is expected to be foo/bar.
296function cmd_cpp {
297
298 if [ "x" == "x$1" ];
299 then
300 show_usage
301 exit 1
302 fi
303
304 if [ ! -e "$rootdir/$1.interface.yaml" ] && \
305 [ ! -e "$rootdir/$1.errors.yaml" ];
306 then
307 echo "Missing YAML for $1."
308 exit 1
309 fi
310
311 mkdir -p "$outputdir"
312
313 sdbusppcmd="$sdbuspp -r $rootdir"
314 intf="${1//\//.}"
315
316 if [ -e "$rootdir/$1.interface.yaml" ];
317 then
318 $sdbusppcmd interface server-header "$intf" > "$outputdir/server.hpp"
319 $sdbusppcmd interface server-cpp "$intf" > "$outputdir/server.cpp"
320 $sdbusppcmd interface client-header "$intf" > "$outputdir/client.hpp"
321 fi
322
323 if [ -e "$rootdir/$1.errors.yaml" ];
324 then
325 $sdbusppcmd error exception-header "$intf" > "$outputdir/error.hpp"
326 $sdbusppcmd error exception-cpp "$intf" > "$outputdir/error.cpp"
327 fi
328}
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.
334function cmd_markdown {
335
336 if [ "x" == "x$1" ];
337 then
338 show_usage
339 exit 1
340 fi
341
342 if [ ! -e "$rootdir/$1.interface.yaml" ] && \
343 [ ! -e "$rootdir/$1.errors.yaml" ];
344 then
345 echo "Missing YAML for $1."
346 exit 1
347 fi
348
349 mkdir -p "$outputdir"
350
351 sdbusppcmd="$sdbuspp -r $rootdir"
352 intf="${1//\//.}"
353 base="$(basename "$1")"
354
355 echo -n > "$outputdir/$base.md"
356 if [ -e "$rootdir/$1.interface.yaml" ];
357 then
358 $sdbusppcmd interface markdown "$intf" >> "$outputdir/$base.md"
359 fi
360
361 if [ -e "$rootdir/$1.errors.yaml" ];
362 then
363 $sdbusppcmd error markdown "$intf" >> "$outputdir/$base.md"
364 fi
365}
366
367## Handle command=version.
368function cmd_version {
369 show_version
370}
371
372"cmd_$cmd" "$*"