Skip to content

Commit 1680884

Browse files
andy31415andreilitvinbzbarsky-apple
authored andcommitted
Allow code pre-generation to accept files outside of chip-root (#25970)
* Start supporting separate root pregeneration * Update documentation * Restyle * Fix typos * Fix pregen logic * Update path handling to support full and relative paths, codepregen of external roots now works * Restyle * Update docs/code_generation.md Co-authored-by: Boris Zbarsky <[email protected]> * Update docs/code_generation.md Co-authored-by: Boris Zbarsky <[email protected]> * Update docs/code_generation.md Co-authored-by: Boris Zbarsky <[email protected]> * Slight rephrase * Another rephrase * Restyle * Normalize paths to not be off by one on generation path lenghts --------- Co-authored-by: Andrei Litvin <[email protected]> Co-authored-by: Boris Zbarsky <[email protected]>
1 parent a090481 commit 1680884

File tree

6 files changed

+83
-18
lines changed

6 files changed

+83
-18
lines changed

docs/code_generation.md

+40-1
Original file line numberDiff line numberDiff line change
@@ -234,9 +234,48 @@ scripts/codepregen.py ${OUTPUT_DIRECTORY:-./zzz_pregenerated/}
234234

235235
# To generate a single output you can use `--input-glob`:
236236

237-
scripts/codepregen.py --input-glob "*all-clusters*" ${OUTPUT_DIRECTORY:-./zzz_pregenerated/}
237+
scripts/codepregen.py --input-glob "*all-clusters*" --input-glob "*controller*" ${OUTPUT_DIRECTORY:-./zzz_pregenerated/}
238238
```
239239

240+
### External applications/zap files
241+
242+
#### Ensure you have a `.matter` file
243+
244+
Code generation generally will use both `.zap` or `.matter` files. If you only
245+
have a `.zap` file, you can create the corresponding `.matter` file via:
246+
247+
```bash
248+
scripts/tools/zap/generate.py ${ZAP_FILE_PATH}
249+
```
250+
251+
The above will use the template `src/app/zap-templates/matter-idl.json` to
252+
generate a `.matter` file corresponding to the input `.zap` file.
253+
254+
`.matter` files are designed to be human readable. It is recommended to take a
255+
look at the generated file and see if it contains what is expected and also lint
256+
it. If anything seems wrong, the `.zap` file should be fixed (`.matter`
257+
represents the content of `.zap`). To lint use:
258+
259+
```bash
260+
scripts/idl_lint.py ${MATTER_FILE_PATH}
261+
```
262+
263+
#### Running pre-generation
264+
265+
If you have zap files outside the CHIP repository (i.e. not in `src` or
266+
`examples`) you should provide the root of your application source.
267+
268+
```bash
269+
scripts/codepregen.py --external-root ${PATH_TO_SOURCE_ROOT} ${OUTPUT_DIRECTORY:-./zzz_pregenerated/}
270+
```
271+
272+
NOTE: `$PATH_TO_SOURCE_ROOT` should be a top-level directory containing
273+
zap/matter files as the code pre-generation will generate files based on the
274+
path inside the root:
275+
276+
- if files are `$PATH_TO_SOURCE_ROOT/some/path/foo.zap` this will generate
277+
files into `$OUTPUT_DIRECTORY/some/path/foo/...`
278+
240279
### Using pre-generated code
241280

242281
Instead of generating code at compile time, the chip build system accepts usage

scripts/codepregen.py

+7-2
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,13 @@ def _ParallelGenerateOne(arg):
8585
'--sdk-root',
8686
default=None,
8787
help='Path to the SDK root (where .zap/.matter files exist).')
88+
@click.option(
89+
'--external-root',
90+
default=None,
91+
multiple=True,
92+
help='Path to an external app root (where .zap/.matter files exist).')
8893
@click.argument('output_dir')
89-
def main(log_level, parallel, dry_run, generator, input_glob, sdk_root, output_dir):
94+
def main(log_level, parallel, dry_run, generator, input_glob, sdk_root, external_root, output_dir):
9095
if _has_coloredlogs:
9196
coloredlogs.install(level=__LOG_LEVELS__[
9297
log_level], fmt='%(asctime)s %(levelname)-7s %(message)s')
@@ -122,7 +127,7 @@ def main(log_level, parallel, dry_run, generator, input_glob, sdk_root, output_d
122127
elif generator == 'codegen':
123128
filter.file_type = IdlFileType.MATTER
124129

125-
targets = FindPregenerationTargets(sdk_root, filter, runner)
130+
targets = FindPregenerationTargets(sdk_root, external_root, filter, runner)
126131

127132
runner.ensure_directory_exists(output_dir)
128133
if parallel:

scripts/pregenerate/__init__.py

+26-11
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,20 @@
2525
from .using_zap import ZapApplicationPregenerator
2626

2727

28-
def FindAllIdls(sdk_root: str) -> Iterator[InputIdlFile]:
28+
def _IdlsInDirectory(top_directory_name: str, truncate_length: int):
29+
for root, dirs, files in os.walk(top_directory_name):
30+
for file in files:
31+
if file.endswith('.zap'):
32+
yield InputIdlFile(file_type=IdlFileType.ZAP,
33+
full_path=os.path.join(root, file),
34+
relative_path=os.path.join(root[truncate_length:], file))
35+
if file.endswith('.matter'):
36+
yield InputIdlFile(file_type=IdlFileType.MATTER,
37+
full_path=os.path.join(root, file),
38+
relative_path=os.path.join(root[truncate_length:], file))
39+
40+
41+
def _FindAllIdls(sdk_root: str, external_roots: Optional[List[str]]) -> Iterator[InputIdlFile]:
2942
relevant_subdirs = [
3043
'examples', # all example apps
3144
'src', # realistically only controller/data_model
@@ -35,17 +48,19 @@ def FindAllIdls(sdk_root: str) -> Iterator[InputIdlFile]:
3548
sdk_root = sdk_root[:-1]
3649
sdk_root_length = len(sdk_root)
3750

51+
# first go over SDK items
3852
for subdir_name in relevant_subdirs:
3953
top_directory_name = os.path.join(sdk_root, subdir_name)
4054
logging.debug(f"Searching {top_directory_name}")
41-
for root, dirs, files in os.walk(top_directory_name):
42-
for file in files:
43-
if file.endswith('.zap'):
44-
yield InputIdlFile(file_type=IdlFileType.ZAP,
45-
relative_path=os.path.join(root[sdk_root_length+1:], file))
46-
if file.endswith('.matter'):
47-
yield InputIdlFile(file_type=IdlFileType.MATTER,
48-
relative_path=os.path.join(root[sdk_root_length+1:], file))
55+
for idl in _IdlsInDirectory(top_directory_name, sdk_root_length+1):
56+
yield idl
57+
58+
# next external roots
59+
if external_roots:
60+
for root in external_roots:
61+
root = os.path.normpath(root)
62+
for idl in _IdlsInDirectory(root, len(root) + 1):
63+
yield idl
4964

5065

5166
@dataclass
@@ -67,7 +82,7 @@ def matches(self, s: str):
6782
return fnmatch.fnmatch(s, self.pattern)
6883

6984

70-
def FindPregenerationTargets(sdk_root: str, filter: TargetFilter, runner):
85+
def FindPregenerationTargets(sdk_root: str, external_roots: Optional[List[str]], filter: TargetFilter, runner):
7186
"""Finds all relevand pre-generation targets in the given
7287
SDK root.
7388
@@ -88,7 +103,7 @@ def FindPregenerationTargets(sdk_root: str, filter: TargetFilter, runner):
88103

89104
path_matchers = [GlobMatcher(pattern) for pattern in filter.path_glob]
90105

91-
for idl in FindAllIdls(sdk_root):
106+
for idl in _FindAllIdls(sdk_root, external_roots):
92107
if filter.file_type is not None:
93108
if idl.file_type != filter.file_type:
94109
logging.debug(f"Will not process file of type {idl.file_type}: {idl.relative_path}")

scripts/pregenerate/types.py

+1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ class IdlFileType(Enum):
2626
class InputIdlFile:
2727
file_type: IdlFileType
2828
relative_path: str
29+
full_path: str
2930

3031
@property
3132
def pregen_subdir(self):

scripts/pregenerate/using_codegen.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -44,14 +44,14 @@ def Generate(self, output_root: str):
4444
output_root, self.idl.pregen_subdir, self.generator)
4545

4646
logging.info(
47-
f"Generating: {self.generator}:{self.idl.relative_path} into {output_dir}")
47+
f"Generating: {self.generator}:{self.idl.full_path} into {output_dir}")
4848

4949
cmd = [
5050
CODEGEN_PY_PATH,
5151
'--log-level', 'fatal',
5252
'--generator', self.generator,
5353
'--output-dir', output_dir,
54-
os.path.join(self.sdk_root, self.idl.relative_path)
54+
self.idl.full_path
5555
]
5656

5757
logging.debug(f"Executing {cmd}")

scripts/pregenerate/using_zap.py

+7-2
Original file line numberDiff line numberDiff line change
@@ -56,16 +56,21 @@ def Generate(self, output_root: str):
5656

5757
output_dir = os.path.join(output_root, self.idl.pregen_subdir, self.generation_type.subdir)
5858

59-
logging.info(f"Generating: {self.generation_type}:{self.idl.relative_path} into {output_dir}")
59+
logging.info(f"Generating: {self.generation_type}:{self.idl.full_path} into {output_dir}")
6060

6161
self.runner.ensure_directory_exists(output_dir)
6262

63+
if self.idl.full_path.startswith(self.sdk_root):
64+
idl_path = self.idl.relative_path
65+
else:
66+
idl_path = self.idl.full_path
67+
6368
cmd = [
6469
ZAP_GENERATE_PATH,
6570
'--templates', self.generation_type.generation_template,
6671
'--output-dir', output_dir,
6772
'--parallel',
68-
self.idl.relative_path
73+
idl_path
6974
]
7075
logging.debug(f"Executing {cmd}")
7176
self.runner.run(cmd, cwd=self.sdk_root)

0 commit comments

Comments
 (0)