From 96fce0c6810fb685f894a911aa32e31f070dd5b1 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. 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 | 144 ++++++++++++++++++ src/darwin/Framework/CHIP/BUILD.gn | 20 ++- 10 files changed, 266 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..558a253e7e4b0e --- /dev/null +++ b/src/app/zap_cluster_list.py @@ -0,0 +1,144 @@ +#!/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]] = { + 'ALARM_CLUSTER': [], + 'APPLICATION_BASIC_CLUSTER': [], + 'BARRIER_CONTROL_CLUSTER': ['barrier-control-server'], + 'BASIC_CLUSTER': ['basic'], + 'BINDING_CLUSTER': ['bindings'], + 'COLOR_CONTROL_CLUSTER': ['color-control-server'], + 'COMMISSIONING_CLUSTER': [], + 'CONTENT_LAUNCH_CLUSTER': ['content-launch-server'], + 'DEVICE_TEMP_CLUSTER': [], + 'DOOR_LOCK_CLUSTER': ['door-lock-server'], + 'GENERAL_COMMISSIONING_CLUSTER': ['general-commissioning-server'], + 'GROUPS_CLUSTER': ['groups-server'], + 'GROUP_KEY_MANAGEMENT_CLUSTER': [], + 'IAS_ZONE_CLUSTER': ['ias-zone-server'], + 'IDENTIFY_CLUSTER': ['identify'], + 'LEVEL_CONTROL_CLUSTER': ['level-control'], + 'LOW_POWER_CLUSTER': ['low-power-server'], + 'MEDIA_PLAYBACK_CLUSTER': ['media-playback-server'], + 'NETWORK_COMMISSIONING_CLUSTER': ['network-commissioning'], + 'OCCUPANCY_SENSING_CLUSTER': [], + 'ON_OFF_CLUSTER': ['on-off-server'], + 'OTA_BOOTLOAD_CLUSTER': [], + 'POWER_CONFIG_CLUSTER': [], + 'SCENES_CLUSTER': ['scenes'], + 'TEMP_MEASUREMENT_CLUSTER': ['temperature-measurement-server'], + 'WINDOW_COVERING_CLUSTER': [], + 'ZLL_COMMISSIONING_CLUSTER': [] +} + +# List of directories in src/app/clusters to build for client clusters. +CLIENT_CLUSTERS: typing.Dict[str, typing.List[str]] = { + 'ALARM_CLUSTER': [], + 'APPLICATION_BASIC_CLUSTER': [], + 'BARRIER_CONTROL_CLUSTER': [], + 'BASIC_CLUSTER': [], + 'BINDING_CLUSTER': [], + 'COLOR_CONTROL_CLUSTER': [], + 'COMMISSIONING_CLUSTER': [], + 'CONTENT_LAUNCH_CLUSTER': [], + 'DEVICE_TEMP_CLUSTER': [], + 'DOOR_LOCK_CLUSTER': ['door-lock-client'], + 'GENERAL_COMMISSIONING_CLUSTER': [], + 'GROUPS_CLUSTER': ['groups-client'], + 'GROUP_KEY_MANAGEMENT_CLUSTER': [], + 'IAS_ZONE_CLUSTER': ['ias-zone-client'], + 'IDENTIFY_CLUSTER': [], + 'LEVEL_CONTROL_CLUSTER': [], + 'LOW_POWER_CLUSTER': [], + 'MEDIA_PLAYBACK_CLUSTER': ['media-playback-client'], + 'NETWORK_COMMISSIONING_CLUSTER': [], + 'OCCUPANCY_SENSING_CLUSTER': [], + 'ON_OFF_CLUSTER': [], + 'OTA_BOOTLOAD_CLUSTER': [], + 'POWER_CONFIG_CLUSTER': [], + 'SCENES_CLUSTER': ['scenes-client'], + 'TEMP_MEASUREMENT_CLUSTER': [], + 'WINDOW_COVERING_CLUSTER': [], + 'ZLL_COMMISSIONING_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") {