xref: /openbmc/sdbusplus/tools/sdbus++-gen-meson (revision 0ac157a0)
1847a0c37SPatrick Williams#!/usr/bin/env bash
2847a0c37SPatrick Williams
3847a0c37SPatrick Williamsset -e
4847a0c37SPatrick Williams
5a4c9edc1SPatrick Williams# Locale can change behavior of utilities like 'sort' but we want the output
6a4c9edc1SPatrick Williams# to be stable on all machines.  Force the locale to 'C' for consistency.
7a4c9edc1SPatrick Williamsexport LC_ALL=C
8a4c9edc1SPatrick Williams
9018b8ff1SPatrick 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.
39*0ac157a0SPatrick Williamstool_version="sdbus++-gen-meson version 9"
40018b8ff1SPatrick Williamsfunction show_version() {
41d77548a1SPatrick 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 -- "$@")"
52d77548a1SPatrick Williamseval set -- "${options}"
53847a0c37SPatrick Williams
549ede18b4SPatrick Williamswhile true; do
55847a0c37SPatrick Williams    case "$1" in
56847a0c37SPatrick Williams        -h | --help)
57847a0c37SPatrick Williams            show_usage
58847a0c37SPatrick Williams            exit
59847a0c37SPatrick Williams            ;;
60847a0c37SPatrick Williams
61847a0c37SPatrick Williams        -c | --command)
62847a0c37SPatrick Williams            shift
63847a0c37SPatrick Williams            cmd="$1"
64847a0c37SPatrick Williams            shift
65847a0c37SPatrick Williams            ;;
66847a0c37SPatrick Williams
67847a0c37SPatrick Williams        -d | --directory)
68847a0c37SPatrick Williams            shift
69847a0c37SPatrick Williams            rootdir="$1"
70847a0c37SPatrick Williams            shift
71847a0c37SPatrick Williams            ;;
72847a0c37SPatrick Williams
73847a0c37SPatrick Williams        -o | --output)
74847a0c37SPatrick Williams            shift
75847a0c37SPatrick Williams            outputdir="$1"
76847a0c37SPatrick Williams            shift
77847a0c37SPatrick Williams            ;;
78847a0c37SPatrick Williams
79847a0c37SPatrick Williams        -t | --tool)
80847a0c37SPatrick Williams            shift
81847a0c37SPatrick Williams            sdbuspp="$1"
82847a0c37SPatrick Williams            shift
83847a0c37SPatrick Williams            ;;
84847a0c37SPatrick Williams
85847a0c37SPatrick Williams        -v | --version)
86847a0c37SPatrick Williams            show_version
87847a0c37SPatrick Williams            exit
88847a0c37SPatrick Williams            ;;
89847a0c37SPatrick Williams
90847a0c37SPatrick Williams        --)
91847a0c37SPatrick Williams            shift
92847a0c37SPatrick Williams            break
93847a0c37SPatrick Williams            ;;
94d77548a1SPatrick Williams
95d77548a1SPatrick Williams        *)
96d77548a1SPatrick Williams            echo "Invalid argument $1"
97d77548a1SPatrick Williams            exit 1
98d77548a1SPatrick Williams            ;;
99847a0c37SPatrick Williams    esac
100847a0c37SPatrick Williamsdone
101847a0c37SPatrick Williams
102847a0c37SPatrick Williams## Create an initially empty meson.build file.
103847a0c37SPatrick Williams## $1 - path to create meson.build at.
104018b8ff1SPatrick Williamsfunction meson_empty_file() {
105847a0c37SPatrick Williams    mkdir -p "$1"
106847a0c37SPatrick Williams    echo "# Generated file; do not modify." > "$1/meson.build"
107847a0c37SPatrick Williams}
108847a0c37SPatrick Williams
109847a0c37SPatrick Williams## Create the root-level meson.build
110847a0c37SPatrick Williams##
111847a0c37SPatrick Williams## Inserts rules to run the available version of this tool to ensure the
112847a0c37SPatrick Williams## version has not changed.
113018b8ff1SPatrick Williamsfunction meson_create_root() {
114d77548a1SPatrick Williams    meson_empty_file "${outputdir}"
115847a0c37SPatrick Williams
116d77548a1SPatrick Williams    cat >> "${outputdir}/meson.build" \
117847a0c37SPatrick Williams        << EOF
118847a0c37SPatrick Williamssdbuspp_gen_meson_ver = run_command(
119847a0c37SPatrick Williams    sdbuspp_gen_meson_prog,
120847a0c37SPatrick Williams    '--version',
12160a94305SEd Tanous    check: true,
122847a0c37SPatrick Williams).stdout().strip().split('\n')[0]
123847a0c37SPatrick Williams
124d77548a1SPatrick Williamsif sdbuspp_gen_meson_ver != '${tool_version}'
125847a0c37SPatrick Williams    warning('Generated meson files from wrong version of sdbus++-gen-meson.')
126847a0c37SPatrick Williams    warning(
127d77548a1SPatrick Williams        'Expected "${tool_version}", got:',
128847a0c37SPatrick Williams        sdbuspp_gen_meson_ver
129847a0c37SPatrick Williams    )
130847a0c37SPatrick Williamsendif
131847a0c37SPatrick Williams
132847a0c37SPatrick WilliamsEOF
133847a0c37SPatrick Williams}
134847a0c37SPatrick Williams
135847a0c37SPatrick Williams## hash-tables to store:
136847a0c37SPatrick Williams##      meson_paths - list of subdirectory paths for which an empty meson.build
137847a0c37SPatrick Williams##                    has already been created.
138847a0c37SPatrick Williams##      interfaces - list of interface paths which a YAML has been found and
139847a0c37SPatrick Williams##                   which YAML types (interface, errors, etc.).
140847a0c37SPatrick Williamsdeclare -A meson_paths
141847a0c37SPatrick Williamsdeclare -A interfaces
142847a0c37SPatrick Williams
143847a0c37SPatrick Williams## Ensure the meson.build files to a path have been created.
144847a0c37SPatrick Williams## $1 - The path requiring to be created.
145018b8ff1SPatrick Williamsfunction meson_create_path() {
146847a0c37SPatrick Williams
147d77548a1SPatrick Williams    meson_path="${outputdir}"
148847a0c37SPatrick Williams    prev_meson_path=""
149847a0c37SPatrick Williams
150847a0c37SPatrick Williams    # Split the path into segments.
1519ede18b4SPatrick Williams    for part in $(echo "$1" | tr '/' '\n'); do
152d77548a1SPatrick Williams        prev_meson_path="${meson_path}"
153d77548a1SPatrick Williams        meson_path="${meson_path}/${part}"
154847a0c37SPatrick Williams
155847a0c37SPatrick Williams        # Create the meson.build for this segment if it doesn't already exist.
156d77548a1SPatrick Williams        if [[ "" == "${meson_paths[${meson_path}]}" ]]; then
157d77548a1SPatrick Williams            meson_paths["${meson_path}"]="1"
158d77548a1SPatrick Williams            meson_empty_file "${meson_path}"
159847a0c37SPatrick Williams
160847a0c37SPatrick Williams            # Add the 'subdir' link into the parent's meson.build.
161847a0c37SPatrick Williams            # We need to skip adding the links into the 'root' meson.build
162847a0c37SPatrick Williams            # because most repositories want to selectively add TLDs based
163847a0c37SPatrick Williams            # on config flags.  Let them figure out their own logic for that.
164d77548a1SPatrick Williams            if [[ ${outputdir} != "${prev_meson_path}" ]]; then
165d77548a1SPatrick Williams                echo "subdir('${part}')" >> "${prev_meson_path}/meson.build"
166847a0c37SPatrick Williams            fi
167847a0c37SPatrick Williams        fi
168847a0c37SPatrick Williams    done
169847a0c37SPatrick Williams}
170847a0c37SPatrick Williams
171847a0c37SPatrick Williams## Generate the meson target for the source files (.cpp/.hpp) from a YAML
172847a0c37SPatrick Williams## interface.
173847a0c37SPatrick Williams##
174847a0c37SPatrick Williams## $1 - The interface to generate a target for.
175018b8ff1SPatrick Williamsfunction meson_cpp_target() {
176d77548a1SPatrick Williams    mesondir="${outputdir}/$1"
177d77548a1SPatrick Williams    yamldir="$(realpath --relative-to="${mesondir}" "${rootdir}")"
178847a0c37SPatrick Williams
179847a0c37SPatrick Williams    # Determine the source and output files based on the YAMLs present.
180847a0c37SPatrick Williams    sources=""
181847a0c37SPatrick Williams    outputs=""
1829ede18b4SPatrick Williams    for s in ${interfaces[$1]}; do
183*0ac157a0SPatrick Williams        sources="${sources}'${yamldir}/$1.${s}', "
184847a0c37SPatrick Williams
185d77548a1SPatrick Williams        case "${s}" in
186847a0c37SPatrick Williams            errors.yaml)
187847a0c37SPatrick Williams                outputs="${outputs}'error.cpp', 'error.hpp', "
188847a0c37SPatrick Williams                ;;
189847a0c37SPatrick Williams
1900336a2fcSPatrick Williams            events.yaml)
1910336a2fcSPatrick Williams                outputs="${outputs}'event.cpp', 'event.hpp', "
1920336a2fcSPatrick Williams                ;;
1930336a2fcSPatrick Williams
194847a0c37SPatrick Williams            interface.yaml)
1951caa5e8aSPatrick Williams                outputs="${outputs}'common.hpp', "
196847a0c37SPatrick Williams                outputs="${outputs}'server.cpp', 'server.hpp', "
1976403d56fSPatrick Williams                outputs="${outputs}'aserver.hpp', "
198847a0c37SPatrick Williams                outputs="${outputs}'client.hpp', "
199847a0c37SPatrick Williams                ;;
200d77548a1SPatrick Williams
201d77548a1SPatrick Williams            *)
202d77548a1SPatrick Williams                echo "Unknown interface type: ${s}"
203d77548a1SPatrick Williams                exit 1
204d77548a1SPatrick Williams                ;;
205847a0c37SPatrick Williams        esac
206847a0c37SPatrick Williams    done
207847a0c37SPatrick Williams
208847a0c37SPatrick Williams    # Create the target to generate the 'outputs'.
209d77548a1SPatrick Williams    cat >> "${mesondir}/meson.build" \
210847a0c37SPatrick Williams        << EOF
211847a0c37SPatrick Williamsgenerated_sources += custom_target(
212847a0c37SPatrick Williams    '$1__cpp'.underscorify(),
213d77548a1SPatrick Williams    input: [ ${sources} ],
214d77548a1SPatrick Williams    output: [ ${outputs} ],
215293c8a26SWilliam A. Kennington III    depend_files: sdbusplusplus_depfiles,
216847a0c37SPatrick Williams    command: [
217847a0c37SPatrick Williams        sdbuspp_gen_meson_prog, '--command', 'cpp',
218847a0c37SPatrick Williams        '--output', meson.current_build_dir(),
219847a0c37SPatrick Williams        '--tool', sdbusplusplus_prog,
220d77548a1SPatrick Williams        '--directory', meson.current_source_dir() / '${yamldir}',
221847a0c37SPatrick Williams        '$1',
222847a0c37SPatrick Williams    ],
223847a0c37SPatrick Williams)
224847a0c37SPatrick Williams
225847a0c37SPatrick WilliamsEOF
226847a0c37SPatrick Williams}
227847a0c37SPatrick Williams
228847a0c37SPatrick Williams## Generate the meson target for the markdown files from a YAML interface.
229847a0c37SPatrick Williams## $1 - The interface to generate a target for.
230018b8ff1SPatrick Williamsfunction meson_md_target() {
231d77548a1SPatrick Williams    mesondir="${outputdir}/$(dirname "$1")"
232d77548a1SPatrick Williams    yamldir="$(realpath --relative-to="${mesondir}" "${rootdir}")"
233847a0c37SPatrick Williams
234847a0c37SPatrick Williams    # Determine the source files based on the YAMLs present.
235847a0c37SPatrick Williams    sources=""
2369ede18b4SPatrick Williams    for s in ${interfaces[$1]}; do
2375800d079SPatrick Williams        sources="${sources}'${yamldir}/$1.${s}', "
238847a0c37SPatrick Williams    done
239847a0c37SPatrick Williams
240847a0c37SPatrick Williams    # Create the target to generate the interface.md file.
241d77548a1SPatrick Williams    cat >> "${mesondir}/meson.build" \
242847a0c37SPatrick Williams        << EOF
243847a0c37SPatrick Williamsgenerated_others += custom_target(
244847a0c37SPatrick Williams    '$1__markdown'.underscorify(),
245d77548a1SPatrick Williams    input: [ ${sources} ],
246847a0c37SPatrick Williams    output: [ '$(basename "$1").md' ],
247293c8a26SWilliam A. Kennington III    depend_files: sdbusplusplus_depfiles,
248847a0c37SPatrick Williams    command: [
249847a0c37SPatrick Williams        sdbuspp_gen_meson_prog, '--command', 'markdown',
250847a0c37SPatrick Williams        '--output', meson.current_build_dir(),
251847a0c37SPatrick Williams        '--tool', sdbusplusplus_prog,
252d77548a1SPatrick Williams        '--directory', meson.current_source_dir() / '${yamldir}',
253847a0c37SPatrick Williams        '$1',
254847a0c37SPatrick Williams    ],
255847a0c37SPatrick Williams)
256847a0c37SPatrick Williams
257847a0c37SPatrick WilliamsEOF
258847a0c37SPatrick Williams}
259847a0c37SPatrick Williams
260847a0c37SPatrick Williams## Handle command=meson by generating the tree of meson.build files.
261018b8ff1SPatrick Williamsfunction cmd_meson() {
262ce8d16d9SWillam A. Kennington III    # Find and sort all the YAML files
2630336a2fcSPatrick Williams    yamls="$(find "${rootdir}" -name '*.interface.yaml' -o -name '*.errors.yaml' -o -name '*.events.yaml')"
264ce8d16d9SWillam A. Kennington III    yamls="$(echo "${yamls}" | sort)"
265847a0c37SPatrick Williams
266847a0c37SPatrick Williams    # Assign the YAML files into the hash-table by interface name.
267d77548a1SPatrick Williams    for y in ${yamls}; do
268d77548a1SPatrick Williams        rel="$(realpath "--relative-to=${rootdir}" "${y}")"
269d77548a1SPatrick Williams        dir="$(dirname "${rel}")"
270847a0c37SPatrick Williams        ext="${rel#*.}"
271d77548a1SPatrick Williams        base="$(basename "${rel}" ".${ext}")"
272d77548a1SPatrick Williams        key="${dir}/${base}"
273847a0c37SPatrick Williams
274d77548a1SPatrick Williams        interfaces["${key}"]="${interfaces[${key}]} ${ext}"
275847a0c37SPatrick Williams    done
276847a0c37SPatrick Williams
277847a0c37SPatrick Williams    # Create the meson.build files.
278847a0c37SPatrick Williams    meson_create_root
279d77548a1SPatrick Williams    # shellcheck disable=SC2312
280847a0c37SPatrick Williams    sorted_ifaces="$(echo "${!interfaces[@]}" | tr " " "\n" | sort)"
2819ede18b4SPatrick Williams    for i in ${sorted_ifaces}; do
282d77548a1SPatrick Williams        meson_create_path "${i}"
283d77548a1SPatrick Williams        meson_cpp_target "${i}"
284d77548a1SPatrick Williams        meson_md_target "${i}"
285847a0c37SPatrick Williams    done
286847a0c37SPatrick Williams}
287847a0c37SPatrick Williams
288847a0c37SPatrick Williams## Handle command=cpp by calling sdbus++ as appropriate.
289847a0c37SPatrick Williams## $1 - interface to generate.
290847a0c37SPatrick Williams##
291847a0c37SPatrick Williams## For an interface foo/bar, the outputdir is expected to be foo/bar.
292018b8ff1SPatrick Williamsfunction cmd_cpp() {
293847a0c37SPatrick Williams
294d77548a1SPatrick Williams    if [[ "" == "$1" ]]; then
295847a0c37SPatrick Williams        show_usage
296847a0c37SPatrick Williams        exit 1
297847a0c37SPatrick Williams    fi
298847a0c37SPatrick Williams
299d77548a1SPatrick Williams    if [[ ! -e "${rootdir}/$1.interface.yaml" ]] &&
3000336a2fcSPatrick Williams    [[ ! -e "${rootdir}/$1.errors.yaml" ]] &&
3010336a2fcSPatrick Williams    [[ ! -e "${rootdir}/$1.events.yaml" ]]; then
302847a0c37SPatrick Williams        echo "Missing YAML for $1."
303847a0c37SPatrick Williams        exit 1
304847a0c37SPatrick Williams    fi
305847a0c37SPatrick Williams
306d77548a1SPatrick Williams    mkdir -p "${outputdir}"
307847a0c37SPatrick Williams
308d77548a1SPatrick Williams    sdbusppcmd="${sdbuspp} -r ${rootdir}"
309847a0c37SPatrick Williams    intf="${1//\//.}"
310847a0c37SPatrick Williams
311d77548a1SPatrick Williams    if [[ -e "${rootdir}/$1.interface.yaml" ]]; then
3121caa5e8aSPatrick Williams        ${sdbusppcmd} interface common-header "${intf}" > "${outputdir}/common.hpp"
313d77548a1SPatrick Williams        ${sdbusppcmd} interface server-header "${intf}" > "${outputdir}/server.hpp"
314d77548a1SPatrick Williams        ${sdbusppcmd} interface server-cpp "${intf}" > "${outputdir}/server.cpp"
315d77548a1SPatrick Williams        ${sdbusppcmd} interface client-header "${intf}" > "${outputdir}/client.hpp"
3166403d56fSPatrick Williams        ${sdbusppcmd} interface aserver-header "${intf}" > "${outputdir}/aserver.hpp"
317847a0c37SPatrick Williams    fi
318847a0c37SPatrick Williams
319d77548a1SPatrick Williams    if [[ -e "${rootdir}/$1.errors.yaml" ]]; then
320d77548a1SPatrick Williams        ${sdbusppcmd} error exception-header "${intf}" > "${outputdir}/error.hpp"
321d77548a1SPatrick Williams        ${sdbusppcmd} error exception-cpp "${intf}" > "${outputdir}/error.cpp"
322847a0c37SPatrick Williams    fi
3230336a2fcSPatrick Williams
3240336a2fcSPatrick Williams    if [[ -e "${rootdir}/$1.events.yaml" ]]; then
3250336a2fcSPatrick Williams        ${sdbusppcmd} event exception-header "${intf}" > "${outputdir}/event.hpp"
3260336a2fcSPatrick Williams        ${sdbusppcmd} event exception-cpp "${intf}" > "${outputdir}/event.cpp"
3270336a2fcSPatrick Williams    fi
328847a0c37SPatrick Williams}
329847a0c37SPatrick Williams
330847a0c37SPatrick Williams## Handle command=markdown by calling sdbus++ as appropriate.
331847a0c37SPatrick Williams## $1 - interface to generate.
332847a0c37SPatrick Williams##
333847a0c37SPatrick Williams## For an interface foo/bar, the outputdir is expected to be foo.
334018b8ff1SPatrick Williamsfunction cmd_markdown() {
335847a0c37SPatrick Williams
336d77548a1SPatrick Williams    if [[ "" == "$1" ]]; then
337847a0c37SPatrick Williams        show_usage
338847a0c37SPatrick Williams        exit 1
339847a0c37SPatrick Williams    fi
340847a0c37SPatrick Williams
341d77548a1SPatrick Williams    if [[ ! -e "${rootdir}/$1.interface.yaml" ]] &&
3420336a2fcSPatrick Williams    [[ ! -e "${rootdir}/$1.errors.yaml" ]] &&
3430336a2fcSPatrick Williams    [[ ! -e "${rootdir}/$1.events.yaml" ]]; then
344847a0c37SPatrick Williams        echo "Missing YAML for $1."
345847a0c37SPatrick Williams        exit 1
346847a0c37SPatrick Williams    fi
347847a0c37SPatrick Williams
348d77548a1SPatrick Williams    mkdir -p "${outputdir}"
349847a0c37SPatrick Williams
350d77548a1SPatrick Williams    sdbusppcmd="${sdbuspp} -r ${rootdir}"
351847a0c37SPatrick Williams    intf="${1//\//.}"
352847a0c37SPatrick Williams    base="$(basename "$1")"
353847a0c37SPatrick Williams
354d77548a1SPatrick Williams    echo -n > "${outputdir}/${base}.md"
355d77548a1SPatrick Williams    if [[ -e "${rootdir}/$1.interface.yaml" ]]; then
356d77548a1SPatrick Williams        ${sdbusppcmd} interface markdown "${intf}" >> "${outputdir}/${base}.md"
357847a0c37SPatrick Williams    fi
358847a0c37SPatrick Williams
359d77548a1SPatrick Williams    if [[ -e "${rootdir}/$1.errors.yaml" ]]; then
360d77548a1SPatrick Williams        ${sdbusppcmd} error markdown "${intf}" >> "${outputdir}/${base}.md"
361847a0c37SPatrick Williams    fi
3620336a2fcSPatrick Williams
3630336a2fcSPatrick Williams    if [[ -e "${rootdir}/$1.events.yaml" ]]; then
3640336a2fcSPatrick Williams        ${sdbusppcmd} event markdown "${intf}" >> "${outputdir}/${base}.md"
3650336a2fcSPatrick Williams    fi
366847a0c37SPatrick Williams}
367847a0c37SPatrick Williams
368847a0c37SPatrick Williams## Handle command=version.
369018b8ff1SPatrick Williamsfunction cmd_version() {
370847a0c37SPatrick Williams    show_version
371847a0c37SPatrick Williams}
372847a0c37SPatrick Williams
373d77548a1SPatrick Williams"cmd_${cmd}" "$*"
374