xref: /openbmc/sdbusplus/tools/sdbus++-gen-meson (revision a4c9edc1)
1847a0c37SPatrick Williams#!/usr/bin/env bash
2847a0c37SPatrick Williams
3847a0c37SPatrick Williamsset -e
4847a0c37SPatrick Williams
5*a4c9edc1SPatrick Williams# Locale can change behavior of utilities like 'sort' but we want the output
6*a4c9edc1SPatrick Williams# to be stable on all machines.  Force the locale to 'C' for consistency.
7*a4c9edc1SPatrick Williamsexport LC_ALL=C
8*a4c9edc1SPatrick Williams
9847a0c37SPatrick 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.
39847a0c37SPatrick Williamstool_version="sdbus++-gen-meson version 1"
40847a0c37SPatrick Williamsfunction show_version {
41847a0c37SPatrick 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 -- "$@")"
52847a0c37SPatrick Williamseval set -- "$options"
53847a0c37SPatrick Williams
54847a0c37SPatrick Williamswhile true;
55847a0c37SPatrick Williamsdo
56847a0c37SPatrick Williams    case "$1" in
57847a0c37SPatrick Williams        -h | --help)
58847a0c37SPatrick Williams            show_usage
59847a0c37SPatrick Williams            exit
60847a0c37SPatrick Williams            ;;
61847a0c37SPatrick Williams
62847a0c37SPatrick Williams        -c | --command)
63847a0c37SPatrick Williams            shift
64847a0c37SPatrick Williams            cmd="$1"
65847a0c37SPatrick Williams            shift
66847a0c37SPatrick Williams            ;;
67847a0c37SPatrick Williams
68847a0c37SPatrick Williams        -d | --directory)
69847a0c37SPatrick Williams            shift
70847a0c37SPatrick Williams            rootdir="$1"
71847a0c37SPatrick Williams            shift
72847a0c37SPatrick Williams            ;;
73847a0c37SPatrick Williams
74847a0c37SPatrick Williams        -o | --output)
75847a0c37SPatrick Williams            shift
76847a0c37SPatrick Williams            outputdir="$1"
77847a0c37SPatrick Williams            shift
78847a0c37SPatrick Williams            ;;
79847a0c37SPatrick Williams
80847a0c37SPatrick Williams        -t | --tool)
81847a0c37SPatrick Williams            shift
82847a0c37SPatrick Williams            sdbuspp="$1"
83847a0c37SPatrick Williams            shift
84847a0c37SPatrick Williams            ;;
85847a0c37SPatrick Williams
86847a0c37SPatrick Williams        -v | --version)
87847a0c37SPatrick Williams            show_version
88847a0c37SPatrick Williams            exit
89847a0c37SPatrick Williams            ;;
90847a0c37SPatrick Williams
91847a0c37SPatrick Williams        --)
92847a0c37SPatrick Williams            shift
93847a0c37SPatrick Williams            break
94847a0c37SPatrick Williams            ;;
95847a0c37SPatrick Williams    esac
96847a0c37SPatrick Williamsdone
97847a0c37SPatrick Williams
98847a0c37SPatrick Williams## Create an initially empty meson.build file.
99847a0c37SPatrick Williams## $1 - path to create meson.build at.
100847a0c37SPatrick Williamsfunction meson_empty_file {
101847a0c37SPatrick Williams    mkdir -p "$1"
102847a0c37SPatrick Williams    echo "# Generated file; do not modify." > "$1/meson.build"
103847a0c37SPatrick Williams}
104847a0c37SPatrick Williams
105847a0c37SPatrick Williams## Create the root-level meson.build
106847a0c37SPatrick Williams##
107847a0c37SPatrick Williams## Inserts rules to run the available version of this tool to ensure the
108847a0c37SPatrick Williams## version has not changed.
109847a0c37SPatrick Williamsfunction meson_create_root {
110847a0c37SPatrick Williams    meson_empty_file "$outputdir"
111847a0c37SPatrick Williams
112847a0c37SPatrick Williams    cat >> "$outputdir/meson.build" \
113847a0c37SPatrick Williams<<EOF
114847a0c37SPatrick Williamssdbuspp_gen_meson_ver = run_command(
115847a0c37SPatrick Williams    sdbuspp_gen_meson_prog,
116847a0c37SPatrick Williams    '--version',
117847a0c37SPatrick Williams).stdout().strip().split('\n')[0]
118847a0c37SPatrick Williams
119847a0c37SPatrick Williamsif sdbuspp_gen_meson_ver != '$tool_version'
120847a0c37SPatrick Williams    warning('Generated meson files from wrong version of sdbus++-gen-meson.')
121847a0c37SPatrick Williams    warning(
122847a0c37SPatrick Williams        'Expected "$tool_version", got:',
123847a0c37SPatrick Williams        sdbuspp_gen_meson_ver
124847a0c37SPatrick Williams    )
125847a0c37SPatrick Williamsendif
126847a0c37SPatrick Williams
127847a0c37SPatrick WilliamsEOF
128847a0c37SPatrick Williams}
129847a0c37SPatrick Williams
130847a0c37SPatrick Williams## hash-tables to store:
131847a0c37SPatrick Williams##      meson_paths - list of subdirectory paths for which an empty meson.build
132847a0c37SPatrick Williams##                    has already been created.
133847a0c37SPatrick Williams##      interfaces - list of interface paths which a YAML has been found and
134847a0c37SPatrick Williams##                   which YAML types (interface, errors, etc.).
135847a0c37SPatrick Williamsdeclare -A meson_paths
136847a0c37SPatrick Williamsdeclare -A interfaces
137847a0c37SPatrick Williams
138847a0c37SPatrick Williams## Ensure the meson.build files to a path have been created.
139847a0c37SPatrick Williams## $1 - The path requiring to be created.
140847a0c37SPatrick Williamsfunction meson_create_path {
141847a0c37SPatrick Williams
142847a0c37SPatrick Williams    meson_path="$outputdir"
143847a0c37SPatrick Williams    prev_meson_path=""
144847a0c37SPatrick Williams
145847a0c37SPatrick Williams    # Split the path into segments.
146847a0c37SPatrick Williams    for part in $(echo "$1" | tr '/' '\n');
147847a0c37SPatrick Williams    do
148847a0c37SPatrick Williams        prev_meson_path="$meson_path"
149847a0c37SPatrick Williams        meson_path="$meson_path/$part"
150847a0c37SPatrick Williams
151847a0c37SPatrick Williams        # Create the meson.build for this segment if it doesn't already exist.
152847a0c37SPatrick Williams        if [ "x" == "x${meson_paths[$meson_path]}" ];
153847a0c37SPatrick Williams        then
154847a0c37SPatrick Williams            meson_paths["$meson_path"]="1"
155847a0c37SPatrick Williams            meson_empty_file "$meson_path"
156847a0c37SPatrick Williams
157847a0c37SPatrick Williams            # Add the 'subdir' link into the parent's meson.build.
158847a0c37SPatrick Williams            # We need to skip adding the links into the 'root' meson.build
159847a0c37SPatrick Williams            # because most repositories want to selectively add TLDs based
160847a0c37SPatrick Williams            # on config flags.  Let them figure out their own logic for that.
161847a0c37SPatrick Williams            if [ "x$outputdir" != "x$prev_meson_path" ];
162847a0c37SPatrick Williams            then
163847a0c37SPatrick Williams                echo "subdir('$part')" >> "$prev_meson_path/meson.build"
164847a0c37SPatrick Williams            fi
165847a0c37SPatrick Williams        fi
166847a0c37SPatrick Williams    done
167847a0c37SPatrick Williams}
168847a0c37SPatrick Williams
169847a0c37SPatrick Williams## Generate the meson target for the source files (.cpp/.hpp) from a YAML
170847a0c37SPatrick Williams## interface.
171847a0c37SPatrick Williams##
172847a0c37SPatrick Williams## $1 - The interface to generate a target for.
173847a0c37SPatrick Williamsfunction meson_cpp_target {
174847a0c37SPatrick Williams
175847a0c37SPatrick Williams    # Determine the source and output files based on the YAMLs present.
176847a0c37SPatrick Williams    sources=""
177847a0c37SPatrick Williams    outputs=""
178847a0c37SPatrick Williams    for s in ${interfaces[$1]};
179847a0c37SPatrick Williams    do
180847a0c37SPatrick Williams        sources="${sources}meson.source_root() / '$1.$s', "
181847a0c37SPatrick Williams
182847a0c37SPatrick Williams        case "$s" in
183847a0c37SPatrick Williams            errors.yaml)
184847a0c37SPatrick Williams                outputs="${outputs}'error.cpp', 'error.hpp', "
185847a0c37SPatrick Williams                ;;
186847a0c37SPatrick Williams
187847a0c37SPatrick Williams            interface.yaml)
188847a0c37SPatrick Williams                outputs="${outputs}'server.cpp', 'server.hpp', "
189847a0c37SPatrick Williams                outputs="${outputs}'client.hpp', "
190847a0c37SPatrick Williams                ;;
191847a0c37SPatrick Williams        esac
192847a0c37SPatrick Williams    done
193847a0c37SPatrick Williams
194847a0c37SPatrick Williams    # Create the target to generate the 'outputs'.
195847a0c37SPatrick Williams    cat >> "$outputdir/$1/meson.build" \
196847a0c37SPatrick Williams<<EOF
197847a0c37SPatrick Williamsgenerated_sources += custom_target(
198847a0c37SPatrick Williams    '$1__cpp'.underscorify(),
199847a0c37SPatrick Williams    input: [ $sources ],
200847a0c37SPatrick Williams    output: [ $outputs ],
201847a0c37SPatrick Williams    command: [
202847a0c37SPatrick Williams        sdbuspp_gen_meson_prog, '--command', 'cpp',
203847a0c37SPatrick Williams        '--output', meson.current_build_dir(),
204847a0c37SPatrick Williams        '--tool', sdbusplusplus_prog,
205847a0c37SPatrick Williams        '--directory', meson.source_root(),
206847a0c37SPatrick Williams        '$1',
207847a0c37SPatrick Williams    ],
208847a0c37SPatrick Williams)
209847a0c37SPatrick Williams
210847a0c37SPatrick WilliamsEOF
211847a0c37SPatrick Williams}
212847a0c37SPatrick Williams
213847a0c37SPatrick Williams## Generate the meson target for the markdown files from a YAML interface.
214847a0c37SPatrick Williams## $1 - The interface to generate a target for.
215847a0c37SPatrick Williamsfunction meson_md_target {
216847a0c37SPatrick Williams
217847a0c37SPatrick Williams    # Determine the source files based on the YAMLs present.
218847a0c37SPatrick Williams    sources=""
219847a0c37SPatrick Williams    for s in ${interfaces[$1]};
220847a0c37SPatrick Williams    do
221847a0c37SPatrick Williams        sources="${sources}meson.source_root() / '$1.$s', "
222847a0c37SPatrick Williams    done
223847a0c37SPatrick Williams
224847a0c37SPatrick Williams    # Create the target to generate the interface.md file.
225847a0c37SPatrick Williams    cat >> "$outputdir/$(dirname "$1")/meson.build" \
226847a0c37SPatrick Williams<<EOF
227847a0c37SPatrick Williamsgenerated_others += custom_target(
228847a0c37SPatrick Williams    '$1__markdown'.underscorify(),
229847a0c37SPatrick Williams    input: [ $sources ],
230847a0c37SPatrick Williams    output: [ '$(basename "$1").md' ],
231847a0c37SPatrick Williams    command: [
232847a0c37SPatrick Williams        sdbuspp_gen_meson_prog, '--command', 'markdown',
233847a0c37SPatrick Williams        '--output', meson.current_build_dir(),
234847a0c37SPatrick Williams        '--tool', sdbusplusplus_prog,
235847a0c37SPatrick Williams        '--directory', meson.source_root(),
236847a0c37SPatrick Williams        '$1',
237847a0c37SPatrick Williams    ],
238847a0c37SPatrick Williams    build_by_default: true,
239847a0c37SPatrick Williams)
240847a0c37SPatrick Williams
241847a0c37SPatrick WilliamsEOF
242847a0c37SPatrick Williams}
243847a0c37SPatrick Williams
244847a0c37SPatrick Williams## Handle command=meson by generating the tree of meson.build files.
245847a0c37SPatrick Williamsfunction cmd_meson {
246847a0c37SPatrick Williams    TLDs="com net org xyz"
247847a0c37SPatrick Williams    yamls=""
248847a0c37SPatrick Williams
249847a0c37SPatrick Williams    # Find all the YAML files in the TLD subdirectories.
250847a0c37SPatrick Williams    for d in $TLDs;
251847a0c37SPatrick Williams    do
252847a0c37SPatrick Williams        dir="$rootdir/$d"
253847a0c37SPatrick Williams        if [ ! -d "$dir" ];
254847a0c37SPatrick Williams        then
255847a0c37SPatrick Williams            continue
256847a0c37SPatrick Williams        fi
257847a0c37SPatrick Williams
258847a0c37SPatrick Williams        yamls="\
259847a0c37SPatrick Williams            $yamls \
260847a0c37SPatrick Williams            $(find "$dir" -name '*.interface.yaml' -o -name '*.errors.yaml') \
261847a0c37SPatrick Williams            "
262847a0c37SPatrick Williams    done
263847a0c37SPatrick Williams
264847a0c37SPatrick Williams    # Sort YAMLs
265847a0c37SPatrick Williams    yamls="$(echo "$yamls" | tr " " "\n" | sort)"
266847a0c37SPatrick Williams
267847a0c37SPatrick Williams    # Assign the YAML files into the hash-table by interface name.
268847a0c37SPatrick Williams    for y in $yamls;
269847a0c37SPatrick Williams    do
270847a0c37SPatrick Williams        rel="$(realpath "--relative-to=$rootdir" "$y")"
271847a0c37SPatrick Williams        dir="$(dirname "$rel")"
272847a0c37SPatrick Williams        ext="${rel#*.}"
273847a0c37SPatrick Williams        base="$(basename "$rel" ".$ext")"
274847a0c37SPatrick Williams
275847a0c37SPatrick Williams        interfaces["$dir/$base"]="${interfaces[$dir/$base]} $ext"
276847a0c37SPatrick Williams    done
277847a0c37SPatrick Williams
278847a0c37SPatrick Williams    # Create the meson.build files.
279847a0c37SPatrick Williams    meson_create_root
280847a0c37SPatrick Williams    sorted_ifaces="$(echo "${!interfaces[@]}" | tr " " "\n" | sort)"
281847a0c37SPatrick Williams    for i in ${sorted_ifaces};
282847a0c37SPatrick Williams    do
283847a0c37SPatrick Williams        meson_create_path "$i"
284847a0c37SPatrick Williams        meson_cpp_target "$i"
285847a0c37SPatrick Williams        meson_md_target "$i"
286847a0c37SPatrick Williams    done
287847a0c37SPatrick Williams}
288847a0c37SPatrick Williams
289847a0c37SPatrick Williams## Handle command=cpp by calling sdbus++ as appropriate.
290847a0c37SPatrick Williams## $1 - interface to generate.
291847a0c37SPatrick Williams##
292847a0c37SPatrick Williams## For an interface foo/bar, the outputdir is expected to be foo/bar.
293847a0c37SPatrick Williamsfunction cmd_cpp {
294847a0c37SPatrick Williams
295847a0c37SPatrick Williams    if [ "x" == "x$1" ];
296847a0c37SPatrick Williams    then
297847a0c37SPatrick Williams        show_usage
298847a0c37SPatrick Williams        exit 1
299847a0c37SPatrick Williams    fi
300847a0c37SPatrick Williams
301847a0c37SPatrick Williams    if [ ! -e "$rootdir/$1.interface.yaml" ] && \
302847a0c37SPatrick Williams        [ ! -e "$rootdir/$1.errors.yaml" ];
303847a0c37SPatrick Williams    then
304847a0c37SPatrick Williams        echo "Missing YAML for $1."
305847a0c37SPatrick Williams        exit 1
306847a0c37SPatrick Williams    fi
307847a0c37SPatrick Williams
308847a0c37SPatrick Williams    mkdir -p "$outputdir"
309847a0c37SPatrick Williams
310847a0c37SPatrick Williams    sdbusppcmd="$sdbuspp -r $rootdir"
311847a0c37SPatrick Williams    intf="${1//\//.}"
312847a0c37SPatrick Williams
313847a0c37SPatrick Williams    if [ -e "$rootdir/$1.interface.yaml" ];
314847a0c37SPatrick Williams    then
315847a0c37SPatrick Williams        $sdbusppcmd interface server-header "$intf" > "$outputdir/server.hpp"
316847a0c37SPatrick Williams        $sdbusppcmd interface server-cpp "$intf" > "$outputdir/server.cpp"
317847a0c37SPatrick Williams        $sdbusppcmd interface client-header "$intf" > "$outputdir/client.hpp"
318847a0c37SPatrick Williams    fi
319847a0c37SPatrick Williams
320847a0c37SPatrick Williams    if [ -e "$rootdir/$1.errors.yaml" ];
321847a0c37SPatrick Williams    then
322847a0c37SPatrick Williams        $sdbusppcmd error exception-header "$intf" > "$outputdir/error.hpp"
323847a0c37SPatrick Williams        $sdbusppcmd error exception-cpp "$intf" > "$outputdir/error.cpp"
324847a0c37SPatrick Williams    fi
325847a0c37SPatrick Williams}
326847a0c37SPatrick Williams
327847a0c37SPatrick Williams## Handle command=markdown by calling sdbus++ as appropriate.
328847a0c37SPatrick Williams## $1 - interface to generate.
329847a0c37SPatrick Williams##
330847a0c37SPatrick Williams## For an interface foo/bar, the outputdir is expected to be foo.
331847a0c37SPatrick Williamsfunction cmd_markdown {
332847a0c37SPatrick Williams
333847a0c37SPatrick Williams    if [ "x" == "x$1" ];
334847a0c37SPatrick Williams    then
335847a0c37SPatrick Williams        show_usage
336847a0c37SPatrick Williams        exit 1
337847a0c37SPatrick Williams    fi
338847a0c37SPatrick Williams
339847a0c37SPatrick Williams    if [ ! -e "$rootdir/$1.interface.yaml" ] && \
340847a0c37SPatrick Williams        [ ! -e "$rootdir/$1.errors.yaml" ];
341847a0c37SPatrick Williams    then
342847a0c37SPatrick Williams        echo "Missing YAML for $1."
343847a0c37SPatrick Williams        exit 1
344847a0c37SPatrick Williams    fi
345847a0c37SPatrick Williams
346847a0c37SPatrick Williams    mkdir -p "$outputdir"
347847a0c37SPatrick Williams
348847a0c37SPatrick Williams    sdbusppcmd="$sdbuspp -r $rootdir"
349847a0c37SPatrick Williams    intf="${1//\//.}"
350847a0c37SPatrick Williams    base="$(basename "$1")"
351847a0c37SPatrick Williams
352847a0c37SPatrick Williams    echo -n > "$outputdir/$base.md"
353847a0c37SPatrick Williams    if [ -e "$rootdir/$1.interface.yaml" ];
354847a0c37SPatrick Williams    then
355847a0c37SPatrick Williams        $sdbusppcmd interface markdown "$intf" >> "$outputdir/$base.md"
356847a0c37SPatrick Williams    fi
357847a0c37SPatrick Williams
358847a0c37SPatrick Williams    if [ -e "$rootdir/$1.errors.yaml" ];
359847a0c37SPatrick Williams    then
360847a0c37SPatrick Williams        $sdbusppcmd error markdown "$intf" >> "$outputdir/$base.md"
361847a0c37SPatrick Williams    fi
362847a0c37SPatrick Williams}
363847a0c37SPatrick Williams
364847a0c37SPatrick Williams## Handle command=version.
365847a0c37SPatrick Williamsfunction cmd_version {
366847a0c37SPatrick Williams    show_version
367847a0c37SPatrick Williams}
368847a0c37SPatrick Williams
369847a0c37SPatrick Williams"cmd_$cmd" "$*"
370