sdbus++-gen-meson: leverage `install_dir` for custom targets

Meson has had a `install_dir` directive on `custom_target` which
allows specifying per-output where the file should be installed.
Leveraging this greatly simplifies the meson in consumers (such as
phosphor-dbus-interfaces) and makes the install less error-prone.

The previous method for installing was to use a `install_subdir`
call with large exclude lists (so that markdown did not end up in
the include tree).  The result of this was that many empty directories
were created in the include, markdown, and registry install paths.

Using this method reduces by 25% the meson content in
phosphor-dbus-interfaces.

Signed-off-by: Patrick Williams <patrick@stwcx.xyz>
Change-Id: I2b03116f517caa75de902ac7e44e6923d6652cad
diff --git a/example/gen/meson.build b/example/gen/meson.build
index 8d7d4de..ef27aee 100644
--- a/example/gen/meson.build
+++ b/example/gen/meson.build
@@ -13,3 +13,23 @@
     )
 endif
 
+inst_markdown_dir = get_option('datadir') / 'doc' / meson.project_name()
+inst_registry_dir = get_option('datadir') / 'redfish-registry' / meson.project_name()
+
+generated_sources = []
+generated_markdown = []
+generated_registry = []
+
+foreach d : yaml_selected_subdirs
+    subdir(d)
+endforeach
+
+generated_headers = []
+foreach s : generated_sources
+    foreach f : s.to_list()
+        if f.full_path().endswith('.hpp')
+            generated_headers += f
+        endif
+    endforeach
+endforeach
+
diff --git a/example/gen/net/poettering/Calculator/meson.build b/example/gen/net/poettering/Calculator/meson.build
index 1b4cc9b..82496e4 100644
--- a/example/gen/net/poettering/Calculator/meson.build
+++ b/example/gen/net/poettering/Calculator/meson.build
@@ -1,8 +1,22 @@
 # Generated file; do not modify.
+
+sdbusplus_current_path = 'net/poettering/Calculator'
+
 generated_sources += custom_target(
     'net/poettering/Calculator__cpp'.underscorify(),
-    input: [ '../../../../yaml/net/poettering/Calculator.events.yaml', '../../../../yaml/net/poettering/Calculator.interface.yaml',  ],
-    output: [ 'event.cpp', 'event.hpp', 'common.hpp', 'server.cpp', 'server.hpp', 'aserver.hpp', 'client.hpp',  ],
+    input: [
+        '../../../../yaml/net/poettering/Calculator.events.yaml',
+        '../../../../yaml/net/poettering/Calculator.interface.yaml',
+    ],
+    output: [
+        'event.cpp',
+        'event.hpp',
+        'common.hpp',
+        'server.hpp',
+        'server.cpp',
+        'aserver.hpp',
+        'client.hpp',
+    ],
     depend_files: sdbusplusplus_depfiles,
     command: [
         sdbuspp_gen_meson_prog, '--command', 'cpp',
@@ -11,5 +25,16 @@
         '--directory', meson.current_source_dir() / '../../../../yaml',
         'net/poettering/Calculator',
     ],
+    install: should_generate_cpp,
+    install_dir: [
+        false,
+        get_option('includedir') / sdbusplus_current_path,
+        get_option('includedir') / sdbusplus_current_path,
+        get_option('includedir') / sdbusplus_current_path,
+        false,
+        get_option('includedir') / sdbusplus_current_path,
+        get_option('includedir') / sdbusplus_current_path,
+    ],
+    build_by_default: should_generate_cpp,
 )
 
diff --git a/example/gen/net/poettering/meson.build b/example/gen/net/poettering/meson.build
index 62b350e..149b068 100644
--- a/example/gen/net/poettering/meson.build
+++ b/example/gen/net/poettering/meson.build
@@ -1,6 +1,9 @@
 # Generated file; do not modify.
 subdir('Calculator')
-generated_others += custom_target(
+
+sdbusplus_current_path = 'net/poettering'
+
+generated_markdown += custom_target(
     'net/poettering/Calculator__markdown'.underscorify(),
     input: [ '../../../yaml/net/poettering/Calculator.events.yaml', '../../../yaml/net/poettering/Calculator.interface.yaml',  ],
     output: [ 'Calculator.md' ],
@@ -12,9 +15,12 @@
         '--directory', meson.current_source_dir() / '../../../yaml',
         'net/poettering/Calculator',
     ],
+    install: should_generate_markdown,
+    install_dir: [inst_markdown_dir / sdbusplus_current_path],
+    build_by_default: should_generate_markdown,
 )
 
