From 5b115493a56ffbfc6a7512c4a9cf150cefaad33b Mon Sep 17 00:00:00 2001 From: Michael Spang Date: Thu, 8 Apr 2021 20:00:54 -0400 Subject: [PATCH] RFC: Read the ZAP file to determine which directories to compile This parses the ZAP file, enumerates enabled clusters, and tries to enable the appropriate directories in src/app/clusters. It's not clear if this is the right thing to do; as selecting directories this way leads to including directories that do not compile for every application. This draft PR filters those back out again. Based on #5882 --- .../all-clusters-common/BUILD.gn | 33 +--- examples/bridge-app/bridge-common/BUILD.gn | 16 +- examples/chip-tool/BUILD.gn | 16 +- .../lighting-app/lighting-common/BUILD.gn | 14 +- examples/lock-app/lock-common/BUILD.gn | 13 +- examples/tv-app/tv-common/BUILD.gn | 29 +--- examples/window-app/common/BUILD.gn | 12 +- src/app/chip_data_model.gni | 60 +++++-- src/app/zap_cluster_list.py | 146 ++++++++++++++++++ src/darwin/Framework/CHIP/BUILD.gn | 20 ++- 10 files changed, 268 insertions(+), 91 deletions(-) create mode 100755 src/app/zap_cluster_list.py diff --git a/examples/all-clusters-app/all-clusters-common/BUILD.gn b/examples/all-clusters-app/all-clusters-common/BUILD.gn index bcccf42a007521..0c45f3c3637184 100644 --- a/examples/all-clusters-app/all-clusters-common/BUILD.gn +++ b/examples/all-clusters-app/all-clusters-common/BUILD.gn @@ -17,32 +17,13 @@ import("//build_overrides/chip.gni") import("${chip_root}/src/app/chip_data_model.gni") chip_data_model("all-clusters-common") { - cluster_sources = [ - "account-login-server", - "application-launcher-server", - "audio-output-server", - "barrier-control-server", - "basic", - "bindings", - "color-control-server", - "content-launch-server", - "door-lock-server", - "general-commissioning-server", - "groups-server", - "ias-zone-server", - "identify", - "keypad-input-server", - "level-control", - "low-power-server", - "media-input-server", - "media-playback-server", - "network-commissioning", - "on-off-server", - "scenes", - "target-navigator-server", - "temperature-measurement-server", - "tv-channel-server", - ] + zap_file = "all-clusters-app.zap" zap_pregenerated_dir = "gen" + + # These clusters are configured in the ZAP file but don't compile. + remove_cluster_sources = [ + "ias-zone-client", + "scenes-client", + ] } diff --git a/examples/bridge-app/bridge-common/BUILD.gn b/examples/bridge-app/bridge-common/BUILD.gn index 4c19d980516fe9..c9d2396e682193 100644 --- a/examples/bridge-app/bridge-common/BUILD.gn +++ b/examples/bridge-app/bridge-common/BUILD.gn @@ -17,13 +17,15 @@ import("//build_overrides/chip.gni") import("${chip_root}/src/app/chip_data_model.gni") chip_data_model("bridge-common") { - cluster_sources = [ - "basic", - "bindings", - "level-control", - "network-commissioning", - "on-off-server", - ] + zap_file = "bridge-app.zap" zap_pregenerated_dir = "gen" + + # These clusters are configured in the ZAP file but don't compile. + remove_cluster_sources = [ + "color-control-server", + "groups-server", + "identify", + "scenes", + ] } diff --git a/examples/chip-tool/BUILD.gn b/examples/chip-tool/BUILD.gn index c9b7d8f58a3e71..3572bb99bf0b8e 100644 --- a/examples/chip-tool/BUILD.gn +++ b/examples/chip-tool/BUILD.gn @@ -25,11 +25,25 @@ config("includes") { } chip_data_model("data_model") { - cluster_sources = [ "media-playback-client" ] + zap_file = "chip-tool.zap" zap_pregenerated_dir = "gen" use_default_client_callbacks = true + + # These clusters are configured in the ZAP file but don't compile. + remove_cluster_sources = [ + "color-control-server", + "door-lock-client", + "groups-client", + "groups-server", + "ias-zone-client", + "ias-zone-server", + "identify", + "level-control", + "scenes", + "scenes-client", + ] } executable("chip-tool") { diff --git a/examples/lighting-app/lighting-common/BUILD.gn b/examples/lighting-app/lighting-common/BUILD.gn index 004618e12a94ac..7ed7f310e18e8b 100644 --- a/examples/lighting-app/lighting-common/BUILD.gn +++ b/examples/lighting-app/lighting-common/BUILD.gn @@ -38,12 +38,14 @@ if (enable_pw_rpc) { } chip_data_model("lighting-common") { - cluster_sources = [ - "bindings", - "level-control", - "network-commissioning", - "on-off-server", - ] + zap_file = "lighting-app.zap" zap_pregenerated_dir = "gen" + + # These clusters are configured in the ZAP file but don't compile. + remove_cluster_sources = [ + "groups-server", + "identify", + "scenes", + ] } diff --git a/examples/lock-app/lock-common/BUILD.gn b/examples/lock-app/lock-common/BUILD.gn index 61d7675bc5cadf..99079d6ebe3fcf 100644 --- a/examples/lock-app/lock-common/BUILD.gn +++ b/examples/lock-app/lock-common/BUILD.gn @@ -17,11 +17,14 @@ import("//build_overrides/chip.gni") import("${chip_root}/src/app/chip_data_model.gni") chip_data_model("lock-common") { - cluster_sources = [ - "bindings", - "network-commissioning", - "on-off-server", - ] + zap_file = "lock-app.zap" zap_pregenerated_dir = "gen" + + # These clusters are configured in the ZAP file but don't compile. + remove_cluster_sources = [ + "groups-server", + "identify", + "scenes", + ] } diff --git a/examples/tv-app/tv-common/BUILD.gn b/examples/tv-app/tv-common/BUILD.gn index 38b85bab65d8a7..da45344a67aba8 100644 --- a/examples/tv-app/tv-common/BUILD.gn +++ b/examples/tv-app/tv-common/BUILD.gn @@ -17,28 +17,13 @@ import("//build_overrides/chip.gni") import("${chip_root}/src/app/chip_data_model.gni") chip_data_model("tv-common") { - cluster_sources = [ - "barrier-control-server", - "basic", - "bindings", - "color-control-server", - "content-launch-server", - "door-lock-client", - "door-lock-server", - "groups-client", - "groups-server", - "ias-zone-server", - "identify", - "identify-client", - "level-control", - "low-power-server", - "media-playback-server", - "network-commissioning", - "on-off-server", - "scenes", - "scenes-client", - "temperature-measurement-server", - ] + zap_file = "tv-app.zap" zap_pregenerated_dir = "gen" + + # These clusters are configured in the ZAP file but don't compile. + remove_cluster_sources = [ + "ias-zone-client", + "scenes-client", + ] } diff --git a/examples/window-app/common/BUILD.gn b/examples/window-app/common/BUILD.gn index cae03951f43359..accf124ac45c51 100644 --- a/examples/window-app/common/BUILD.gn +++ b/examples/window-app/common/BUILD.gn @@ -17,10 +17,14 @@ import("//build_overrides/chip.gni") import("${chip_root}/src/app/chip_data_model.gni") chip_data_model("window-common") { - cluster_sources = [ - "bindings", - "network-commissioning", - ] + zap_file = "window-app.zap" zap_pregenerated_dir = "gen" + + # These clusters are configured in the ZAP file but don't compile. + remove_cluster_sources = [ + "groups-server", + "identify", + "scenes", + ] } diff --git a/src/app/chip_data_model.gni b/src/app/chip_data_model.gni index f2468ba61f7ead..9084bdf7c384bf 100644 --- a/src/app/chip_data_model.gni +++ b/src/app/chip_data_model.gni @@ -18,14 +18,24 @@ import("${chip_root}/src/lib/core/core.gni") _app_root = get_path_info(".", "abspath") +_zap_cluster_list_script = get_path_info("zap_cluster_list.py", "abspath") + # Defines a source_set for CHIP data model. # # Arguments: # zap_pregenerated_dir # Path to the ZAP "gen" dir. # +# zap_file +# Names of ZAP source file. +# # cluster_sources -# Names of the clusters to compile. +# Names of the clusters directories to compile. +# Deprecated, specify zap_file instead. +# +# remove_cluster_sources +# Names of the cluster directories to remove. +# TODO - Remove this option once everything compiles. # # use_default_client_callbacks # Include CHIPClientCallbacks.cpp. @@ -53,6 +63,8 @@ template("chip_data_model") { [ "zap_pregenerated_dir", "cluster_sources", + "remove_cluster_sources", + "zap_file", "use_default_client_callbacks", ]) @@ -102,22 +114,36 @@ template("chip_data_model") { ] if (defined(invoker.cluster_sources)) { - foreach(cluster, invoker.cluster_sources) { - if (cluster == "door-lock-server") { - sources += [ - "${_app_root}/clusters/${cluster}/door-lock-server-core.cpp", - "${_app_root}/clusters/${cluster}/door-lock-server-logging.cpp", - "${_app_root}/clusters/${cluster}/door-lock-server-schedule.cpp", - "${_app_root}/clusters/${cluster}/door-lock-server-user.cpp", - ] - } else if (cluster == "network-commissioning") { - sources += [ - "${_app_root}/clusters/${cluster}/${cluster}-ember.cpp", - "${_app_root}/clusters/${cluster}/${cluster}.cpp", - ] - } else { - sources += [ "${_app_root}/clusters/${cluster}/${cluster}.cpp" ] - } + _cluster_sources = invoker.cluster_sources + } else if (defined(invoker.zap_file)) { + _zap_path = rebase_path(invoker.zap_file, root_build_dir) + _script_args = [ "--zap_file=" + _zap_path ] + + _cluster_sources = exec_script(_zap_cluster_list_script, + _script_args, + "list lines", + [ invoker.zap_file ]) + } + + if (defined(invoker.remove_cluster_sources)) { + _cluster_sources -= invoker.remove_cluster_sources + } + + foreach(cluster, _cluster_sources) { + if (cluster == "door-lock-server") { + sources += [ + "${_app_root}/clusters/${cluster}/door-lock-server-core.cpp", + "${_app_root}/clusters/${cluster}/door-lock-server-logging.cpp", + "${_app_root}/clusters/${cluster}/door-lock-server-schedule.cpp", + "${_app_root}/clusters/${cluster}/door-lock-server-user.cpp", + ] + } else if (cluster == "network-commissioning") { + sources += [ + "${_app_root}/clusters/${cluster}/${cluster}-ember.cpp", + "${_app_root}/clusters/${cluster}/${cluster}.cpp", + ] + } else { + sources += [ "${_app_root}/clusters/${cluster}/${cluster}.cpp" ] } } diff --git a/src/app/zap_cluster_list.py b/src/app/zap_cluster_list.py new file mode 100755 index 00000000000000..300cbe774a4ad4 --- /dev/null +++ b/src/app/zap_cluster_list.py @@ -0,0 +1,146 @@ +#!/usr/bin/env python3 +"""Parses a ZAP input file and outputs directories to compile.""" + +import argparse +import pathlib +import json +import typing +import sys + +# List of directories in src/app/clusters to build for server clusters. +SERVER_CLUSTERS: typing.Dict[str, typing.List[str]] = { + 'NETWORK_COMMISSIONING_CLUSTER': ['network-commissioning'], + 'BASIC_CLUSTER': ['basic'], + 'OCCUPANCY_SENSING_CLUSTER': [], + 'GROUPS_CLUSTER': ['groups-server'], + 'IDENTIFY_CLUSTER': ['identify'], + 'LEVEL_CONTROL_CLUSTER': ['level-control'], + 'ON_OFF_CLUSTER': ['on-off-server'], + 'COLOR_CONTROL_CLUSTER': ['color-control-server'], + 'TEMP_MEASUREMENT_CLUSTER': ['temperature-measurement-server'], + 'BARRIER_CONTROL_CLUSTER': ['barrier-control-server'], + 'APPLICATION_BASIC_CLUSTER': [], + 'GENERAL_COMMISSIONING_CLUSTER': ['general-commissioning-server'], + 'DOOR_LOCK_CLUSTER': ['door-lock-server'], + 'CONTENT_LAUNCH_CLUSTER': ['content-launch-server'], + 'GROUP_KEY_MANAGEMENT_CLUSTER': [], + 'BINDING_CLUSTER': ['bindings'], + 'LOW_POWER_CLUSTER': ['low-power-server'], + 'MEDIA_PLAYBACK_CLUSTER': ['media-playback-server'], + 'ZLL_COMMISSIONING_CLUSTER': [], + 'COMMISSIONING_CLUSTER': [], + 'IAS_ZONE_CLUSTER': ['ias-zone-server'], + 'SCENES_CLUSTER': ['scenes'], + 'OTA_BOOTLOAD_CLUSTER': [], + 'DEVICE_TEMP_CLUSTER': [], + 'POWER_CONFIG_CLUSTER': [], + 'ALARM_CLUSTER': [], + 'WINDOW_COVERING_CLUSTER': [], +} + +# List of directories in src/app/clusters to build for client clusters. +CLIENT_CLUSTERS: typing.Dict[str, typing.List[str]] = { + 'BASIC_CLUSTER': [], + 'WINDOW_COVERING_CLUSTER': [], + 'ALARM_CLUSTER': [], + 'SCENES_CLUSTER': ['scenes-client'], + 'COMMISSIONING_CLUSTER': [], + 'OCCUPANCY_SENSING_CLUSTER': [], + 'DEVICE_TEMP_CLUSTER': [], + 'POWER_CONFIG_CLUSTER': [], + 'ZLL_COMMISSIONING_CLUSTER': [], + 'DEVICE_TEMP_CLUSTER': [], + 'GROUPS_CLUSTER': ['groups-client'], + 'IDENTIFY_CLUSTER': [], + 'COLOR_CONTROL_CLUSTER': [], + 'OTA_BOOTLOAD_CLUSTER': [], + 'GROUP_KEY_MANAGEMENT_CLUSTER': [], + 'TEMP_MEASUREMENT_CLUSTER': [], + 'ON_OFF_CLUSTER': [], + 'DOOR_LOCK_CLUSTER': [], + 'APPLICATION_BASIC_CLUSTER': [], + 'IAS_ZONE_CLUSTER': ['ias-zone-client'], + 'BINDING_CLUSTER': [], + 'LOW_POWER_CLUSTER': [], + 'DOOR_LOCK_CLUSTER': ['door-lock-client'], + 'GENERAL_COMMISSIONING_CLUSTER': [], + 'CONTENT_LAUNCH_CLUSTER': [], + 'MEDIA_PLAYBACK_CLUSTER': ['media-playback-client'], + 'LEVEL_CONTROL_CLUSTER': [], + 'NETWORK_COMMISSIONING_CLUSTER': [], + 'BARRIER_CONTROL_CLUSTER': [], +} + + +def get_cluster_sources(clusters: typing.Set[str], + source_map: typing.Dict[str, + typing.List[str]], side: str): + """Returns a list of cluster source directories for the given clusters. + + Returns: + The set of source directories to build.. + """ + + cluster_sources: typing.Set[str] = set() + + for cluster in clusters: + if not cluster in source_map: + raise ValueError("Unhandled %s cluster: %s" % (side, cluster)) + + cluster_sources.update(source_map[cluster]) + + return cluster_sources + + +def dump_zapfile_clusters(zap_file_path: pathlib.Path): + """Prints all of the source directories to build for a given ZAP file. + + Arguments: + zap_file_path - Path to the ZAP input file. + """ + + client_clusters: typing.Set[str] = set() + server_clusters: typing.Set[str] = set() + + with open(zap_file_path, "r") as zap_file: + zap_json = json.loads(zap_file.read()) + + for endpoint_type in zap_json.get('endpointTypes'): + for cluster in endpoint_type.get('clusters'): + side: str = cluster.get('side') + if side == 'client': + clusters_set = client_clusters + elif side == 'server': + clusters_set = server_clusters + else: + raise ValueError("Invalid side for cluster: %s" % side) + + clusters_set.add(cluster.get('define')) + + cluster_sources: typing.Set[str] = set() + + cluster_sources.update( + get_cluster_sources(server_clusters, SERVER_CLUSTERS, 'server')) + + cluster_sources.update( + get_cluster_sources(client_clusters, CLIENT_CLUSTERS, 'client')) + + for cluster in sorted(cluster_sources): + print(cluster) + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument('--zap_file', + help='Path to .zap file', + type=pathlib.Path) + + args = parser.parse_args() + + dump_zapfile_clusters(args.zap_file) + + sys.exit(0) + + +if __name__ == '__main__': + main() diff --git a/src/darwin/Framework/CHIP/BUILD.gn b/src/darwin/Framework/CHIP/BUILD.gn index 6ed64ec916ed86..895d04c7548c6b 100644 --- a/src/darwin/Framework/CHIP/BUILD.gn +++ b/src/darwin/Framework/CHIP/BUILD.gn @@ -60,13 +60,27 @@ static_library("framework") { } chip_data_model("darwin_data_model") { - cluster_sources = [ "media-playback-client" ] + zap_file = "chip-tool.zap" zap_pregenerated_dir = "gen" - public_configs = [ ":darwin_config" ] - use_default_client_callbacks = true + + # These clusters are configured in the ZAP file but don't compile. + remove_cluster_sources = [ + "color-control-server", + "door-lock-client", + "groups-client", + "groups-server", + "ias-zone-client", + "ias-zone-server", + "identify", + "level-control", + "scenes", + "scenes-client", + ] + + public_configs = [ ":darwin_config" ] } group("CHIP") {