idf-build-apps 2.4.1__py3-none-any.whl → 2.4.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -8,7 +8,7 @@ Tools for building ESP-IDF related apps.
8
8
  # ruff: noqa: E402
9
9
  # avoid circular imports
10
10
 
11
- __version__ = '2.4.1'
11
+ __version__ = '2.4.2'
12
12
 
13
13
  from .session_args import (
14
14
  SessionArgs,
idf_build_apps/app.py CHANGED
@@ -10,9 +10,7 @@ import re
10
10
  import shutil
11
11
  import sys
12
12
  import typing as t
13
- from datetime import (
14
- datetime,
15
- )
13
+ from datetime import datetime, timezone
16
14
  from pathlib import (
17
15
  Path,
18
16
  )
@@ -153,10 +151,12 @@ class App(BaseModel):
153
151
  size_json_filename: t.Optional[str] = None,
154
152
  **kwargs: t.Any,
155
153
  ) -> None:
156
- kwargs.update({
157
- 'app_dir': app_dir,
158
- 'target': target,
159
- })
154
+ kwargs.update(
155
+ {
156
+ 'app_dir': app_dir,
157
+ 'target': target,
158
+ }
159
+ )
160
160
  super().__init__(**kwargs)
161
161
 
162
162
  # These internal variables store the paths with environment variables and placeholders;
@@ -169,12 +169,14 @@ class App(BaseModel):
169
169
  self._is_build_log_path_temp = not bool(build_log_filename)
170
170
 
171
171
  # pass all parameters to initialize hook method
172
- kwargs.update({
173
- 'work_dir': self._work_dir,
174
- 'build_dir': self._build_dir,
175
- 'build_log_filename': build_log_filename,
176
- 'size_json_filename': size_json_filename,
177
- })
172
+ kwargs.update(
173
+ {
174
+ 'work_dir': self._work_dir,
175
+ 'build_dir': self._build_dir,
176
+ 'build_log_filename': build_log_filename,
177
+ 'size_json_filename': size_json_filename,
178
+ }
179
+ )
178
180
  self._kwargs = kwargs
179
181
  self._initialize_hook(**kwargs)
180
182
 
@@ -472,11 +474,11 @@ class App(BaseModel):
472
474
  def record_build_duration(func):
473
475
  @functools.wraps(func)
474
476
  def wrapper(self, *args, **kwargs):
475
- self._build_timestamp = datetime.utcnow()
477
+ self._build_timestamp = datetime.now(timezone.utc)
476
478
  try:
477
479
  return func(self, *args, **kwargs)
478
480
  finally:
479
- self._build_duration = (datetime.utcnow() - self._build_timestamp).total_seconds()
481
+ self._build_duration = (datetime.now(timezone.utc) - self._build_timestamp).total_seconds()
480
482
 
481
483
  return wrapper
482
484
 
@@ -544,6 +546,14 @@ class App(BaseModel):
544
546
  modified_files: t.Union[t.List[str], str, None] = None,
545
547
  check_app_dependencies: bool = False,
546
548
  ) -> None:
549
+ if self.build_status not in (
550
+ BuildStatus.UNKNOWN,
551
+ BuildStatus.SHOULD_BE_BUILT,
552
+ ):
553
+ self.build_comment = f'Build {self.build_status.value}. Skipping...'
554
+ return
555
+
556
+ # real build starts here
547
557
  self._pre_build()
548
558
 
549
559
  try:
@@ -560,8 +570,16 @@ class App(BaseModel):
560
570
  self._post_build()
561
571
 
562
572
  def _post_build(self) -> None:
573
+ """Post build actions for failed/success builds"""
574
+ if self.build_status not in (
575
+ BuildStatus.FAILED,
576
+ BuildStatus.SUCCESS,
577
+ ):
578
+ return
579
+
563
580
  self._build_stage = BuildStage.POST_BUILD
564
581
 
582
+ # both status applied
565
583
  if self.copy_sdkconfig:
566
584
  try:
