Skip to content

Commit 3472839

Browse files
andy31415andreilitvin
authored andcommitted
Switch default generation target for generate.py to matter idl files (#24756)
* Documentation update * Fix paths * No need for an output directory for matter idl generation * Restyle * Make the output directory for generate.py really not needed (use a default that always exists for now) * Simplify the code * Restyle * Update regen_all to be able to figure out distinct commands using dry-run * Use a proper temporary directory, so matter idl naming does not clash * Regen * Fix usage of None for output directory in chef * Update template name for statistics output * Updated template text again to make it clearer what we generate * Fix chef codegen * Use shutil move since on CI the temporary directory is separate from the checkout filesystem --------- Co-authored-by: Andrei Litvin <andreilitvin@google.com>
1 parent 67594d3 commit 3472839

File tree

3 files changed

+81
-23
lines changed

3 files changed

+81
-23
lines changed

docs/code_generation.md

+18-2
Original file line numberDiff line numberDiff line change
@@ -172,8 +172,24 @@ Additionally, individual code regeneration can be done using
172172

173173
```bash
174174
/scripts/tools/zap/generate.py \
175-
examples/bridge-app/bridge-common/bridge-app.zap \
176-
-o zzz_generated/bridge-app/zap-generated
175+
examples/bridge-app/bridge-common/bridge-app.zap
176+
```
177+
178+
The above will just generate a `<app>.matter` file along side the `.zap` file,
179+
as this is the only file that requires updates for applications. You can code
180+
generate other things by passing in the `-t/--templates` argument to
181+
generate.py. In those cases, you may also need to specify an output directory
182+
via `-o/--output-dir`.
183+
184+
#### Flow for updating an application zap file:
185+
186+
```
187+
# use zap UI to edit the file (or edit zap file in any other way)
188+
./scripts/tools/zap/run_zaptool.sh $PATH_TO_ZAP_FILE
189+
190+
# re-generate .matter file. Note that for .matter file generation, output
191+
# directory is NOT used
192+
./scripts/tools/zap/generate.py $PATH_TO_ZAP_FILE
177193
```
178194

179195
### Compile-time code generation / pre-generated code

scripts/tools/zap/generate.py

+22-9
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import fcntl
2020
import json
2121
import os
22+
import shutil
2223
import subprocess
2324
import sys
2425
import tempfile
@@ -41,6 +42,7 @@ class CmdLineArgs:
4142
prettify_output: bool = True
4243
version_check: bool = True
4344
lock_file: Optional[str] = None
45+
delete_output_dir: bool = False
4446

4547

4648
CHIP_ROOT_DIR = os.path.realpath(
@@ -106,8 +108,12 @@ def detectZclFile(zapFile):
106108

107109

108110
def runArgumentsParser() -> CmdLineArgs:
109-
default_templates = 'src/app/zap-templates/app-templates.json'
110-
default_output_dir = 'zap-generated/'
111+
# By default generate the idl file only. This will get moved from the
112+
# output directory into the zap file directory automatically.
113+
#
114+
# All the rest of the files (app-templates.json) are generally built at
115+
# compile time.
116+
default_templates = 'src/app/zap-templates/matter-idl.json'
111117

112118
parser = argparse.ArgumentParser(
113119
description='Generate artifacts from .zapt templates')
@@ -117,7 +123,7 @@ def runArgumentsParser() -> CmdLineArgs:
117123
parser.add_argument('-z', '--zcl',
118124
help='Path to the zcl templates records to use for generating artifacts (default: autodetect read from zap file)')
119125
parser.add_argument('-o', '--output-dir', default=None,
120-
help='Output directory for the generated files (default: automatically selected)')
126+
help='Output directory for the generated files (default: a temporary directory in out)')
121127
parser.add_argument('--run-bootstrap', default=None, action='store_true',
122128
help='Automatically run ZAP bootstrap. By default the bootstrap is not triggered')
123129
parser.add_argument('--parallel', action='store_true')
@@ -129,20 +135,21 @@ def runArgumentsParser() -> CmdLineArgs:
129135
parser.add_argument('--version-check', action='store_true')
130136
parser.add_argument('--no-version-check',
131137
action='store_false', dest='version_check')
138+
parser.add_argument('--keep-output-dir', action='store_true',
139+
help='Keep any created output directory. Useful for temporary directories.')
132140
parser.set_defaults(parallel=True)
133141
parser.set_defaults(prettify_output=True)
134142
parser.set_defaults(version_check=True)
135143
parser.set_defaults(lock_file=None)
144+
parser.set_defaults(keep_output_dir=False)
136145
args = parser.parse_args()
137146

138-
# By default, this script assumes that the global CHIP template is used with
139-
# a default 'zap-generated/' output folder relative to APP_ROOT_DIR.
140-
# If needed, the user may specify a specific template as a second argument. In
141-
# this case the output folder is relative to CHIP_ROOT_DIR.
147+
delete_output_dir = False
142148
if args.output_dir:
143149
output_dir = args.output_dir
144150
elif args.templates == default_templates:
145-
output_dir = os.path.join(Path(args.zap).parent, default_output_dir)
151+
output_dir = tempfile.mkdtemp(prefix='zapgen')
152+
delete_output_dir = not args.keep_output_dir
146153
else:
147154
output_dir = ''
148155

@@ -162,6 +169,7 @@ def runArgumentsParser() -> CmdLineArgs:
162169
prettify_output=args.prettify_output,
163170
version_check=args.version_check,
164171
lock_file=args.lock_file,
172+
delete_output_dir=delete_output_dir,
165173
)
166174

167175

