idf-build-apps 2.4.1.dev0__tar.gz → 2.4.3__tar.gz
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.
- {idf_build_apps-2.4.1.dev0 → idf_build_apps-2.4.3}/.github/workflows/test-build-idf-apps.yml +6 -3
- {idf_build_apps-2.4.1.dev0 → idf_build_apps-2.4.3}/.pre-commit-config.yaml +4 -5
- {idf_build_apps-2.4.1.dev0 → idf_build_apps-2.4.3}/CHANGELOG.md +27 -1
- {idf_build_apps-2.4.1.dev0 → idf_build_apps-2.4.3}/PKG-INFO +1 -1
- {idf_build_apps-2.4.1.dev0 → idf_build_apps-2.4.3}/docs/conf.py +14 -12
- {idf_build_apps-2.4.1.dev0 → idf_build_apps-2.4.3}/idf_build_apps/__init__.py +1 -1
- {idf_build_apps-2.4.1.dev0 → idf_build_apps-2.4.3}/idf_build_apps/app.py +65 -35
- {idf_build_apps-2.4.1.dev0 → idf_build_apps-2.4.3}/idf_build_apps/constants.py +6 -5
- {idf_build_apps-2.4.1.dev0 → idf_build_apps-2.4.3}/idf_build_apps/finder.py +4 -2
- {idf_build_apps-2.4.1.dev0 → idf_build_apps-2.4.3}/idf_build_apps/junit/report.py +10 -6
- {idf_build_apps-2.4.1.dev0 → idf_build_apps-2.4.3}/idf_build_apps/junit/utils.py +2 -2
- {idf_build_apps-2.4.1.dev0 → idf_build_apps-2.4.3}/idf_build_apps/main.py +94 -56
- {idf_build_apps-2.4.1.dev0 → idf_build_apps-2.4.3}/idf_build_apps/manifest/soc_header.py +18 -14
- {idf_build_apps-2.4.1.dev0 → idf_build_apps-2.4.3}/pyproject.toml +1 -5
- {idf_build_apps-2.4.1.dev0 → idf_build_apps-2.4.3}/setup.py +1 -1
- {idf_build_apps-2.4.1.dev0 → idf_build_apps-2.4.3}/tests/test_build.py +23 -5
- {idf_build_apps-2.4.1.dev0 → idf_build_apps-2.4.3}/tests/test_finder.py +27 -0
- {idf_build_apps-2.4.1.dev0 → idf_build_apps-2.4.3}/.editorconfig +0 -0
- {idf_build_apps-2.4.1.dev0 → idf_build_apps-2.4.3}/.git-blame-ignore-revs +0 -0
- {idf_build_apps-2.4.1.dev0 → idf_build_apps-2.4.3}/.gitattributes +0 -0
- {idf_build_apps-2.4.1.dev0 → idf_build_apps-2.4.3}/.github/dependabot.yml +0 -0
- {idf_build_apps-2.4.1.dev0 → idf_build_apps-2.4.3}/.github/workflows/check-pre-commit.yml +0 -0
- {idf_build_apps-2.4.1.dev0 → idf_build_apps-2.4.3}/.github/workflows/issue_comment.yml +0 -0
- {idf_build_apps-2.4.1.dev0 → idf_build_apps-2.4.3}/.github/workflows/new_issues.yml +0 -0
- {idf_build_apps-2.4.1.dev0 → idf_build_apps-2.4.3}/.github/workflows/new_prs.yml +0 -0
- {idf_build_apps-2.4.1.dev0 → idf_build_apps-2.4.3}/.github/workflows/publish-pypi.yml +0 -0
- {idf_build_apps-2.4.1.dev0 → idf_build_apps-2.4.3}/.github/workflows/test-build-docs.yml +0 -0
- {idf_build_apps-2.4.1.dev0 → idf_build_apps-2.4.3}/.gitignore +0 -0
- {idf_build_apps-2.4.1.dev0 → idf_build_apps-2.4.3}/.readthedocs.yml +0 -0
- {idf_build_apps-2.4.1.dev0 → idf_build_apps-2.4.3}/CONTRIBUTING.md +0 -0
- {idf_build_apps-2.4.1.dev0 → idf_build_apps-2.4.3}/LICENSE +0 -0
- {idf_build_apps-2.4.1.dev0 → idf_build_apps-2.4.3}/README.md +0 -0
- {idf_build_apps-2.4.1.dev0 → idf_build_apps-2.4.3}/docs/CHANGELOG.md +0 -0
- {idf_build_apps-2.4.1.dev0 → idf_build_apps-2.4.3}/docs/CONTRIBUTING.md +0 -0
- {idf_build_apps-2.4.1.dev0 → idf_build_apps-2.4.3}/docs/Makefile +0 -0
- {idf_build_apps-2.4.1.dev0 → idf_build_apps-2.4.3}/docs/_apidoc_templates/module.rst_t +0 -0
- {idf_build_apps-2.4.1.dev0 → idf_build_apps-2.4.3}/docs/_apidoc_templates/package.rst_t +0 -0
- {idf_build_apps-2.4.1.dev0 → idf_build_apps-2.4.3}/docs/_apidoc_templates/toc.rst_t +0 -0
- {idf_build_apps-2.4.1.dev0 → idf_build_apps-2.4.3}/docs/_static/espressif-logo.svg +0 -0
- {idf_build_apps-2.4.1.dev0 → idf_build_apps-2.4.3}/docs/_static/theme_overrides.css +0 -0
- {idf_build_apps-2.4.1.dev0 → idf_build_apps-2.4.3}/docs/_templates/layout.html +0 -0
- {idf_build_apps-2.4.1.dev0 → idf_build_apps-2.4.3}/docs/cli.rst +0 -0
- {idf_build_apps-2.4.1.dev0 → idf_build_apps-2.4.3}/docs/config_file.md +0 -0
- {idf_build_apps-2.4.1.dev0 → idf_build_apps-2.4.3}/docs/find_build.md +0 -0
- {idf_build_apps-2.4.1.dev0 → idf_build_apps-2.4.3}/docs/index.rst +0 -0
- {idf_build_apps-2.4.1.dev0 → idf_build_apps-2.4.3}/docs/manifest.md +0 -0
- {idf_build_apps-2.4.1.dev0 → idf_build_apps-2.4.3}/docs/migration/1.x_to_2.x.md +0 -0
- {idf_build_apps-2.4.1.dev0 → idf_build_apps-2.4.3}/idf_build_apps/__main__.py +0 -0
- {idf_build_apps-2.4.1.dev0 → idf_build_apps-2.4.3}/idf_build_apps/autocompletions.py +0 -0
- {idf_build_apps-2.4.1.dev0 → idf_build_apps-2.4.3}/idf_build_apps/build_apps_args.py +0 -0
- {idf_build_apps-2.4.1.dev0 → idf_build_apps-2.4.3}/idf_build_apps/config.py +0 -0
- {idf_build_apps-2.4.1.dev0 → idf_build_apps-2.4.3}/idf_build_apps/junit/__init__.py +0 -0
- {idf_build_apps-2.4.1.dev0 → idf_build_apps-2.4.3}/idf_build_apps/log.py +0 -0
- {idf_build_apps-2.4.1.dev0 → idf_build_apps-2.4.3}/idf_build_apps/manifest/__init__.py +0 -0
- {idf_build_apps-2.4.1.dev0 → idf_build_apps-2.4.3}/idf_build_apps/manifest/if_parser.py +0 -0
- {idf_build_apps-2.4.1.dev0 → idf_build_apps-2.4.3}/idf_build_apps/manifest/manifest.py +0 -0
- {idf_build_apps-2.4.1.dev0 → idf_build_apps-2.4.3}/idf_build_apps/session_args.py +0 -0
- {idf_build_apps-2.4.1.dev0 → idf_build_apps-2.4.3}/idf_build_apps/utils.py +0 -0
- {idf_build_apps-2.4.1.dev0 → idf_build_apps-2.4.3}/idf_build_apps/yaml/__init__.py +0 -0
- {idf_build_apps-2.4.1.dev0 → idf_build_apps-2.4.3}/idf_build_apps/yaml/parser.py +0 -0
- {idf_build_apps-2.4.1.dev0 → idf_build_apps-2.4.3}/license_header.txt +0 -0
- {idf_build_apps-2.4.1.dev0 → idf_build_apps-2.4.3}/tests/conftest.py +0 -0
- {idf_build_apps-2.4.1.dev0 → idf_build_apps-2.4.3}/tests/test_app.py +0 -0
- {idf_build_apps-2.4.1.dev0 → idf_build_apps-2.4.3}/tests/test_manifest.py +0 -0
- {idf_build_apps-2.4.1.dev0 → idf_build_apps-2.4.3}/tests/test_utils.py +0 -0
{idf_build_apps-2.4.1.dev0 → idf_build_apps-2.4.3}/.github/workflows/test-build-idf-apps.yml
RENAMED
|
@@ -52,9 +52,12 @@ jobs:
|
|
|
52
52
|
bash $IDF_PATH/install.sh
|
|
53
53
|
. $IDF_PATH/export.sh
|
|
54
54
|
pip install idf_build_apps-*.whl
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
55
|
+
cd $IDF_PATH/examples/get-started/hello_world
|
|
56
|
+
cat 'CONFIG_IDF_TARGET="esp32"' >sdkconfig.defaults
|
|
57
|
+
idf-build-apps build --build-dir build_@t --size-file size_info.json
|
|
58
|
+
test -f build_esp32/hello_world.bin
|
|
59
|
+
test -f build_esp32/size_info.json
|
|
60
|
+
test ! -f build_esp32s2/hello_world.bin
|
|
58
61
|
|
|
59
62
|
build-apps-on-idf-master:
|
|
60
63
|
runs-on: ubuntu-latest
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
repos:
|
|
2
2
|
- repo: https://github.com/pre-commit/pre-commit-hooks
|
|
3
|
-
rev: v4.
|
|
3
|
+
rev: v4.6.0
|
|
4
4
|
hooks:
|
|
5
5
|
- id: trailing-whitespace
|
|
6
6
|
- id: end-of-file-fixer
|
|
@@ -16,14 +16,13 @@ repos:
|
|
|
16
16
|
- license_header.txt # defaults to: LICENSE.txt
|
|
17
17
|
- --use-current-year
|
|
18
18
|
- repo: https://github.com/charliermarsh/ruff-pre-commit
|
|
19
|
-
rev: 'v0.
|
|
19
|
+
rev: 'v0.5.5'
|
|
20
20
|
hooks:
|
|
21
21
|
- id: ruff
|
|
22
|
-
args: ['--fix'
|
|
22
|
+
args: ['--fix']
|
|
23
23
|
- id: ruff-format
|
|
24
|
-
args: ['--preview']
|
|
25
24
|
- repo: https://github.com/pre-commit/mirrors-mypy
|
|
26
|
-
rev: 'v1.8.0'
|
|
25
|
+
rev: 'v1.8.0' # 1.9 doesn't support python 3.7
|
|
27
26
|
hooks:
|
|
28
27
|
- id: mypy
|
|
29
28
|
args: ['--warn-unused-ignores']
|
|
@@ -2,7 +2,33 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
|
|
5
|
-
## v2.4.
|
|
5
|
+
## v2.4.3 (2024-08-07)
|
|
6
|
+
|
|
7
|
+
### Feat
|
|
8
|
+
|
|
9
|
+
- set default building target to "all" if `--target` is not specified
|
|
10
|
+
- set default paths to current directory if `--paths` is not specified
|
|
11
|
+
|
|
12
|
+
## v2.4.2 (2024-08-01)
|
|
13
|
+
|
|
14
|
+
### Feat
|
|
15
|
+
|
|
16
|
+
- support `--enable-preview-targets`
|
|
17
|
+
- support `--include-all-apps` while find_apps
|
|
18
|
+
- support `--output-format json` while find_apps
|
|
19
|
+
- support `include_disabled_apps` while `find_apps`
|
|
20
|
+
|
|
21
|
+
### Fix
|
|
22
|
+
|
|
23
|
+
- ignore specified target if unknown in current ESP-IDF branch instead of raise exception
|
|
24
|
+
- correct `post_build` actions for succeeded with warnings builds
|
|
25
|
+
- **completions**: fix typos in help
|
|
26
|
+
|
|
27
|
+
### Refactor
|
|
28
|
+
|
|
29
|
+
- update deprecated `datetime.utcnow`
|
|
30
|
+
|
|
31
|
+
## v2.4.1 (2024-06-18)
|
|
6
32
|
|
|
7
33
|
### Fix
|
|
8
34
|
|
|
@@ -52,15 +52,17 @@ docs_dir = os.path.dirname(__file__)
|
|
|
52
52
|
api_dir = os.path.join(docs_dir, 'api')
|
|
53
53
|
if os.path.isdir(api_dir):
|
|
54
54
|
shutil.rmtree(api_dir)
|
|
55
|
-
subprocess.run(
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
55
|
+
subprocess.run(
|
|
56
|
+
[
|
|
57
|
+
'sphinx-apidoc',
|
|
58
|
+
os.path.join(docs_dir, '..', 'idf_build_apps'),
|
|
59
|
+
'-f',
|
|
60
|
+
'-H',
|
|
61
|
+
'API Reference',
|
|
62
|
+
'--no-headings',
|
|
63
|
+
'-t',
|
|
64
|
+
'_apidoc_templates',
|
|
65
|
+
'-o',
|
|
66
|
+
api_dir,
|
|
67
|
+
]
|
|
68
|
+
)
|
|
@@ -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
|
-
|
|
158
|
-
|
|
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
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
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.
|
|
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.
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
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
|
|
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
|
|
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
|
|
106
|
+
You can also specify your shell using the `--shell` option.
|
|
106
107
|
|
|
107
|
-
If you do not want
|
|
108
|
-
|
|
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
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# SPDX-FileCopyrightText: 2022-
|
|
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
|
-
|
|
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.
|
|
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
|
|
91
|
-
raise ValueError(
|
|
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
|
|
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)
|
|
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.
|
|
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
|
|
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:
|
|
@@ -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
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
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)
|
|
@@ -452,8 +458,12 @@ def get_parser() -> argparse.ArgumentParser:
|
|
|
452
458
|
help='Path to the default configuration file, toml file',
|
|
453
459
|
)
|
|
454
460
|
|
|
455
|
-
common_args.add_argument(
|
|
456
|
-
|
|
461
|
+
common_args.add_argument(
|
|
462
|
+
'-p', '--paths', nargs='*', help='One or more paths to look for apps. By default build the current directory.'
|
|
463
|
+
)
|
|
464
|
+
common_args.add_argument(
|
|
465
|
+
'-t', '--target', default='all', help='filter apps by given target. By default build all supported targets.'
|
|
466
|
+
)
|
|
457
467
|
common_args.add_argument(
|
|
458
468
|
'--build-system', default='cmake', choices=['cmake', 'make'], help='filter apps by given build system'
|
|
459
469
|
)
|
|
@@ -551,14 +561,19 @@ def get_parser() -> argparse.ArgumentParser:
|
|
|
551
561
|
action='store_true',
|
|
552
562
|
help='Exit with error if any of the manifest rules does not exist on your filesystem',
|
|
553
563
|
)
|
|
554
|
-
|
|
564
|
+
common_args.add_argument(
|
|
565
|
+
'--enable-preview-targets',
|
|
566
|
+
action='store_true',
|
|
567
|
+
help='Build the apps with all targets in the current ESP-IDF branch, '
|
|
568
|
+
'including preview targets, when the app supports the target.',
|
|
569
|
+
)
|
|
555
570
|
common_args.add_argument(
|
|
556
571
|
'--default-build-targets',
|
|
557
572
|
nargs='+',
|
|
558
|
-
help='space-separated list of
|
|
559
|
-
'
|
|
573
|
+
help='space-separated list of string which specifies the targets for building the apps. '
|
|
574
|
+
'If provided, the apps will be built only with the specified targets '
|
|
575
|
+
'when the app supports the target.',
|
|
560
576
|
)
|
|
561
|
-
|
|
562
577
|
common_args.add_argument(
|
|
563
578
|
'--modified-components',
|
|
564
579
|
type=semicolon_separated_str_to_list,
|
|
@@ -610,7 +625,7 @@ def get_parser() -> argparse.ArgumentParser:
|
|
|
610
625
|
|
|
611
626
|
find_parser = actions.add_parser(
|
|
612
627
|
'find',
|
|
613
|
-
help='Find the buildable applications. Run `idf-build-apps find --help` for more information on a command',
|
|
628
|
+
help='Find the buildable applications. Run `idf-build-apps find --help` for more information on a command.',
|
|
614
629
|
description='Find the buildable applications in the given path or paths for specified chips. '
|
|
615
630
|
'`--path` and `--target` options must be provided. '
|
|
616
631
|
'By default, print the found apps in stdout. '
|
|
@@ -618,12 +633,23 @@ def get_parser() -> argparse.ArgumentParser:
|
|
|
618
633
|
parents=[common_args],
|
|
619
634
|
formatter_class=IdfBuildAppsCliFormatter,
|
|
620
635
|
)
|
|
621
|
-
|
|
622
636
|
find_parser.add_argument('-o', '--output', help='Print the found apps to the specified file instead of stdout')
|
|
637
|
+
find_parser.add_argument(
|
|
638
|
+
'--output-format',
|
|
639
|
+
choices=['raw', 'json'],
|
|
640
|
+
default='raw',
|
|
641
|
+
help='Output format. In "raw" format, each line is a valid json that represents the app. '
|
|
642
|
+
'In "json" format, the whole file is a JSON file of a list of apps.',
|
|
643
|
+
)
|
|
644
|
+
find_parser.add_argument(
|
|
645
|
+
'--include-all-apps',
|
|
646
|
+
action='store_true',
|
|
647
|
+
help='Include skipped and disabled apps. By default only apps that should be built.',
|
|
648
|
+
)
|
|
623
649
|
|
|
624
650
|
build_parser = actions.add_parser(
|
|
625
651
|
'build',
|
|
626
|
-
help='Build the found applications. Run `idf-build-apps build --help` for more information on a command',
|
|
652
|
+
help='Build the found applications. Run `idf-build-apps build --help` for more information on a command.',
|
|
627
653
|
description='Build the application in the given path or paths for specified chips. '
|
|
628
654
|
'`--path` and `--target` options must be provided.',
|
|
629
655
|
parents=[common_args],
|
|
@@ -696,18 +722,18 @@ def get_parser() -> argparse.ArgumentParser:
|
|
|
696
722
|
completions_parser = actions.add_parser(
|
|
697
723
|
'completions',
|
|
698
724
|
help='Add the autocompletion activation script to the shell rc file. '
|
|
699
|
-
'Run `idf-build-apps
|
|
725
|
+
'Run `idf-build-apps completions --help` for more information on a command.',
|
|
700
726
|
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, '
|
|
727
|
+
'With the `--activate` option, add the autocompletion activation script to the shell rc file '
|
|
728
|
+
'for bash, zsh, or fish. Other shells are not supported.'
|
|
729
|
+
'The `--shell` option is used only with the `--activate` option, '
|
|
704
730
|
'if provided, add the autocompletion activation script to the given shell; '
|
|
705
731
|
'without this argument, will detect shell type automatically. '
|
|
706
732
|
'May need to restart or re-login for the autocompletion to start working',
|
|
707
733
|
formatter_class=IdfBuildAppsCliFormatter,
|
|
708
734
|
)
|
|
709
735
|
completions_parser.add_argument(
|
|
710
|
-
'-a', '--activate', action='store_true', help='Activate autocompletion automatically and permanently'
|
|
736
|
+
'-a', '--activate', action='store_true', help='Activate autocompletion automatically and permanently. '
|
|
711
737
|
)
|
|
712
738
|
completions_parser.add_argument(
|
|
713
739
|
'-s',
|
|
@@ -737,28 +763,27 @@ def validate_args(parser: argparse.ArgumentParser, args: argparse.Namespace) ->
|
|
|
737
763
|
raise InvalidCommand('subcommand is required. {find, build, completions}')
|
|
738
764
|
|
|
739
765
|
if not args.paths:
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
766
|
+
cur_dir = os.getcwd()
|
|
767
|
+
LOGGER.debug(f'--paths is missing. Set --path as current directory "{cur_dir}".')
|
|
768
|
+
args.paths = [cur_dir]
|
|
743
769
|
|
|
744
770
|
if not args.target:
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
'(choices: [{}]'.format(','.join([*ALL_TARGETS, 'all']))
|
|
748
|
-
)
|
|
771
|
+
LOGGER.debug('--target is missing. Set --target as "all".')
|
|
772
|
+
args.target = 'all'
|
|
749
773
|
|
|
750
774
|
default_build_targets = []
|
|
751
775
|
if args.default_build_targets:
|
|
752
776
|
for target in args.default_build_targets:
|
|
753
777
|
if target not in ALL_TARGETS:
|
|
754
|
-
|
|
755
|
-
f'Unrecognizable target {target} specified with "--default-build-targets". '
|
|
778
|
+
LOGGER.warning(
|
|
779
|
+
f'Ignoring... Unrecognizable target {target} specified with "--default-build-targets". '
|
|
756
780
|
f'Current ESP-IDF available targets: {ALL_TARGETS}'
|
|
757
781
|
)
|
|
758
|
-
|
|
759
|
-
if target not in default_build_targets:
|
|
782
|
+
elif target not in default_build_targets:
|
|
760
783
|
default_build_targets.append(target)
|
|
761
|
-
|
|
784
|
+
args.default_build_targets = default_build_targets
|
|
785
|
+
elif args.enable_preview_targets:
|
|
786
|
+
args.default_build_targets = deepcopy(ALL_TARGETS)
|
|
762
787
|
|
|
763
788
|
if args.ignore_app_dependencies_components is not None:
|
|
764
789
|
if args.modified_components is None:
|
|
@@ -796,36 +821,49 @@ def main():
|
|
|
796
821
|
if args.action == 'build':
|
|
797
822
|
args.output = None # build action doesn't support output option
|
|
798
823
|
|
|
824
|
+
kwargs = {
|
|
825
|
+
'build_system': args.build_system,
|
|
826
|
+
'recursive': args.recursive,
|
|
827
|
+
'exclude_list': args.exclude or [],
|
|
828
|
+
'work_dir': args.work_dir,
|
|
829
|
+
'build_dir': args.build_dir or 'build',
|
|
830
|
+
'config_rules_str': args.config,
|
|
831
|
+
'build_log_filename': args.build_log,
|
|
832
|
+
'size_json_filename': args.size_file,
|
|
833
|
+
'check_warnings': args.check_warnings,
|
|
834
|
+
'manifest_rootpath': args.manifest_rootpath,
|
|
835
|
+
'manifest_files': args.manifest_file,
|
|
836
|
+
'check_manifest_rules': args.check_manifest_rules,
|
|
837
|
+
'default_build_targets': args.default_build_targets,
|
|
838
|
+
'modified_components': args.modified_components,
|
|
839
|
+
'modified_files': args.modified_files,
|
|
840
|
+
'ignore_app_dependencies_components': args.ignore_app_dependencies_components,
|
|
841
|
+
'ignore_app_dependencies_filepatterns': args.ignore_app_dependencies_filepatterns,
|
|
842
|
+
'sdkconfig_defaults': args.sdkconfig_defaults,
|
|
843
|
+
}
|
|
844
|
+
# only useful in find
|
|
845
|
+
if args.action == 'find' and args.include_all_apps:
|
|
846
|
+
kwargs['include_skipped_apps'] = True
|
|
847
|
+
kwargs['include_disabled_apps'] = True
|
|
848
|
+
|
|
799
849
|
# 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
|
-
)
|
|
850
|
+
apps = find_apps(args.paths, args.target, **kwargs)
|
|
822
851
|
|
|
823
852
|
if args.action == 'find':
|
|
824
853
|
if args.output:
|
|
825
854
|
os.makedirs(os.path.dirname(os.path.realpath(args.output)), exist_ok=True)
|
|
855
|
+
if args.output.endswith('.json'):
|
|
856
|
+
LOGGER.info('Detecting output file ends with ".json", writing json file.')
|
|
857
|
+
args.output_format = 'json'
|
|
858
|
+
|
|
826
859
|
with open(args.output, 'w') as fw:
|
|
827
|
-
|
|
828
|
-
|
|
860
|
+
if args.output_format == 'raw':
|
|
861
|
+
for app in apps:
|
|
862
|
+
fw.write(app.to_json() + '\n')
|
|
863
|
+
elif args.output_format == 'json':
|
|
864
|
+
fw.write(json.dumps([app.model_dump() for app in apps], indent=2))
|
|
865
|
+
else:
|
|
866
|
+
raise ValueError(f'Output format {args.output_format} is not supported.')
|
|
829
867
|
else:
|
|
830
868
|
for app in apps:
|
|
831
869
|
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
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
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]:
|
|
@@ -61,7 +61,7 @@ idf-build-apps = "idf_build_apps:main.main"
|
|
|
61
61
|
|
|
62
62
|
[tool.commitizen]
|
|
63
63
|
name = "cz_conventional_commits"
|
|
64
|
-
version = "2.4.
|
|
64
|
+
version = "2.4.3"
|
|
65
65
|
tag_format = "v$version"
|
|
66
66
|
version_files = [
|
|
67
67
|
"idf_build_apps/__init__.py",
|
|
@@ -77,10 +77,6 @@ testpaths = [
|
|
|
77
77
|
profile = 'black'
|
|
78
78
|
force_grid_wrap = 1
|
|
79
79
|
|
|
80
|
-
[tool.black]
|
|
81
|
-
line-length = 120
|
|
82
|
-
skip-string-normalization = true
|
|
83
|
-
|
|
84
80
|
[tool.ruff]
|
|
85
81
|
line-length = 120
|
|
86
82
|
target-version = "py37"
|
|
@@ -30,7 +30,7 @@ entry_points = \
|
|
|
30
30
|
{'console_scripts': ['idf-build-apps = idf_build_apps:main.main']}
|
|
31
31
|
|
|
32
32
|
setup(name='idf-build-apps',
|
|
33
|
-
version='2.4.
|
|
33
|
+
version='2.4.3',
|
|
34
34
|
description='Tools for building ESP-IDF related apps.',
|
|
35
35
|
author=None,
|
|
36
36
|
author_email='Fu Hanxi <fuhanxi@espressif.com>',
|
|
@@ -112,7 +112,11 @@ class TestBuild:
|
|
|
112
112
|
apps = [
|
|
113
113
|
CMakeApp(test_dir, 'esp32', build_dir='build_1'),
|
|
114
114
|
CMakeApp(test_dir, 'esp32', build_dir='build_2'),
|
|
115
|
+
CMakeApp(test_dir, 'esp32', build_dir='build_3'),
|
|
116
|
+
CMakeApp(test_dir, 'esp32', build_dir='build_4'),
|
|
115
117
|
]
|
|
118
|
+
apps[2].build_status = BuildStatus.DISABLED
|
|
119
|
+
apps[3].build_status = BuildStatus.SKIPPED
|
|
116
120
|
|
|
117
121
|
build_apps(deepcopy(apps), dry_run=True, junitxml=str(tmpdir / 'test.xml'))
|
|
118
122
|
|
|
@@ -123,13 +127,20 @@ class TestBuild:
|
|
|
123
127
|
assert test_suite.attrib['tests'] == '0'
|
|
124
128
|
assert test_suite.attrib['failures'] == '0'
|
|
125
129
|
assert test_suite.attrib['errors'] == '0'
|
|
126
|
-
assert test_suite.attrib['skipped'] == '
|
|
130
|
+
assert test_suite.attrib['skipped'] == '4'
|
|
127
131
|
|
|
128
132
|
for i, testcase in enumerate(test_suite.findall('testcase')):
|
|
129
133
|
assert testcase.attrib['name'] == apps[i].build_path
|
|
130
134
|
assert float(testcase.attrib['time']) > 0
|
|
131
135
|
assert testcase.find('skipped') is not None
|
|
132
|
-
|
|
136
|
+
if i in (0, 1):
|
|
137
|
+
assert testcase.find('skipped').attrib['message'] == 'dry run'
|
|
138
|
+
elif i == 2:
|
|
139
|
+
assert testcase.find('skipped').attrib['message'] == 'Build disabled. Skipping...'
|
|
140
|
+
elif i == 3:
|
|
141
|
+
assert testcase.find('skipped').attrib['message'] == 'Build skipped. Skipping...'
|
|
142
|
+
else:
|
|
143
|
+
assert False # not expected
|
|
133
144
|
|
|
134
145
|
build_apps(deepcopy(apps), junitxml=str(tmpdir / 'test.xml'))
|
|
135
146
|
|
|
@@ -140,14 +151,21 @@ class TestBuild:
|
|
|
140
151
|
assert test_suite.attrib['tests'] == '2'
|
|
141
152
|
assert test_suite.attrib['failures'] == '0'
|
|
142
153
|
assert test_suite.attrib['errors'] == '0'
|
|
143
|
-
assert test_suite.attrib['skipped'] == '
|
|
154
|
+
assert test_suite.attrib['skipped'] == '2'
|
|
144
155
|
|
|
145
156
|
for i, testcase in enumerate(test_suite.findall('testcase')):
|
|
146
|
-
assert testcase.attrib['name'] == apps[i].build_path
|
|
147
157
|
assert float(testcase.attrib['time']) > 0
|
|
148
|
-
assert testcase.
|
|
158
|
+
assert testcase.attrib['name'] == apps[i].build_path
|
|
149
159
|
assert testcase.find('error') is None
|
|
150
160
|
assert testcase.find('failure') is None
|
|
161
|
+
if i in (0, 1):
|
|
162
|
+
assert testcase.find('skipped') is None
|
|
163
|
+
elif i == 2:
|
|
164
|
+
assert testcase.find('skipped').attrib['message'] == 'Build disabled. Skipping...'
|
|
165
|
+
elif i == 3:
|
|
166
|
+
assert testcase.find('skipped').attrib['message'] == 'Build skipped. Skipping...'
|
|
167
|
+
else:
|
|
168
|
+
assert False # not expected
|
|
151
169
|
|
|
152
170
|
def test_work_dir_inside_relative_app_dir(self, tmp_path):
|
|
153
171
|
create_project('foo', tmp_path)
|
|
@@ -109,6 +109,33 @@ examples/get-started:
|
|
|
109
109
|
== apps
|
|
110
110
|
)
|
|
111
111
|
|
|
112
|
+
def test_include_disabled_apps(self, tmpdir):
|
|
113
|
+
test_dir = Path(IDF_PATH) / 'examples' / 'get-started'
|
|
114
|
+
yaml_file = tmpdir / 'test.yml'
|
|
115
|
+
yaml_file.write_text(
|
|
116
|
+
f"""
|
|
117
|
+
{test_dir}:
|
|
118
|
+
enable:
|
|
119
|
+
- if: IDF_TARGET == "esp32s2"
|
|
120
|
+
""",
|
|
121
|
+
encoding='utf8',
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
test_dir = Path(IDF_PATH) / 'examples' / 'get-started'
|
|
125
|
+
apps = find_apps(
|
|
126
|
+
str(test_dir), 'esp32', recursive=True, manifest_files=str(yaml_file), include_disabled_apps=False
|
|
127
|
+
)
|
|
128
|
+
assert not apps
|
|
129
|
+
|
|
130
|
+
apps = find_apps(
|
|
131
|
+
str(test_dir), 'esp32', recursive=True, manifest_files=str(yaml_file), include_disabled_apps=True
|
|
132
|
+
)
|
|
133
|
+
assert apps
|
|
134
|
+
for app in apps:
|
|
135
|
+
assert app.build_status == BuildStatus.DISABLED
|
|
136
|
+
app.build()
|
|
137
|
+
assert app.build_comment == 'Build disabled. Skipping...'
|
|
138
|
+
|
|
112
139
|
|
|
113
140
|
class TestFindWithModifiedFilesComponents:
|
|
114
141
|
@pytest.mark.parametrize(
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|