-generated_others += custom_target(
+generated_registry += custom_target(
     'net/poettering/Calculator__registry'.underscorify(),
     input: [ '../../../yaml/net/poettering/Calculator.events.yaml',  ],
     output: [ 'Calculator.json' ],
@@ -26,5 +32,8 @@
         '--directory', meson.current_source_dir() / '../../../yaml',
         'net/poettering/Calculator',
     ],
+    install: should_generate_registry,
+    install_dir: [inst_registry_dir / sdbusplus_current_path],
+    build_by_default: should_generate_registry,
 )
 
diff --git a/example/meson.build b/example/meson.build
index bb4f4a4..8a63e8e 100644
--- a/example/meson.build
+++ b/example/meson.build
@@ -50,18 +50,8 @@
     dependencies: asio_dep,
 )
 
-generated_sources = []
-generated_others = []
+yaml_selected_subdirs = ['net']
 subdir('gen')
-subdir('gen/net')
-
-custom_target(
-    'example_md',
-    command: 'true',
-    output: 'example_md',
-    capture: true,
-    depends: generated_others,
-    build_by_default: true)
 
 executable(
     'calculator-server',
diff --git a/meson.build b/meson.build
index 613f9ca..8b65e92 100644
--- a/meson.build
+++ b/meson.build
@@ -21,7 +21,6 @@
   error('No valid python3 installation found')
 endif
 
-
 root_inc = include_directories('include')
 
 libsdbusplus_src = files(
@@ -72,6 +71,10 @@
     ],
 )
 
+should_generate_cpp = true
+should_generate_markdown = false
+should_generate_registry = false
+
 subdir('tools')
 
 if not get_option('examples').disabled()
diff --git a/test/gen/meson.build b/test/gen/meson.build
index 8d7d4de..ef27aee 100644
--- a/test/gen/meson.build
+++ b/test/gen/meson.build
@@ -13,3 +13,23 @@
     )
 endif
 
+inst_markdown_dir = get_option('datadir') / 'doc' / meson.project_name()
+inst_registry_dir = get_option('datadir') / 'redfish-registry' / meson.project_name()
+
+generated_sources = []
+generated_markdown = []
+generated_registry = []
+
+foreach d : yaml_selected_subdirs
+    subdir(d)
+endforeach
+
+generated_headers = []
+foreach s : generated_sources
+    foreach f : s.to_list()
+        if f.full_path().endswith('.hpp')
+            generated_headers += f
+        endif
+    endforeach
+endforeach
+
diff --git a/test/gen/server/Test/meson.build b/test/gen/server/Test/meson.build
index 459f0a8..53b0820 100644
--- a/test/gen/server/Test/meson.build
+++ b/test/gen/server/Test/meson.build
@@ -1,8 +1,19 @@
 # Generated file; do not modify.
+
+sdbusplus_current_path = 'server/Test'
+
 generated_sources += custom_target(
     'server/Test__cpp'.underscorify(),
-    input: [ '../../../yaml/server/Test.interface.yaml',  ],
-    output: [ 'common.hpp', 'server.cpp', 'server.hpp', 'aserver.hpp', 'client.hpp',  ],
+    input: [
+        '../../../yaml/server/Test.interface.yaml',
+    ],
+    output: [
+        'common.hpp',
+        'server.hpp',
+        'server.cpp',
+        'aserver.hpp',
+        'client.hpp',
+    ],
     depend_files: sdbusplusplus_depfiles,
     command: [
         sdbuspp_gen_meson_prog, '--command', 'cpp',
@@ -11,5 +22,14 @@
         '--directory', meson.current_source_dir() / '../../../yaml',
         'server/Test',
     ],
+    install: should_generate_cpp,
+    install_dir: [
+        get_option('includedir') / sdbusplus_current_path,
+        get_option('includedir') / sdbusplus_current_path,
+        false,
+        get_option('includedir') / sdbusplus_current_path,
+        get_option('includedir') / sdbusplus_current_path,
+    ],
+    build_by_default: should_generate_cpp,
 )
 