@@ -181,7 +189,7 @@ def extractGeneratedIdl(output_dir, zap_config_path):
181189
# multiple extensions. This is to work with existing codebase only
182190
raise Error("Unexpected input zap file %s" % self.zap_config)
183191

184-
os.rename(idl_path, target_path)
192+
shutil.move(idl_path, target_path)
185193

186194

187195
def runGeneration(cmdLineArgs):
@@ -327,6 +335,11 @@ def main():
327335
for prettifier in prettifiers:
328336
prettifier(cmdLineArgs.templateFile, cmdLineArgs.outputDir)
329337

338+
if cmdLineArgs.delete_output_dir:
339+
shutil.rmtree(cmdLineArgs.outputDir)
340+
else:
341+
print("Files generated in: %s" % cmdLineArgs.outputDir)
342+
330343

331344
if __name__ == '__main__':
332345
main()

scripts/tools/zap_regen_all.py

+41-12
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,13 @@ class ZapDistinctOutput:
8181

8282

8383
class ZAPGenerateTarget:
84+
85+
@staticmethod
86+
def MatterIdlTarget(zap_config):
87+
# NOTE: this assumes `src/app/zap-templates/matter-idl.json` is the
88+
# DEFAULT generation target and it needs no output_dir
89+
return ZAPGenerateTarget(zap_config, template=None, output_dir=None)
90+
8491
def __init__(self, zap_config, template, output_dir=None):
8592
self.script = './scripts/tools/zap/generate.py'
8693
self.zap_config = str(zap_config)
@@ -93,7 +100,16 @@ def __init__(self, zap_config, template, output_dir=None):
93100
self.output_dir = None
94101

95102
def distinct_output(self):
96-
return ZapDistinctOutput(input_template=self.template, output_directory=self.output_dir)
103+
if not self.template and not self.output_dir:
104+
# Matter IDL templates have no template/output dir as they go with the
105+
# default.
106+
#
107+
# output_directory is MIS-USED here because zap files may reside in the same
108+
# directory (e.g. chef) so we claim the zap config is an output directory
109+
# for uniqueness
110+
return ZapDistinctOutput(input_template=None, output_directory=self.zap_config)
111+
else:
112+
return ZapDistinctOutput(input_template=self.template, output_directory=self.output_dir)
97113

98114
def log_command(self):
99115
"""Log the command that will get run for this target
@@ -128,7 +144,23 @@ def generate(self) -> TargetRunStats:
128144
generate_end = time.time()
129145

130146
if "chef" in self.zap_config:
131-
af_gen_event = os.path.join(self.output_dir, "af-gen-event.h")
147+
if self.output_dir:
148+
af_gen_event = os.path.join(self.output_dir, "af-gen-event.h")
149+
else:
150+
# location of file is based on zap file, we update a default here.
151+
# This is because matter idl codegen does NOT require an output directory.
152+
#
153+
# a file of:
154+
# examples/chef/devices/rootnode_heatingcoolingunit_ncdGai1E5a.zap
155+
# would get:
156+
# zzz_generated/chef-rootnode_heatingcoolingunit_ncdGai1E5a/zap-generated/af-gen-event.h
157+
#
158+
af_gen_event = os.path.join(
159+
CHIP_ROOT_DIR, 'zzz_generated',
160+
'chef-' + os.path.splitext(os.path.basename(self.zap_config))[0],
161+
'zap-generated', 'af-gen-event.h'
162+
)
163+
132164
with open(af_gen_event, "w+"): # Empty file needed for linux
133165
pass
134166
idl_path = self.zap_config.replace(".zap", ".matter")
@@ -246,10 +278,8 @@ def getGlobalTemplatesTargets():
246278
'zzz_generated', 'placeholder', example_name, 'zap-generated')
247279
template = 'examples/placeholder/templates/templates.json'
248280

249-
targets.append(ZAPGenerateTarget(
250-
filepath, output_dir=output_dir, template="src/app/zap-templates/matter-idl.json"))
251-
targets.append(
252-
ZAPGenerateTarget(filepath, output_dir=output_dir, template=template))
281+
targets.append(ZAPGenerateTarget.MatterIdlTarget(filepath))
282+
targets.append(ZAPGenerateTarget(filepath, output_dir=output_dir, template=template))
253283
continue
254284

255285
if example_name == "chef":
@@ -271,13 +301,9 @@ def getGlobalTemplatesTargets():
271301
# a name like <zap-generated/foo.h>
272302
output_dir = os.path.join(
273303
'zzz_generated', generate_subdir, 'zap-generated')
274-
targets.append(ZAPGenerateTarget(filepath, output_dir=output_dir,
275-
template="src/app/zap-templates/matter-idl.json"))
304+
targets.append(ZAPGenerateTarget.MatterIdlTarget(filepath))
276305

277-
targets.append(ZAPGenerateTarget(
278-
'src/controller/data_model/controller-clusters.zap',
279-
template="src/app/zap-templates/matter-idl.json",
280-
output_dir=os.path.join('zzz_generated/controller-clusters/zap-generated')))
306+
targets.append(ZAPGenerateTarget.MatterIdlTarget('src/controller/data_model/controller-clusters.zap'))
281307

282308
# This generates app headers for darwin only, for easier/clearer include
283309
# in .pbxproj files.
@@ -425,6 +451,9 @@ def main():
425451
for timing in timings:
426452
tmpl = timing.template
427453

454+
if tmpl is None:
455+
tmpl = '[NONE (matter idl generation)]'
456+
428457
if len(tmpl) > 50:
429458
# easier to distinguish paths ... shorten common in-fixes
430459
tmpl = tmpl.replace("/zap-templates/", "/../")

0 commit comments

Comments
 (0)