567
585
  shutil.copy(
@@ -573,12 +591,21 @@ class App(BaseModel):
573
591
  else:
574
592
  self._logger.debug('Copied sdkconfig file from %s to %s', self.work_dir, self.build_path)
575
593
 
594
+ # for originally success builds generate size.json if enabled
595
+ #
596
+ # for the rest of the actions, we need to check if there's further build warnings
597
+ # to tell if this build is successful or not
598
+ if self.build_status == BuildStatus.SUCCESS:
599
+ self.write_size_json()
600
+
576
601
  if not os.path.isfile(self.build_log_path):
602
+ self._logger.warning(f'{self.build_log_path} does not exist. Skipping post build actions...')
577
603
  return
578
604
 
605
+ # check warnings
579
606
  has_unignored_warning = False
580
607
  with open(self.build_log_path) as fr:
581
- lines = [line.rstrip() for line in fr.readlines() if line.rstrip()]
608
+ lines = [line.rstrip() for line in fr if line.rstrip()]
582
609
  for line in lines:
583
610
  is_error_or_warning, ignored = self.is_error_or_warning(line)
584
611
  if is_error_or_warning:
@@ -588,6 +615,14 @@ class App(BaseModel):
588
615
  self._logger.warning('%s', line)
589
616
  has_unignored_warning = True
590
617
 
618
+ # correct build status for originally successful builds
619
+ if self.build_status == BuildStatus.SUCCESS:
620
+ if self.check_warnings and has_unignored_warning:
621
+ self.build_status = BuildStatus.FAILED
622
+ self.build_comment = 'build succeeded with warnings'
623
+ elif has_unignored_warning:
624
+ self.build_comment = 'build succeeded with warnings'
625
+
591
626
  if self.build_status == BuildStatus.FAILED:
592
627
  # print last few lines to help debug
593
628
  self._logger.error(
@@ -598,14 +633,14 @@ class App(BaseModel):
598
633
  for line in lines[-self.LOG_DEBUG_LINES :]:
599
634
  self._logger.error('%s', line)
600
635
 
601
- if self._is_build_log_path_temp and self.build_status == BuildStatus.SUCCESS:
636
+ return
637
+
638
+ # Actions for real success builds
639
+ # remove temp log file
640
+ if self._is_build_log_path_temp:
602
641
  os.unlink(self.build_log_path)
603
642
  self._logger.debug('Removed success build temporary log file: %s', self.build_log_path)
604
643
 
605
- # Generate Size Files
606
- if self.build_status == BuildStatus.SUCCESS:
607
- self.write_size_json()
608
-
609
644
  # Cleanup build directory if not preserving
610
645
  if not self.preserve:
611
646
  exclude_list = []
@@ -619,13 +654,6 @@ class App(BaseModel):
619
654
  )
620
655
  self._logger.debug('Removed built binaries under: %s', self.build_path)
621
656
 
622
- # Build Result
623
- if self.check_warnings and has_unignored_warning:
624
- self.build_status = BuildStatus.FAILED
625
- self.build_comment = 'build succeeded with warnings'
626
- elif has_unignored_warning:
627
- self.build_comment = 'build succeeded with warnings'
628
-
629
657
  def _build(
630
658
  self,
631
659
  *,
@@ -665,12 +693,14 @@ class App(BaseModel):
665
693
  else:
666
694
  with open(self.size_json_path, 'w') as fw:
667
695
  subprocess_run(
668
- ([
669
- sys.executable,
670
- str(IDF_SIZE_PY),
671
- '--json',
672
- map_file,
673
- ]),
696
+ (
697
+ [
698
+ sys.executable,
699
+ str(IDF_SIZE_PY),
700
+ '--json',
701
+ map_file,
702
+ ]
703
+ ),
674
704
  log_terminal=False,
675
705
  log_fs=fw,
676
706
  check=True,
@@ -922,7 +952,7 @@ class CMakeApp(App):
922
952
  '-DSDKCONFIG_DEFAULTS={}'.format(';'.join(self.sdkconfig_files) if self.sdkconfig_files else ';'),
923
953
  ]
924
954
 
925
- if modified_components is not None and check_app_dependencies and self.build_status == BuildStatus.UNKNOWN:
955
+ if self.build_status == BuildStatus.UNKNOWN and modified_components is not None and check_app_dependencies:
926
956
  subprocess_run(
927
957
  [*common_args, 'reconfigure'],
928
958
  log_terminal=self._is_build_log_path_temp,
@@ -80,6 +80,7 @@ IDF_VERSION = to_version(f'{IDF_VERSION_MAJOR}.{IDF_VERSION_MINOR}.{IDF_VERSION_
80
80
 
81
81
  class BuildStatus(str, enum.Enum):
82
82
  UNKNOWN = 'unknown'
83
+ DISABLED = 'disabled'
83
84
  SKIPPED = 'skipped'
84
85
  SHOULD_BE_BUILT = 'should be built'
85
86
  FAILED = 'build failed'
@@ -98,14 +99,14 @@ class BuildStage(str, enum.Enum):
98
99
 
99
100
 
100
101
  completion_instructions = """
101
- With `--activate` option detect your shell type and add the appropriate commands to your shell's config file
102
- so that it is run on startup. You will likely have to restart
102
+ With the `--activate` option, detect your shell type and add the appropriate commands to your shell's config file
103
+ so that it runs on startup. You will likely have to restart.
103
104
  or re-login for the autocompletion to start working.
104
105
 
105
- You can also specify your shell by the `--shell` option.
106
+ You can also specify your shell using the `--shell` option.
106
107
 
107
- If you do not want automaticall modifying your shell config file
108
- you can manually add commands provided below to activate autocompletion
108
+ If you do not want automatic modification of your shell configuration file
109
+ You can manually add the commands provided below to activate autocompletion.
109
110
  or run them in your current terminal session for one-time activation.
110
111
 
111
112
  Once again, you will likely have to restart
idf_build_apps/finder.py CHANGED
@@ -1,4 +1,4 @@
1
- # SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
1
+ # SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
2
2
  # SPDX-License-Identifier: Apache-2.0
3
3
 
4
4
  import logging
@@ -43,6 +43,7 @@ def _get_apps_from_path(
43
43
  check_app_dependencies: bool = False,
44
44
  sdkconfig_defaults_str: t.Optional[str] = None,
45
45
  include_skipped_apps: bool = False,
46
+ include_disabled_apps: bool = False,
46
47
  ) -> t.List[App]:
47
48
  modified_components = to_list(modified_components)
48
49
  modified_files = to_list(modified_files)
@@ -50,7 +51,8 @@ def _get_apps_from_path(
50
51
  def _validate_app(_app: App) -> bool:
51
52
  if target not in _app.supported_targets:
52
53
  LOGGER.debug('=> Ignored. %s only supports targets: %s', _app, ', '.join(_app.supported_targets))
53
- return False
54
+ _app.build_status = BuildStatus.DISABLED
55
+ return include_disabled_apps
54
56
 
55
57
  _app._check_should_build(
56
58
  manifest_rootpath=manifest_rootpath,
@@ -38,6 +38,7 @@ import os.path
38
38
  import typing as t
39
39
  from datetime import (
40
40
  datetime,
41
+ timezone,
41
42
  )
42
43
  from xml.etree import (
43
44
  ElementTree,
@@ -81,14 +82,17 @@ class TestCase:
81
82
  raise ValueError('Only one of failure_reason, skipped_reason, error_reason can be set')
82
83
 
83
84
  self.duration_sec = duration_sec
84
- self.timestamp = timestamp or datetime.utcnow()
85
+ self.timestamp = timestamp or datetime.now(timezone.utc)
85
86
 
86
87
  self.properties = properties or {}
87
88
 
88
89
  @classmethod
89
90
  def from_app(cls, app: App) -> 'TestCase':
90
- if app.build_status not in (BuildStatus.FAILED, BuildStatus.SUCCESS, BuildStatus.SKIPPED):
91
- raise ValueError(f'Cannot create test case from app with build status {app.build_status}')
91
+ if app.build_status in (BuildStatus.UNKNOWN, BuildStatus.SHOULD_BE_BUILT):
92
+ raise ValueError(
93
+ f'Cannot create build report for apps with build status {app.build_status}. '
94
+ f'Please finish the build process first.'
95
+ )
92
96
 
93
97
  kwargs: t.Dict[str, t.Any] = {
94
98
  'name': app.build_path,
@@ -98,7 +102,7 @@ class TestCase:
98
102
  }
99
103
  if app.build_status == BuildStatus.FAILED:
100
104
  kwargs['failure_reason'] = app.build_comment
101
- elif app.build_status == BuildStatus.SKIPPED:
105
+ elif app.build_status in (BuildStatus.DISABLED, BuildStatus.SKIPPED):
102
106
  kwargs['skipped_reason'] = app.build_comment
103
107
 
104
108
  if app.size_json_path and os.path.isfile(app.size_json_path):
@@ -106,7 +110,7 @@ class TestCase:
106
110
  for k, v in json.load(f).items():
107
111
  kwargs['properties'][f'{k}'] = str(v)
108
112
 
109
- return cls(**kwargs) # type
113
+ return cls(**kwargs)
110
114
 
111
115
  @property
112
116
  def is_failed(self) -> bool:
@@ -155,7 +159,7 @@ class TestSuite:
155
159
  self.skipped = 0
156
160
 
157
161
  self.duration_sec: float = 0
158
- self.timestamp = datetime.utcnow()
162
+ self.timestamp = datetime.now(timezone.utc)
159
163
 
160
164
  self.properties = get_sys_info()
161
165
 
@@ -1,4 +1,4 @@
1
- # SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
1
+ # SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
2
2
  # SPDX-License-Identifier: Apache-2.0
3
3
 
4
4
  import os
@@ -26,7 +26,7 @@ def get_processor_name():
26
26
  if os.path.isfile('/proc/cpuinfo'):
27
27
  try:
28
28
  with open('/proc/cpuinfo') as f:
29
- for line in f.readlines():
29
+ for line in f:
30
30
  if 'model name' in line:
31
31
  return re.sub('.*model name.*:', '', line, 1).strip()
32
32
  except Exception:
idf_build_apps/main.py CHANGED
@@ -11,6 +11,7 @@ import re
11
11
  import sys
12
12
  import textwrap
13
13
  import typing as t
14
+ from copy import deepcopy
14
15
 
15
16
  import argcomplete
16
17
  from pydantic import (
@@ -127,6 +128,7 @@ def find_apps(
127
128
  ignore_app_dependencies_filepatterns: t.Optional[t.Union[t.List[str], str]] = None,
128
129
  sdkconfig_defaults: t.Optional[str] = None,
129
130
  include_skipped_apps: bool = False,
131
+ include_disabled_apps: bool = False,
130
132
  ) -> t.List[App]:
131
133
  """
132
134
  Find app directories in paths (possibly recursively), which contain apps for the given build system, compatible
@@ -158,6 +160,7 @@ def find_apps(
158
160
  :param sdkconfig_defaults: semicolon-separated string, pass to idf.py -DSDKCONFIG_DEFAULTS if specified,
159
161
  also could be set via environment variables "SDKCONFIG_DEFAULTS"
160
162
  :param include_skipped_apps: include skipped apps or not
163
+ :param include_disabled_apps: include disabled apps or not
161
164
  :return: list of found apps
162
165
  """
163
166
  if default_build_targets:
@@ -223,6 +226,7 @@ def find_apps(
223
226
  modified_files=modified_files,
224
227
  sdkconfig_defaults_str=sdkconfig_defaults,
225
228
  include_skipped_apps=include_skipped_apps,
229
+ include_disabled_apps=include_disabled_apps,
226
230
  )
227
231
  )
228
232
 
@@ -365,12 +369,14 @@ def build_apps(
365
369
  if os.path.isfile(app.size_json_path):
366
370
  with open(build_apps_args.collect_size_info, 'a') as fw:
367
371
  fw.write(
368
- json.dumps({
369
- 'app_name': app.name,
370
- 'config_name': app.config_name,
371
- 'target': app.target,
372
- 'path': app.size_json_path,
373
- })
372
+ json.dumps(
373
+ {
374
+ 'app_name': app.name,
375
+ 'config_name': app.config_name,
376
+ 'target': app.target,
377
+ 'path': app.size_json_path,
378
+ }
379
+ )
374
380
  + '\n'
375
381
  )
376
382
  LOGGER.debug('Recorded size info file path in %s', build_apps_args.collect_size_info)
@@ -551,14 +557,19 @@ def get_parser() -> argparse.ArgumentParser:
551
557
  action='store_true',
552
558
  help='Exit with error if any of the manifest rules does not exist on your filesystem',
553
559
  )
554
-
560
+ common_args.add_argument(
561
+ '--enable-preview-targets',
562
+ action='store_true',
563
+ help='Build the apps with all targets in the current ESP-IDF branch, '
564
+ 'including preview targets, when the app supports the target.',
565
+ )
555
566
  common_args.add_argument(
556
567
  '--default-build-targets',
557
568
  nargs='+',
558
- help='space-separated list of supported targets. Targets supported in current ESP-IDF branch '
559
- '(except preview ones) would be used if this option is not set.',
569
+ help='space-separated list of string which specifies the targets for building the apps. '
570
+ 'If provided, the apps will be built only with the specified targets '
571
+ 'when the app supports the target.',
560
572
  )
561
-
562
573
  common_args.add_argument(
563
574
  '--modified-components',
564
575
  type=semicolon_separated_str_to_list,
@@ -610,7 +621,7 @@ def get_parser() -> argparse.ArgumentParser:
610
621
 
611
622
  find_parser = actions.add_parser(
612
623
  'find',
613
- help='Find the buildable applications. Run `idf-build-apps find --help` for more information on a command',
624
+ help='Find the buildable applications. Run `idf-build-apps find --help` for more information on a command.',
614
625
  description='Find the buildable applications in the given path or paths for specified chips. '
615
626
  '`--path` and `--target` options must be provided. '
616
627
  'By default, print the found apps in stdout. '
@@ -618,12 +629,23 @@ def get_parser() -> argparse.ArgumentParser:
618
629
  parents=[common_args],
619
630
  formatter_class=IdfBuildAppsCliFormatter,
620
631
  )
621
-
622
632
  find_parser.add_argument('-o', '--output', help='Print the found apps to the specified file instead of stdout')
633
+ find_parser.add_argument(
634
+ '--output-format',
635
+ choices=['raw', 'json'],
636
+ default='raw',
637
+ help='Output format. In "raw" format, each line is a valid json that represents the app. '
638
+ 'In "json" format, the whole file is a JSON file of a list of apps.',
639
+ )
640
+ find_parser.add_argument(
641
+ '--include-all-apps',
642
+ action='store_true',
643
+ help='Include skipped and disabled apps. By default only apps that should be built.',
644
+ )
623
645
 
624
646
  build_parser = actions.add_parser(
625
647
  'build',
626
- help='Build the found applications. Run `idf-build-apps build --help` for more information on a command',
648
+ help='Build the found applications. Run `idf-build-apps build --help` for more information on a command.',
627
649
  description='Build the application in the given path or paths for specified chips. '
628
650
  '`--path` and `--target` options must be provided.',
629
651
  parents=[common_args],
@@ -696,18 +718,18 @@ def get_parser() -> argparse.ArgumentParser:
696
718
  completions_parser = actions.add_parser(
697
719
  'completions',
698
720
  help='Add the autocompletion activation script to the shell rc file. '
699
- 'Run `idf-build-apps complations --help` for more information on a command',
721
+ 'Run `idf-build-apps completions --help` for more information on a command.',
700
722
  description='Without `--activate` option print instructions for manual activation. '
701
- 'With `--activate` option add the autocompletion activation script to the shell rc file '
702
- 'for bash, zsh, or fish. Other shells are not supported. '
703
- 'The `--shell` option used only with the `--activate` option, '
723
+ 'With the `--activate` option, add the autocompletion activation script to the shell rc file '
724
+ 'for bash, zsh, or fish. Other shells are not supported.'
725
+ 'The `--shell` option is used only with the `--activate` option, '
704
726
  'if provided, add the autocompletion activation script to the given shell; '
705
727
  'without this argument, will detect shell type automatically. '
706
728
  'May need to restart or re-login for the autocompletion to start working',
707
729
  formatter_class=IdfBuildAppsCliFormatter,
708
730
  )
709
731
  completions_parser.add_argument(
710
- '-a', '--activate', action='store_true', help='Activate autocompletion automatically and permanently'
732
+ '-a', '--activate', action='store_true', help='Activate autocompletion automatically and permanently. '
711
733
  )
712
734
  completions_parser.add_argument(
713
735
  '-s',
@@ -751,14 +773,15 @@ def validate_args(parser: argparse.ArgumentParser, args: argparse.Namespace) ->
751
773
  if args.default_build_targets:
752
774
  for target in args.default_build_targets:
753
775
  if target not in ALL_TARGETS:
754
- raise InvalidCommand(
755
- f'Unrecognizable target {target} specified with "--default-build-targets". '
776
+ LOGGER.warning(
777
+ f'Ignoring... Unrecognizable target {target} specified with "--default-build-targets". '
756
778
  f'Current ESP-IDF available targets: {ALL_TARGETS}'
757
779
  )
758
-
759
- if target not in default_build_targets:
780
+ elif target not in default_build_targets:
760
781
  default_build_targets.append(target)
761
- args.default_build_targets = default_build_targets
782
+ args.default_build_targets = default_build_targets
783
+ elif args.enable_preview_targets:
784
+ args.default_build_targets = deepcopy(ALL_TARGETS)
762
785
 
763
786
  if args.ignore_app_dependencies_components is not None:
764
787
  if args.modified_components is None:
@@ -796,36 +819,49 @@ def main():
796
819
  if args.action == 'build':
797
820
  args.output = None # build action doesn't support output option
798
821
 
822
+ kwargs = {
823
+ 'build_system': args.build_system,
824
+ 'recursive': args.recursive,
825
+ 'exclude_list': args.exclude or [],
826
+ 'work_dir': args.work_dir,
827
+ 'build_dir': args.build_dir or 'build',
828
+ 'config_rules_str': args.config,
829
+ 'build_log_filename': args.build_log,
830
+ 'size_json_filename': args.size_file,
831
+ 'check_warnings': args.check_warnings,
832
+ 'manifest_rootpath': args.manifest_rootpath,
833
+ 'manifest_files': args.manifest_file,
834
+ 'check_manifest_rules': args.check_manifest_rules,
835
+ 'default_build_targets': args.default_build_targets,
836
+ 'modified_components': args.modified_components,
837
+ 'modified_files': args.modified_files,
838
+ 'ignore_app_dependencies_components': args.ignore_app_dependencies_components,
839
+ 'ignore_app_dependencies_filepatterns': args.ignore_app_dependencies_filepatterns,
840
+ 'sdkconfig_defaults': args.sdkconfig_defaults,
841
+ }
842
+ # only useful in find
843
+ if args.action == 'find' and args.include_all_apps:
844
+ kwargs['include_skipped_apps'] = True
845
+ kwargs['include_disabled_apps'] = True
846
+
799
847
  # real call starts here
800
- apps = find_apps(
801
- args.paths,
802
- args.target,
803
- build_system=args.build_system,
804
- recursive=args.recursive,
805
- exclude_list=args.exclude or [],
806
- work_dir=args.work_dir,
807
- build_dir=args.build_dir or 'build',
808
- config_rules_str=args.config,
809
- build_log_filename=args.build_log,
810
- size_json_filename=args.size_file,
811
- check_warnings=args.check_warnings,
812
- manifest_rootpath=args.manifest_rootpath,
813
- manifest_files=args.manifest_file,
814
- check_manifest_rules=args.check_manifest_rules,
815
- default_build_targets=args.default_build_targets,
816
- modified_components=args.modified_components,
817
- modified_files=args.modified_files,
818
- ignore_app_dependencies_components=args.ignore_app_dependencies_components,
819
- ignore_app_dependencies_filepatterns=args.ignore_app_dependencies_filepatterns,
820
- sdkconfig_defaults=args.sdkconfig_defaults,
821
- )
848
+ apps = find_apps(args.paths, args.target, **kwargs)
822
849
 
823
850
  if args.action == 'find':
824
851
  if args.output:
825
852
  os.makedirs(os.path.dirname(os.path.realpath(args.output)), exist_ok=True)
853
+ if args.output.endswith('.json'):
854
+ LOGGER.info('Detecting output file ends with ".json", writing json file.')
855
+ args.output_format = 'json'
856
+
826
857
  with open(args.output, 'w') as fw:
827
- for app in apps:
828
- fw.write(app.to_json() + '\n')
858
+ if args.output_format == 'raw':
859
+ for app in apps:
860
+ fw.write(app.to_json() + '\n')
861
+ elif args.output_format == 'json':
862
+ fw.write(json.dumps([app.model_dump() for app in apps], indent=2))
863
+ else:
864
+ raise ValueError(f'Output format {args.output_format} is not supported.')
829
865
  else:
830
866
  for app in apps:
831
867
  print(app)
@@ -94,20 +94,24 @@ class SocHeader(dict):
94
94
 
95
95
  @classmethod
96
96
  def _parse_soc_header(cls, target: str) -> t.Dict[str, t.Any]:
97
- soc_headers_dirs = cls._get_dirs_from_candidates([
98
- # master c5 mp
99
- os.path.abspath(os.path.join(IDF_PATH, 'components', 'soc', target, 'mp', 'include', 'soc')),
100
- # other branches
101
- os.path.abspath(os.path.join(IDF_PATH, 'components', 'soc', target, 'include', 'soc')),
102
- # release/v4.2
103
- os.path.abspath(os.path.join(IDF_PATH, 'components', 'soc', 'soc', target, 'include', 'soc')),
104
- ])
105
- esp_rom_headers_dirs = cls._get_dirs_from_candidates([
106
- # master c5 mp
107
- os.path.abspath(os.path.join(IDF_PATH, 'components', 'esp_rom', target, 'mp', target)),
108
- # others
109
- os.path.abspath(os.path.join(IDF_PATH, 'components', 'esp_rom', target)),
110
- ])
97
+ soc_headers_dirs = cls._get_dirs_from_candidates(
98
+ [
99
+ # master c5 mp
100
+ os.path.abspath(os.path.join(IDF_PATH, 'components', 'soc', target, 'mp', 'include', 'soc')),
101
+ # other branches
102
+ os.path.abspath(os.path.join(IDF_PATH, 'components', 'soc', target, 'include', 'soc')),
103
+ # release/v4.2
104
+ os.path.abspath(os.path.join(IDF_PATH, 'components', 'soc', 'soc', target, 'include', 'soc')),
105
+ ]
106
+ )
107
+ esp_rom_headers_dirs = cls._get_dirs_from_candidates(
108
+ [
109
+ # master c5 mp
110
+ os.path.abspath(os.path.join(IDF_PATH, 'components', 'esp_rom', target, 'mp', target)),
111
+ # others
112
+ os.path.abspath(os.path.join(IDF_PATH, 'components', 'esp_rom', target)),
113
+ ]
114
+ )
111
115
 
112
116
  header_files: t.List[str] = []
113
117
  for d in [*soc_headers_dirs, *esp_rom_headers_dirs]:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: idf-build-apps
3
- Version: 2.4.1
3
+ Version: 2.4.2
4
4
  Summary: Tools for building ESP-IDF related apps.
5
5
  Author-email: Fu Hanxi <fuhanxi@espressif.com>
6
6
  Requires-Python: >=3.7
@@ -1,26 +1,26 @@
1
- idf_build_apps/__init__.py,sha256=RpyMLjmi3aM04B7-M-j6BguTlsj0Q5ofPZ9E_Tv3k80,650
1
+ idf_build_apps/__init__.py,sha256=BwKVA9OBak7HwLAOrcfYb-ir3L5sCQDsB_FC7GO4KjE,650
2
2
  idf_build_apps/__main__.py,sha256=8E-5xHm2MlRun0L88XJleNh5U50dpE0Q1nK5KqomA7I,182
3
- idf_build_apps/app.py,sha256=z6i55q_XaMjea34_nbAKgNTU-qOEkO_qTHCYSeQNUFw,35887
3
+ idf_build_apps/app.py,sha256=q9udvZyBG3qWrNxlyuG3iTiLcayOSrSwRuyL2n7QALY,37002
4
4
  idf_build_apps/autocompletions.py,sha256=g-bx0pzXoFKI0VQqftkHyGVWN6MLjuFOdozeuAf45yo,2138
5
5
  idf_build_apps/build_apps_args.py,sha256=r6VCJDdCzE873X8OTputYkCBZPgECaKoNlAejfcamJk,1644
6
6
  idf_build_apps/config.py,sha256=I75uOQGarCWVKGi16ZYpo0qTVU25BUP4eh6-RWCtbvw,2924
7
- idf_build_apps/constants.py,sha256=s-b-wAKjrIjF4tAspJBkXaDVC6HMX3Hv1mM2vGuLrB8,3952
8
- idf_build_apps/finder.py,sha256=qw5moNq7U5mHSsR0CCfGkKE9p4QsWYNcfkxzeQ73HgM,6252
7
+ idf_build_apps/constants.py,sha256=8Bh99xGFpyLkEovQMglS2KydxoEZesAHQSgdpsUnSTM,4000
8
+ idf_build_apps/finder.py,sha256=2TOQ6fq9q3MtsLnG4o0VvA2aMd3Zb6w6CL-U_tQrT3k,6362
9
9
  idf_build_apps/log.py,sha256=JysogBHoompfW9E9w0U4wZH7tt8dBdfoh-stPXQz1hw,2573
10
- idf_build_apps/main.py,sha256=17w4VaIjmdbosBqU7EF4-0gziM6veslQOBPH_JXK75U,37293
10
+ idf_build_apps/main.py,sha256=wKDt5iQKjpDmxJecPJMMMYb2kDI2qIRH_Qlkg3u6jlY,39199
11
11
  idf_build_apps/session_args.py,sha256=2WDTy40IFAc0KQ57HaeBcYj_k10eUXRKkDOWLrFCaHY,2985
12
12
  idf_build_apps/utils.py,sha256=dYxNXPe7FRWxzUFlTzOb3G-LpKpRUrNWdQrsO5MXAB8,9702
13
13
  idf_build_apps/junit/__init__.py,sha256=IxvdaS6eSXp7kZxRuXqyZyGxuA_A1nOW1jF1HMi8Gns,231
14
- idf_build_apps/junit/report.py,sha256=vHE5RcBa7Bj4a1p2lXaTh0m9eJIO_uTGrOnJg8NEi4I,6430
15
- idf_build_apps/junit/utils.py,sha256=gtibRs8WTE8IXTIAS73QR_k_jrJlOjCl2y-9KiP5_Nk,1304
14
+ idf_build_apps/junit/report.py,sha256=T7dVU3Sz5tqjfbcFW7wjsb65PDH6C2HFf73ePJqBhMs,6555
15
+ idf_build_apps/junit/utils.py,sha256=j0PYhFTZjXtTwkENdeL4bFJcX24ktf1CsOOVXz65yNo,1297
16
16
  idf_build_apps/manifest/__init__.py,sha256=Q2-cb3ngNjnl6_zWhUfzZZB10f_-Rv2JYNck3Lk7UkQ,133
17
17
  idf_build_apps/manifest/if_parser.py,sha256=r0pivV9gmniPn3Ia6sTMbW5tFAKInhOXk-Lfd6GokqE,6381
18
18
  idf_build_apps/manifest/manifest.py,sha256=P5ZaUd72A_HOVF6iuwap__Bw-w7WI72ugiTURm9PNNQ,10708
19
- idf_build_apps/manifest/soc_header.py,sha256=_edrD1sYGUHZTksBxCVO5HwhJr_7KaePaEAjc_z4S-E,4252
19
+ idf_build_apps/manifest/soc_header.py,sha256=PzJ37xFspt5f0AXWvAFNA_avHZA9fMXHBrwDYLi3qEI,4344
20
20
  idf_build_apps/yaml/__init__.py,sha256=W-3z5no07RQ6eYKGyOAPA8Z2CLiMPob8DD91I4URjrA,162
21
21
  idf_build_apps/yaml/parser.py,sha256=Y2OyB4g1DCC7C7jrvpIyZV9lgeCB_XvuB75iGmqiTaM,2093
22
- idf_build_apps-2.4.1.dist-info/entry_points.txt,sha256=3pVUirUEsb6jsDRikkQWNUt4hqLK2ci1HvW_Vf8b6uE,59
23
- idf_build_apps-2.4.1.dist-info/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
24
- idf_build_apps-2.4.1.dist-info/WHEEL,sha256=EZbGkh7Ie4PoZfRQ8I0ZuP9VklN_TvcZ6DSE5Uar4z4,81
25
- idf_build_apps-2.4.1.dist-info/METADATA,sha256=V3DJVgbVs-PtFCUIsdZLgr1vBS5mz8v-sJp2n7yVW5w,4608
26
- idf_build_apps-2.4.1.dist-info/RECORD,,
22
+ idf_build_apps-2.4.2.dist-info/entry_points.txt,sha256=3pVUirUEsb6jsDRikkQWNUt4hqLK2ci1HvW_Vf8b6uE,59
23
+ idf_build_apps-2.4.2.dist-info/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
24
+ idf_build_apps-2.4.2.dist-info/WHEEL,sha256=EZbGkh7Ie4PoZfRQ8I0ZuP9VklN_TvcZ6DSE5Uar4z4,81
25
+ idf_build_apps-2.4.2.dist-info/METADATA,sha256=wk_YDe56T2b3qXhknNIRzcBtCpvcDQCqku22o7IbYIU,4608
26
+ idf_build_apps-2.4.2.dist-info/RECORD,,