diff --git a/test/gen/server/meson.build b/test/gen/server/meson.build
index 6ab2512..20a77bf 100644
--- a/test/gen/server/meson.build
+++ b/test/gen/server/meson.build
@@ -1,6 +1,9 @@
 # Generated file; do not modify.
 subdir('Test')
-generated_others += custom_target(
+
+sdbusplus_current_path = 'server'
+
+generated_markdown += custom_target(
     'server/Test__markdown'.underscorify(),
     input: [ '../../yaml/server/Test.interface.yaml',  ],
     output: [ 'Test.md' ],
@@ -12,5 +15,8 @@
         '--directory', meson.current_source_dir() / '../../yaml',
         'server/Test',
     ],
+    install: should_generate_markdown,
+    install_dir: [inst_markdown_dir / sdbusplus_current_path],
+    build_by_default: should_generate_markdown,
 )
 
diff --git a/test/meson.build b/test/meson.build
index c0b7a0a..2329e31 100644
--- a/test/meson.build
+++ b/test/meson.build
@@ -87,10 +87,8 @@
     ),
 )
 
-generated_sources = []
-generated_others = []
+yaml_selected_subdirs = ['server']
 subdir('gen')
-subdir('gen/server')
 
 server_test_pre = declare_dependency(
     include_directories: include_directories('gen'),
@@ -102,17 +100,8 @@
     implicit_include_directories: false,
     dependencies: server_test_pre)
 
-generated_sources_header = []
-foreach s : generated_sources
-    foreach f : s.to_list()
-        if f.full_path().endswith('.hpp')
-            generated_sources_header += f
-        endif
-    endforeach
-endforeach
-
 server_test_dep = declare_dependency(
-  sources: generated_sources_header,
+  sources: generated_headers,
   link_with: server_test_lib,
   dependencies: server_test_pre)
 
diff --git a/tools/sdbus++-gen-meson b/tools/sdbus++-gen-meson
index d92717a..1da2588 100755
--- a/tools/sdbus++-gen-meson
+++ b/tools/sdbus++-gen-meson
@@ -130,6 +130,26 @@
     )
 endif
 
+inst_markdown_dir = get_option('datadir') / 'doc' / meson.project_name()
+inst_registry_dir = get_option('datadir') / 'redfish-registry' / meson.project_name()
+
+generated_sources = []
+generated_markdown = []
+generated_registry = []
+
+foreach d : yaml_selected_subdirs
+    subdir(d)
+endforeach
+
+generated_headers = []
+foreach s : generated_sources
+    foreach f : s.to_list()
+        if f.full_path().endswith('.hpp')
+            generated_headers += f
+        endif
+    endforeach
+endforeach
+
 EOF
 }
 
@@ -169,6 +189,23 @@
     done
 }
 
+## Add the 'sdbusplus_current_path' to the meson file.
+##
+## $1 - The path to insert into.
+##
+## This is done after the subdir processing because we need to leave
+## the meson variable in this state for the install directives.
+function meson_insert_current_path() {
+    meson_path="${outputdir}/${1}"
+    current_path="${1}"
+    cat >> "${meson_path}/meson.build" \
+        << EOF
+
+sdbusplus_current_path = '${current_path}'
+
+EOF
+}
+
 ## Generate the meson target for the source files (.cpp/.hpp) from a YAML
 ## interface.
 ##
@@ -176,27 +213,48 @@
 function meson_cpp_target() {
     mesondir="${outputdir}/$1"
     yamldir="$(realpath --relative-to="${mesondir}" "${rootdir}")"
+    nl=$'\n'
+    ind="        "
 
     # Determine the source and output files based on the YAMLs present.
     sources=""
     outputs=""
+    install=""
     for s in ${interfaces[$1]}; do
-        sources="${sources}'${yamldir}/$1.${s}', "
+        sources="${sources}${ind}'${yamldir}/$1.${s}',${nl}"
 
         case "${s}" in
             errors.yaml)
-                outputs="${outputs}'error.cpp', 'error.hpp', "
+                outputs="${outputs}${ind}'error.cpp',${nl}"
+                install="${install}${ind}false,${nl}"
+
+                outputs="${outputs}${ind}'error.hpp',${nl}"
+                install="${install}${ind}get_option('includedir') / sdbusplus_current_path,${nl}"
                 ;;
 
             events.yaml)
