| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503 |
- # Copyright (c) 2022 Project CHIP Authors
- #
- # Licensed under the Apache License, Version 2.0 (the "License");
- # you may not use this file except in compliance with the License.
- # You may obtain a copy of the License at
- #
- # http://www.apache.org/licenses/LICENSE-2.0
- #
- # Unless required by applicable law or agreed to in writing, software
- # distributed under the License is distributed on an "AS IS" BASIS,
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- # See the License for the specific language governing permissions and
- # limitations under the License.
- import("//build_overrides/build.gni")
- import("//build_overrides/chip.gni")
- import("//build_overrides/pigweed.gni")
- import("$dir_pw_build/python.gni")
- import("${chip_root}/scripts/py_matter_idl/files.gni")
- declare_args() {
- # Location where code has been pre-generated
- chip_code_pre_generated_directory = ""
- }
- # Code generation that will happen at build time.
- #
- # uses `scripts/codegen.py` for code generation.
- template("_chip_build_time_codegen") {
- _name = target_name
- _generator = invoker.generator
- config("${_name}_config") {
- include_dirs = [ target_gen_dir ]
- }
- pw_python_action("${_name}_codegen") {
- script = "${chip_root}/scripts/codegen.py"
- # TODO: this seems to touch internals. Is this ok? speeds up builds!
- _pw_internal_run_in_venv = false
- _idl_file = invoker.input
- _expected_outputs = "${target_gen_dir}/${_name}.expected.outputs"
- write_file(_expected_outputs, invoker.outputs, "list lines")
- args = [
- "--generator",
- _generator,
- "--output-dir",
- rebase_path(target_gen_dir, root_build_dir),
- "--expected-outputs",
- rebase_path(_expected_outputs, root_build_dir),
- ]
- if (defined(invoker.options)) {
- foreach(option, invoker.options) {
- args += [
- "--option",
- option,
- ]
- }
- }
- args += [ rebase_path(_idl_file, root_build_dir) ]
- inputs = [
- _idl_file,
- _expected_outputs,
- ]
- # ensure any change in codegen files will result in a rebuild
- inputs += matter_idl_generator_files
- sources = [ _idl_file ]
- outputs = []
- foreach(name, invoker.outputs) {
- outputs += [ "${target_gen_dir}/${name}" ]
- }
- }
- source_set(_name) {
- sources = []
- foreach(name, invoker.outputs) {
- sources += [ "${target_gen_dir}/${name}" ]
- }
- public_configs = [ ":${_name}_config" ]
- if (defined(invoker.public_configs)) {
- public_configs += invoker.public_configs
- }
- forward_variables_from(invoker, [ "deps" ])
- if (!defined(deps)) {
- deps = []
- }
- deps += [ ":${_name}_codegen" ]
- }
- }
- # Code generation that will happen at build time.
- #
- # variables:
- # input
- # The ".zap" file to use to start the code generation
- #
- # generator
- # Name of the generator to use. Supported variants:
- # - "app-templates"
- #
- #
- #
- # deps, public_configs
- # Forwarded to the resulting source set
- #
- #
- # uses `zap` for code generation.
- template("_chip_build_time_zapgen") {
- _name = target_name
- _generator = invoker.generator
- config("${_name}_config") {
- include_dirs = [ "${target_gen_dir}/zapgen/" ]
- }
- assert(_generator == "app-templates")
- if (_generator == "app-templates") {
- _template_path =
- rebase_path("${chip_root}/src/app/zap-templates/app-templates.json")
- _partials_dir = "${chip_root}/src/app/zap-templates/partials"
- _template_dir = "${chip_root}/src/app/zap-templates/templates/app"
- # TODO: unclear how to maintain these: there is no parser that can figure
- # out links of template files and zap files and such
- _extra_dependencies = [
- "${_partials_dir}/header.zapt",
- "${_partials_dir}/im_command_handler_cluster_commands.zapt",
- # Application templates, actually generating files
- "${_template_dir}/access.zapt",
- "${_template_dir}/CHIPClusters.zapt",
- "${_template_dir}/endpoint_config.zapt",
- "${_template_dir}/gen_config.zapt",
- "${_template_dir}/im-cluster-command-handler.zapt",
- ]
- _output_subdir = "zap-generated"
- }
- pw_python_action("${_name}_zap_pregen") {
- script = "${chip_root}/scripts/tools/zap/generate.py"
- # TODO: this seems to touch internals. Is this ok? speeds up builds!
- _pw_internal_run_in_venv = false
- _idl_file = invoker.input
- args = [
- "--no-prettify-output",
- "--templates",
- _template_path,
- "--output-dir",
- rebase_path(target_gen_dir) + "/zap_pregen/" + _output_subdir,
- # TODO: lock file support should be removed as this serializes zap
- # (slower), however this is currently done because on Darwin zap startup
- # may conflict and error out with:
- # Error: EEXIST: file already exists, mkdir '/var/folders/24/8k48jl6d249_n_qfxwsl6xvm0000gn/T/pkg/465fcc8a6282e28dc7a166859d5814d34e2fb94249a72fa9229033b5b32dff1a'
- "--lock-file",
- rebase_path("${root_out_dir}/zap_gen.lock"),
- "--parallel",
- _idl_file,
- ]
- inputs = [
- _idl_file,
- _template_path,
- ]
- inputs += _extra_dependencies
- # ensure any change in codegen files will result in a rebuild
- inputs += matter_idl_generator_files
- sources = [ _idl_file ]
- outputs = []
- foreach(name, invoker.outputs) {
- outputs += [ "${target_gen_dir}/zap_pregen/${name}" ]
- }
- forward_variables_from(invoker, [ "prune_outputs" ])
- if (defined(prune_outputs)) {
- foreach(name, prune_outputs) {
- outputs += [ "${target_gen_dir}/zap_pregen/${name}" ]
- }
- }
- }
- # This action ensures that any "extra" files generated by zap codegen
- # are actually deleted.
- #
- # This is to avoid double-codegen of configurations like endpoint config
- # or access credentials being generated for both "controller client" and
- # application-specific
- pw_python_action("${_name}_files") {
- # TODO: this seems to touch internals. Is this ok? speeds up builds!
- _pw_internal_run_in_venv = false
- script = "${chip_root}/scripts/tools/zap/prune_outputs.py"
- _keep_file = rebase_path("${target_gen_dir}/${_name}.keep.outputs")
- write_file(_keep_file, invoker.outputs, "list lines")
- args = [
- "--keep",
- _keep_file,
- "--input-dir",
- rebase_path("${target_gen_dir}/zap_pregen/"),
- "--output-dir",
- rebase_path("${target_gen_dir}/zapgen/"),
- ]
- inputs = []
- foreach(name, invoker.outputs) {
- inputs += [ "${target_gen_dir}/zap_pregen/${name}" ]
- }
- outputs = []
- foreach(name, invoker.outputs) {
- outputs += [ "${target_gen_dir}/zapgen/${name}" ]
- }
- deps = [ ":${_name}_zap_pregen" ]
- }
- source_set(_name) {
- sources = []
- foreach(name, invoker.outputs) {
- sources += [ "${target_gen_dir}/zapgen/${name}" ]
- }
- public_configs = [ ":${_name}_config" ]
- if (defined(invoker.public_configs)) {
- public_configs += invoker.public_configs
- }
- forward_variables_from(invoker, [ "deps" ])
- if (!defined(public_deps)) {
- public_deps = []
- }
- public_deps += [
- ":${_name}_files",
- ":${_name}_zap_pregen",
- ]
- }
- }
- # Defines a target that runs code generation based on
- # scripts/codegen.py
- #
- # Arguments:
- # input
- # The ".matter" file to use to start the code generation
- #
- # generator
- # Name of the generator to use (e.g. java-jni, java-class, cpp-app)
- #
- # outputs
- # Explicit names of the expected outputs. Enforced to validate that
- # expected outputs are generated when processing input files.
- #
- # deps, public_configs
- # Forwarded to the resulting source set
- #
- # Command line parameters:
- #
- # chip_code_pre_generated_directory:
- # - If this is set, generation will NOT happen at compile time but rather
- # the code generation is assumed to have already happened and reside in
- # the given location.
- # - The TOP LEVEL directory is assumed to be given. Actual location for
- # individual generators is expected to be of the form
- # <top_dir>/<matter_path>/<generator>
- #
- # NOTE: content of "outputs" is verified to match the output of codegen.py
- # exactly. It is not inferred on purpose, to make build-rules explicit
- # and verifiable (even though codegen.py can at runtime report its outputs)
- #
- # To find the list of generated files, you can run codegen.py with the
- # "--name-only" argument
- #
- # NOTE:
- # the result of the target_name WILL BE a `source_set`. Treat it as such.
- #
- # Example usage:
- #
- # chip_codegen("java-jni-generate") {
- # input = "controller-clusters.matter"
- # generator = "java-jni"
- #
- # outputs = [
- # "jni/IdentifyClient-ReadImpl.cpp",
- # "jni/IdentifyClient-InvokeSubscribeImpl.cpp",
- # # ... more to follow
- # ]
- # }
- #
- template("chip_codegen") {
- if (chip_code_pre_generated_directory == "") {
- _chip_build_time_codegen(target_name) {
- forward_variables_from(invoker,
- [
- "deps",
- "generator",
- "input",
- "outputs",
- "options",
- "public_configs",
- ])
- }
- } else {
- _name = target_name
- not_needed(invoker, [ "options" ])
- # This constructs a path like:
- # FROM all-clusters-app.matter (inside examples/all-clusters-app/all-clusters-common/)
- # USING "cpp-app" for generator:
- # => ${pregen_dir}/examples/all-clusters-app/all-clusters-common/all-clusters-app/codegen/cpp-app
- _generation_dir =
- chip_code_pre_generated_directory + "/" +
- string_replace(rebase_path(invoker.input, chip_root), ".matter", "") +
- "/codegen/" + invoker.generator
- config("${_name}_config") {
- include_dirs = [ "${_generation_dir}" ]
- }
- source_set(_name) {
- public_configs = [ ":${_name}_config" ]
- if (defined(invoker.public_configs)) {
- public_configs += invoker.public_configs
- }
- forward_variables_from(invoker, [ "deps" ])
- sources = []
- foreach(name, invoker.outputs) {
- sources += [ "${_generation_dir}/${name}" ]
- }
- }
- }
- }
- # Defines a target that runs code generation based on
- # scripts/codegen.py
- #
- # Arguments:
- # input
- # The ".matter" file to use to start the code generation
- #
- # generator
- # Name of the generator to use (e.g. java-jni, java-class, cpp-app)
- #
- # outputs
- # Explicit names of the expected outputs. Enforced to validate that
- # expected outputs are generated when processing input files.
- #
- # deps, public_configs
- # Forwarded to the resulting source set
- #
- # Command line parameters:
- #
- # chip_code_pre_generated_directory:
- # - If this is set, generation will NOT happen at compile time but rather
- # the code generation is assumed to have already happened and reside in
- # the given location.
- # - The TOP LEVEL directory is assumed to be given. Actual location for
- # individual generators is expected to be of the form
- # <top_dir>/<matter_path>/<generator>
- #
- # NOTE: content of "outputs" is verified to match the output of codegen.py
- # exactly. It is not inferred on purpose, to make build-rules explicit
- # and verifiable (even though codegen.py can at runtime report its outputs)
- #
- # To find the list of generated files, you can run codegen.py with the
- # "--name-only" argument
- #
- # NOTE:
- # the result of the target_name WILL BE a `source_set`. Treat it as such.
- #
- # Example usage:
- #
- # chip_codegen("java-jni-generate") {
- # input = "controller-clusters.matter"
- # generator = "java-jni"
- #
- # outputs = [
- # "jni/IdentifyClient-ReadImpl.cpp",
- # "jni/IdentifyClient-InvokeSubscribeImpl.cpp",
- # # ... more to follow
- # ]
- # }
- #
- template("chip_zapgen") {
- if (chip_code_pre_generated_directory == "") {
- _chip_build_time_zapgen(target_name) {
- forward_variables_from(invoker,
- [
- "deps",
- "generator",
- "input",
- "outputs",
- "public_configs",
- "prune_outputs",
- ])
- }
- } else {
- _name = target_name
- # This contstructs a path like:
- # FROM all-clusters-app.zap (inside examples/all-clusters-app/all-clusters-common/)
- # USING "cpp-app" for generator:
- # => ${pregen_dir}/examples/all-clusters-app/all-clusters-common/all-clusters-app/codegen/cpp-app
- _generation_dir =
- chip_code_pre_generated_directory + "/" +
- string_replace(rebase_path(invoker.input, chip_root), ".zap", "") +
- "/zap/" + invoker.generator
- config("${_name}_config") {
- include_dirs = [ "${_generation_dir}" ]
- }
- # Pick up only the headers and mark them available to use
- # Specifically controller seems to require header files but NOT cpp (does)
- # not want to include cpp compilation of IM command handler data
- source_set("${_name}_headers") {
- sources = []
- foreach(name, invoker.outputs) {
- if (get_path_info(name, "extension") == "h") {
- sources += [ "${_generation_dir}/${name}" ]
- }
- }
- # Ugly, but references WILL reference back into main code.
- check_includes = false
- }
- # need to have consistent naming. Make sure "files" exists
- action("${_name}_files") {
- script = "${chip_root}/scripts/tools/zap/check_file_existence.py"
- _output_name = "${target_gen_dir}/${_name}_files_checked.stamp"
- args = [
- "--touch",
- rebase_path(_output_name),
- ]
- outputs = [ _output_name ]
- foreach(name, invoker.outputs) {
- args += [
- "--exists",
- rebase_path("${_generation_dir}/${name}"),
- ]
- }
- # Depending on the files gets access to the headers
- public_deps = [ ":${_name}_headers" ]
- }
- source_set(_name) {
- forward_variables_from(invoker,
- [
- "deps",
- "public_configs",
- "prune_outputs",
- ])
- if (!defined(public_configs)) {
- public_configs = []
- }
- public_configs += [ ":${_name}_config" ]
- sources = []
- foreach(name, invoker.outputs) {
- sources += [ "${_generation_dir}/${name}" ]
- }
- # Ugly, but references WILL reference back into main code.
- check_includes = false
- }
- }
- }
|