-                outputs="${outputs}'event.cpp', 'event.hpp', "
+                outputs="${outputs}${ind}'event.cpp',${nl}"
+                install="${install}${ind}false,${nl}"
+
+                outputs="${outputs}${ind}'event.hpp',${nl}"
+                install="${install}${ind}get_option('includedir') / sdbusplus_current_path,${nl}"
                 ;;
 
             interface.yaml)
-                outputs="${outputs}'common.hpp', "
-                outputs="${outputs}'server.cpp', 'server.hpp', "
-                outputs="${outputs}'aserver.hpp', "
-                outputs="${outputs}'client.hpp', "
+                outputs="${outputs}${ind}'common.hpp',${nl}"
+                install="${install}${ind}get_option('includedir') / sdbusplus_current_path,${nl}"
+
+                outputs="${outputs}${ind}'server.hpp',${nl}"
+                install="${install}${ind}get_option('includedir') / sdbusplus_current_path,${nl}"
+
+                outputs="${outputs}${ind}'server.cpp',${nl}"
+                install="${install}${ind}false,${nl}"
+
+                outputs="${outputs}${ind}'aserver.hpp',${nl}"
+                install="${install}${ind}get_option('includedir') / sdbusplus_current_path,${nl}"
+
+                outputs="${outputs}${ind}'client.hpp',${nl}"
+                install="${install}${ind}get_option('includedir') / sdbusplus_current_path,${nl}"
                 ;;
 
             *)
@@ -211,8 +269,10 @@
         << EOF
 generated_sources += custom_target(
     '$1__cpp'.underscorify(),
-    input: [ ${sources} ],
-    output: [ ${outputs} ],
+    input: [
+${sources}    ],
+    output: [
+${outputs}    ],
     depend_files: sdbusplusplus_depfiles,
     command: [
         sdbuspp_gen_meson_prog, '--command', 'cpp',
@@ -221,6 +281,10 @@
         '--directory', meson.current_source_dir() / '${yamldir}',
         '$1',
     ],
+    install: should_generate_cpp,
+    install_dir: [
+${install}    ],
+    build_by_default: should_generate_cpp,
 )
 
 EOF
@@ -241,7 +305,7 @@
     # Create the target to generate the interface.md file.
     cat >> "${mesondir}/meson.build" \
         << EOF
-generated_others += custom_target(
+generated_markdown += custom_target(
     '$1__markdown'.underscorify(),
     input: [ ${sources} ],
     output: [ '$(basename "$1").md' ],
@@ -253,6 +317,9 @@
         '--directory', meson.current_source_dir() / '${yamldir}',
         '$1',
     ],
+    install: should_generate_markdown,
+    install_dir: [inst_markdown_dir / sdbusplus_current_path],
+    build_by_default: should_generate_markdown,
 )
 
 EOF
@@ -294,7 +361,7 @@
     # Create the target to generate the interface.md file.
     cat >> "${mesondir}/meson.build" \
         << EOF
-generated_others += custom_target(
+generated_registry += custom_target(
     '$1__registry'.underscorify(),
     input: [ ${sources} ],
     output: [ '$(basename "$1").json' ],
@@ -306,6 +373,9 @@
         '--directory', meson.current_source_dir() / '${yamldir}',
         '$1',
     ],
+    install: should_generate_registry,
+    install_dir: [inst_registry_dir / sdbusplus_current_path],
+    build_by_default: should_generate_registry,
 )
 
 EOF
@@ -333,8 +403,16 @@
     meson_create_root
     # shellcheck disable=SC2312
     sorted_ifaces="$(echo "${!interfaces[@]}" | tr " " "\n" | sort)"
+    iface_parent_dirs="$(echo "${sorted_ifaces}" | xargs -n1 dirname)"
+    # shellcheck disable=SC2312
+    sorted_dirs="$(echo "${sorted_ifaces} ${iface_parent_dirs}" | tr " " "\n" | sort | uniq)"
     for i in ${sorted_ifaces}; do
         meson_create_path "${i}"
+    done
+    for i in ${sorted_dirs}; do
+        meson_insert_current_path "${i}"
+    done
+    for i in ${sorted_ifaces}; do
         meson_cpp_target "${i}"
         meson_md_target "${i}"
         meson_registry_target "${i}"