idf-build-apps 2.13.3__tar.gz → 2.14.0__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.13.3 → idf_build_apps-2.14.0}/.github/workflows/publish-pypi.yml +1 -1
- {idf_build_apps-2.13.3 → idf_build_apps-2.14.0}/.github/workflows/sync-jira.yml +2 -2
- {idf_build_apps-2.13.3 → idf_build_apps-2.14.0}/.github/workflows/test-build-docs.yml +1 -1
- {idf_build_apps-2.13.3 → idf_build_apps-2.14.0}/.github/workflows/test-build-idf-apps.yml +10 -6
- {idf_build_apps-2.13.3 → idf_build_apps-2.14.0}/.pre-commit-config.yaml +3 -3
- {idf_build_apps-2.13.3 → idf_build_apps-2.14.0}/CHANGELOG.md +55 -2
- {idf_build_apps-2.13.3 → idf_build_apps-2.14.0}/PKG-INFO +1 -1
- {idf_build_apps-2.13.3 → idf_build_apps-2.14.0}/docs/conf_common.py +1 -1
- {idf_build_apps-2.13.3 → idf_build_apps-2.14.0}/docs/en/conf.py +1 -1
- {idf_build_apps-2.13.3 → idf_build_apps-2.14.0}/docs/en/explanations/dependency_driven_build.rst +11 -0
- {idf_build_apps-2.13.3 → idf_build_apps-2.14.0}/docs/en/references/manifest.rst +9 -0
- {idf_build_apps-2.13.3 → idf_build_apps-2.14.0}/idf_build_apps/__init__.py +2 -2
- {idf_build_apps-2.13.3 → idf_build_apps-2.14.0}/idf_build_apps/__main__.py +1 -1
- {idf_build_apps-2.13.3 → idf_build_apps-2.14.0}/idf_build_apps/app.py +4 -2
- {idf_build_apps-2.13.3 → idf_build_apps-2.14.0}/idf_build_apps/args.py +15 -1
- {idf_build_apps-2.13.3 → idf_build_apps-2.14.0}/idf_build_apps/autocompletions.py +1 -1
- {idf_build_apps-2.13.3 → idf_build_apps-2.14.0}/idf_build_apps/constants.py +1 -1
- {idf_build_apps-2.13.3 → idf_build_apps-2.14.0}/idf_build_apps/finder.py +1 -1
- {idf_build_apps-2.13.3 → idf_build_apps-2.14.0}/idf_build_apps/junit/__init__.py +1 -1
- {idf_build_apps-2.13.3 → idf_build_apps-2.14.0}/idf_build_apps/junit/report.py +1 -1
- {idf_build_apps-2.13.3 → idf_build_apps-2.14.0}/idf_build_apps/junit/utils.py +1 -1
- {idf_build_apps-2.13.3 → idf_build_apps-2.14.0}/idf_build_apps/log.py +1 -1
- {idf_build_apps-2.13.3 → idf_build_apps-2.14.0}/idf_build_apps/main.py +15 -6
- {idf_build_apps-2.13.3 → idf_build_apps-2.14.0}/idf_build_apps/manifest/__init__.py +1 -1
- {idf_build_apps-2.13.3 → idf_build_apps-2.14.0}/idf_build_apps/manifest/manifest.py +20 -6
- {idf_build_apps-2.13.3 → idf_build_apps-2.14.0}/idf_build_apps/manifest/soc_header.py +1 -1
- {idf_build_apps-2.13.3 → idf_build_apps-2.14.0}/idf_build_apps/session_args.py +1 -1
- {idf_build_apps-2.13.3 → idf_build_apps-2.14.0}/idf_build_apps/utils.py +1 -1
- {idf_build_apps-2.13.3 → idf_build_apps-2.14.0}/idf_build_apps/yaml/__init__.py +1 -1
- {idf_build_apps-2.13.3 → idf_build_apps-2.14.0}/idf_build_apps/yaml/parser.py +37 -4
- {idf_build_apps-2.13.3 → idf_build_apps-2.14.0}/pyproject.toml +2 -2
- {idf_build_apps-2.13.3 → idf_build_apps-2.14.0}/setup.py +1 -1
- {idf_build_apps-2.13.3 → idf_build_apps-2.14.0}/tests/conftest.py +1 -1
- {idf_build_apps-2.13.3 → idf_build_apps-2.14.0}/tests/test_app.py +1 -1
- {idf_build_apps-2.13.3 → idf_build_apps-2.14.0}/tests/test_args.py +15 -1
- {idf_build_apps-2.13.3 → idf_build_apps-2.14.0}/tests/test_build.py +1 -2
- {idf_build_apps-2.13.3 → idf_build_apps-2.14.0}/tests/test_cmd.py +67 -1
- {idf_build_apps-2.13.3 → idf_build_apps-2.14.0}/tests/test_disable_reasons.py +1 -1
- {idf_build_apps-2.13.3 → idf_build_apps-2.14.0}/tests/test_finder.py +2 -2
- {idf_build_apps-2.13.3 → idf_build_apps-2.14.0}/tests/test_manifest.py +28 -1
- {idf_build_apps-2.13.3 → idf_build_apps-2.14.0}/tests/test_utils.py +1 -1
- {idf_build_apps-2.13.3 → idf_build_apps-2.14.0}/.editorconfig +0 -0
- {idf_build_apps-2.13.3 → idf_build_apps-2.14.0}/.git-blame-ignore-revs +0 -0
- {idf_build_apps-2.13.3 → idf_build_apps-2.14.0}/.gitattributes +0 -0
- {idf_build_apps-2.13.3 → idf_build_apps-2.14.0}/.github/dependabot.yml +0 -0
- {idf_build_apps-2.13.3 → idf_build_apps-2.14.0}/.gitignore +0 -0
- {idf_build_apps-2.13.3 → idf_build_apps-2.14.0}/.readthedocs.yml +0 -0
- {idf_build_apps-2.13.3 → idf_build_apps-2.14.0}/CONTRIBUTING.md +0 -0
- {idf_build_apps-2.13.3 → idf_build_apps-2.14.0}/LICENSE +0 -0
- {idf_build_apps-2.13.3 → idf_build_apps-2.14.0}/README.md +0 -0
- {idf_build_apps-2.13.3 → idf_build_apps-2.14.0}/docs/_apidoc_templates/module.rst_t +0 -0
- {idf_build_apps-2.13.3 → idf_build_apps-2.14.0}/docs/_apidoc_templates/package.rst_t +0 -0
- {idf_build_apps-2.13.3 → idf_build_apps-2.14.0}/docs/_apidoc_templates/toc.rst_t +0 -0
- {idf_build_apps-2.13.3 → idf_build_apps-2.14.0}/docs/_static/espressif-logo.svg +0 -0
- {idf_build_apps-2.13.3 → idf_build_apps-2.14.0}/docs/_static/theme_overrides.css +0 -0
- {idf_build_apps-2.13.3 → idf_build_apps-2.14.0}/docs/_templates/layout.html +0 -0
- {idf_build_apps-2.13.3 → idf_build_apps-2.14.0}/docs/en/Makefile +0 -0
- {idf_build_apps-2.13.3 → idf_build_apps-2.14.0}/docs/en/explanations/build.rst +0 -0
- {idf_build_apps-2.13.3 → idf_build_apps-2.14.0}/docs/en/explanations/build_status.rst +0 -0
- {idf_build_apps-2.13.3 → idf_build_apps-2.14.0}/docs/en/explanations/config_rules.rst +0 -0
- {idf_build_apps-2.13.3 → idf_build_apps-2.14.0}/docs/en/explanations/find.rst +0 -0
- {idf_build_apps-2.13.3 → idf_build_apps-2.14.0}/docs/en/guides/1.x_to_2.x.md +0 -0
- {idf_build_apps-2.13.3 → idf_build_apps-2.14.0}/docs/en/guides/custom_app.md +0 -0
- {idf_build_apps-2.13.3 → idf_build_apps-2.14.0}/docs/en/index.rst +0 -0
- {idf_build_apps-2.13.3 → idf_build_apps-2.14.0}/docs/en/others/CHANGELOG.md +0 -0
- {idf_build_apps-2.13.3 → idf_build_apps-2.14.0}/docs/en/others/CONTRIBUTING.md +0 -0
- {idf_build_apps-2.13.3 → idf_build_apps-2.14.0}/docs/en/references/cli.rst +0 -0
- {idf_build_apps-2.13.3 → idf_build_apps-2.14.0}/docs/en/references/config_file.rst +0 -0
- {idf_build_apps-2.13.3 → idf_build_apps-2.14.0}/idf_build_apps/py.typed +0 -0
- {idf_build_apps-2.13.3 → idf_build_apps-2.14.0}/idf_build_apps/vendors/__init__.py +0 -0
- {idf_build_apps-2.13.3 → idf_build_apps-2.14.0}/idf_build_apps/vendors/pydantic_sources.py +0 -0
- {idf_build_apps-2.13.3 → idf_build_apps-2.14.0}/license_header.txt +0 -0
|
@@ -46,7 +46,7 @@ jobs:
|
|
|
46
46
|
pull-requests: write
|
|
47
47
|
steps:
|
|
48
48
|
- name: Check out
|
|
49
|
-
uses: actions/checkout@
|
|
49
|
+
uses: actions/checkout@v6
|
|
50
50
|
|
|
51
51
|
- name: Run synchronization to Jira
|
|
52
52
|
uses: espressif/sync-jira-actions@v1
|
|
@@ -55,7 +55,7 @@ jobs:
|
|
|
55
55
|
env:
|
|
56
56
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
57
57
|
JIRA_PASS: ${{ secrets.JIRA_PASS }}
|
|
58
|
-
JIRA_PROJECT:
|
|
58
|
+
JIRA_PROJECT: CII
|
|
59
59
|
JIRA_COMPONENT: idf-build-apps
|
|
60
60
|
JIRA_URL: ${{ secrets.JIRA_URL }}
|
|
61
61
|
JIRA_USER: ${{ secrets.JIRA_USER }}
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
name: Test Build IDF Apps
|
|
2
2
|
|
|
3
|
+
concurrency:
|
|
4
|
+
group: ${{ github.workflow }}-${{ github.ref }}-${{ github.run_id }}
|
|
5
|
+
cancel-in-progress: false
|
|
6
|
+
|
|
3
7
|
on:
|
|
4
8
|
pull_request:
|
|
5
9
|
paths:
|
|
@@ -20,7 +24,7 @@ jobs:
|
|
|
20
24
|
build-python-packages:
|
|
21
25
|
runs-on: ubuntu-22.04
|
|
22
26
|
steps:
|
|
23
|
-
- uses: actions/checkout@
|
|
27
|
+
- uses: actions/checkout@v6
|
|
24
28
|
- uses: actions/setup-python@v6
|
|
25
29
|
with:
|
|
26
30
|
python-version: '3.7'
|
|
@@ -29,7 +33,7 @@ jobs:
|
|
|
29
33
|
pip install flit
|
|
30
34
|
flit build
|
|
31
35
|
- name: Upload built python packages
|
|
32
|
-
uses: actions/upload-artifact@
|
|
36
|
+
uses: actions/upload-artifact@v6
|
|
33
37
|
with:
|
|
34
38
|
name: wheel
|
|
35
39
|
path: dist/idf_build_apps-*.whl
|
|
@@ -39,13 +43,13 @@ jobs:
|
|
|
39
43
|
needs: build-python-packages
|
|
40
44
|
strategy:
|
|
41
45
|
matrix:
|
|
42
|
-
idf-branch: [ release-v5.
|
|
46
|
+
idf-branch: [ release-v5.1, release-v5.2, release-v5.3, release-v5.4, release-v5.5 ]
|
|
43
47
|
runs-on: ubuntu-latest
|
|
44
48
|
container:
|
|
45
49
|
image: espressif/idf:${{ matrix.idf-branch }}
|
|
46
50
|
steps:
|
|
47
51
|
- name: Download wheel
|
|
48
|
-
uses: actions/download-artifact@
|
|
52
|
+
uses: actions/download-artifact@v7
|
|
49
53
|
with:
|
|
50
54
|
name: wheel
|
|
51
55
|
- name: Build the Apps
|
|
@@ -67,7 +71,7 @@ jobs:
|
|
|
67
71
|
env:
|
|
68
72
|
FLIT_ROOT_INSTALL: 1
|
|
69
73
|
steps:
|
|
70
|
-
- uses: actions/checkout@
|
|
74
|
+
- uses: actions/checkout@v6
|
|
71
75
|
- name: Build the Apps
|
|
72
76
|
run: |
|
|
73
77
|
bash $IDF_PATH/install.sh
|
|
@@ -97,7 +101,7 @@ jobs:
|
|
|
97
101
|
branch:
|
|
98
102
|
- release/v3.4
|
|
99
103
|
steps:
|
|
100
|
-
- uses: actions/checkout@
|
|
104
|
+
- uses: actions/checkout@v6
|
|
101
105
|
- name: Install dependencies
|
|
102
106
|
run: |
|
|
103
107
|
apt update \
|
|
@@ -17,13 +17,13 @@ repos:
|
|
|
17
17
|
- --use-current-year
|
|
18
18
|
exclude: 'idf_build_apps/vendors/'
|
|
19
19
|
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
20
|
-
rev: 'v0.
|
|
20
|
+
rev: 'v0.14.11'
|
|
21
21
|
hooks:
|
|
22
|
-
- id: ruff
|
|
22
|
+
- id: ruff-check
|
|
23
23
|
args: ['--fix']
|
|
24
24
|
- id: ruff-format
|
|
25
25
|
- repo: https://github.com/pre-commit/mirrors-mypy
|
|
26
|
-
rev: 'v1.
|
|
26
|
+
rev: 'v1.19.1'
|
|
27
27
|
hooks:
|
|
28
28
|
- id: mypy
|
|
29
29
|
args: ['--warn-unused-ignores']
|
|
@@ -1,9 +1,47 @@
|
|
|
1
|
-
|
|
1
|
+
<a href="https://www.espressif.com">
|
|
2
|
+
<img src="https://www.espressif.com/sites/all/themes/espressif/logo-black.svg" align="right" height="20" />
|
|
3
|
+
</a>
|
|
4
|
+
|
|
5
|
+
# CHANGELOG
|
|
6
|
+
|
|
7
|
+
> All notable changes to this project are documented in this file.
|
|
8
|
+
> This list is not exhaustive - only important changes, fixes, and new features in the code are reflected here.
|
|
9
|
+
|
|
10
|
+
<div style="text-align: center;">
|
|
11
|
+
<a href="https://keepachangelog.com/en/1.1.0/">
|
|
12
|
+
<img alt="Static Badge" src="https://img.shields.io/badge/Keep%20a%20Changelog-v1.1.0-salmon?logo=keepachangelog&logoColor=black&labelColor=white&link=https%3A%2F%2Fkeepachangelog.com%2Fen%2F1.1.0%2F">
|
|
13
|
+
</a>
|
|
14
|
+
<a href="https://www.conventionalcommits.org/en/v1.0.0/">
|
|
15
|
+
<img alt="Static Badge" src="https://img.shields.io/badge/Conventional%20Commits-v1.0.0-pink?logo=conventionalcommits&logoColor=black&labelColor=white&link=https%3A%2F%2Fwww.conventionalcommits.org%2Fen%2Fv1.0.0%2F">
|
|
16
|
+
</a>
|
|
17
|
+
<a href="https://semver.org/spec/v2.0.0.html">
|
|
18
|
+
<img alt="Static Badge" src="https://img.shields.io/badge/Semantic%20Versioning-v2.0.0-grey?logo=semanticrelease&logoColor=black&labelColor=white&link=https%3A%2F%2Fsemver.org%2Fspec%2Fv2.0.0.html">
|
|
19
|
+
</a>
|
|
20
|
+
</div>
|
|
21
|
+
<hr>
|
|
22
|
+
|
|
23
|
+
## v2.14.0 (2026-01-16)
|
|
2
24
|
|
|
3
|
-
|
|
25
|
+
### ✨ New Features
|
|
26
|
+
|
|
27
|
+
- support root_components placeholder *(igor.udot - 104959e)*
|
|
28
|
+
|
|
29
|
+
### 🐛 Bug Fixes
|
|
30
|
+
|
|
31
|
+
- **pre-commit**: change mypy python_version from 3.9 to 3.10 *(Evgeny Torbin - bdf0788)*
|
|
32
|
+
- fixed issue that parser_bool_expr thorws AttributeError not caught *(Xiao Xufeng - 3878948)*
|
|
33
|
+
- `model_validate` does not support `extra` in python<=3.8 *(Fu Hanxi - 8a108a1)*
|
|
34
|
+
- add disabled apps to junit with `--include-all-apps` flag *(Evgeny Torbin - 071d4e3)*
|
|
35
|
+
|
|
36
|
+
### 📖 Documentation
|
|
37
|
+
|
|
38
|
+
- base_components placeholder *(igor.udot - 7958201)*
|
|
39
|
+
|
|
40
|
+
---
|
|
4
41
|
|
|
5
42
|
## v2.13.3 (2025-10-23)
|
|
6
43
|
|
|
44
|
+
---
|
|
7
45
|
|
|
8
46
|
## v2.13.2 (2025-10-23)
|
|
9
47
|
|
|
@@ -12,6 +50,7 @@ All notable changes to this project will be documented in this file.
|
|
|
12
50
|
- update broken tests for `size.json` *(Evgeny Torbin - c603221)*
|
|
13
51
|
- change `idf_size.py --format json` to `--format json2` *(Evgeny Torbin - 49b9f3d)*
|
|
14
52
|
|
|
53
|
+
---
|
|
15
54
|
|
|
16
55
|
## v2.13.1 (2025-09-29)
|
|
17
56
|
|
|
@@ -19,6 +58,7 @@ All notable changes to this project will be documented in this file.
|
|
|
19
58
|
|
|
20
59
|
- path checking for modified apps *(Fu Hanxi - 18f554c)*
|
|
21
60
|
|
|
61
|
+
---
|
|
22
62
|
|
|
23
63
|
## v2.13.0 (2025-09-26)
|
|
24
64
|
|
|
@@ -31,6 +71,7 @@ All notable changes to this project will be documented in this file.
|
|
|
31
71
|
- **find_apps**: ignore target-specific sdkconfig files even without setting CONFIG_IDF_TARGET *(Fu Hanxi - 1861a7a)*
|
|
32
72
|
- record `checked_should_build` *(Fu Hanxi - f37fff1)*
|
|
33
73
|
|
|
74
|
+
---
|
|
34
75
|
|
|
35
76
|
## v2.12.3 (2025-09-16)
|
|
36
77
|
|
|
@@ -591,3 +632,15 @@ This is the last version to support ESP-IDF v4.1 since it's EOL on Feb. 24th, 20
|
|
|
591
632
|
### Added
|
|
592
633
|
|
|
593
634
|
- Use `--format json` instead of `--json` with `idf_size.py`
|
|
635
|
+
|
|
636
|
+
---
|
|
637
|
+
|
|
638
|
+
<div style="text-align: center;">
|
|
639
|
+
<small>
|
|
640
|
+
<b>
|
|
641
|
+
<a href="https://www.github.com/espressif/cz-plugin-espressif">Commitizen Espressif plugin</a>
|
|
642
|
+
</b>
|
|
643
|
+
<br>
|
|
644
|
+
<sup><a href="https://www.espressif.com">Espressif Systems CO LTD. (2026)</a><sup>
|
|
645
|
+
</small>
|
|
646
|
+
</div>
|
{idf_build_apps-2.13.3 → idf_build_apps-2.14.0}/docs/en/explanations/dependency_driven_build.rst
RENAMED
|
@@ -63,6 +63,17 @@ Here is an example of a manifest file:
|
|
|
63
63
|
depends_filepatterns:
|
|
64
64
|
- "common_header_files/**/*"
|
|
65
65
|
|
|
66
|
+
You may also reuse a common set of component dependencies by using the special placeholder ``- *common_components`` inside ``depends_components``. This placeholder is expanded when loading the manifest file, using the values provided via the CLI option ``--common-components`` (or the ``common_components`` argument to :meth:`~idf_build_apps.manifest.manifest.Manifest.from_file`).
|
|
67
|
+
|
|
68
|
+
.. code:: yaml
|
|
69
|
+
|
|
70
|
+
# rules.yml
|
|
71
|
+
examples/foo:
|
|
72
|
+
depends_components:
|
|
73
|
+
- *common_components
|
|
74
|
+
- "some_1"
|
|
75
|
+
- "some_2"
|
|
76
|
+
|
|
66
77
|
The apps under folder ``examples/foo`` will be built with the following CLI options:
|
|
67
78
|
|
|
68
79
|
- ``--manifest-files rules.yml --modified-files examples/foo/main/foo.c``
|
|
@@ -209,6 +209,15 @@ Reuse Lists
|
|
|
209
209
|
|
|
210
210
|
To reuse the items defined in a list, you can use the ``+`` and ``-`` postfixes respectively. The order of calculation is always ``+`` first, followed by ``-``.
|
|
211
211
|
|
|
212
|
+
Placeholder: ``*common_components``
|
|
213
|
+
-----------------------------------
|
|
214
|
+
|
|
215
|
+
In addition to YAML anchors, ``idf-build-apps`` also supports a special placeholder entry ``- *common_components`` inside ``depends_components``.
|
|
216
|
+
|
|
217
|
+
When loading the manifest file, this placeholder is expanded using the values provided via the CLI option ``--common-components`` (or the ``common_components`` argument to :meth:`~idf_build_apps.manifest.manifest.Manifest.from_file`).
|
|
218
|
+
|
|
219
|
+
This placeholder entry is only supported inside ``depends_components``.
|
|
220
|
+
|
|
212
221
|
Array Elements as Strings
|
|
213
222
|
-------------------------
|
|
214
223
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# SPDX-FileCopyrightText: 2022-
|
|
1
|
+
# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD
|
|
2
2
|
# SPDX-License-Identifier: Apache-2.0
|
|
3
3
|
|
|
4
4
|
"""
|
|
@@ -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.
|
|
11
|
+
__version__ = '2.14.0'
|
|
12
12
|
|
|
13
13
|
from .session_args import (
|
|
14
14
|
SessionArgs,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# SPDX-FileCopyrightText: 2022-
|
|
1
|
+
# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD
|
|
2
2
|
# SPDX-License-Identifier: Apache-2.0
|
|
3
3
|
|
|
4
4
|
import copy
|
|
@@ -511,7 +511,9 @@ class App(BaseModel):
|
|
|
511
511
|
BuildStatus.UNKNOWN,
|
|
512
512
|
BuildStatus.SHOULD_BE_BUILT,
|
|
513
513
|
):
|
|
514
|
-
|
|
514
|
+
if not self.build_comment:
|
|
515
|
+
self.build_comment = f'Build {self.build_status.value}. Skipping...'
|
|
516
|
+
|
|
515
517
|
return
|
|
516
518
|
|
|
517
519
|
# real build starts here
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# SPDX-FileCopyrightText: 2024-
|
|
1
|
+
# SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD
|
|
2
2
|
# SPDX-License-Identifier: Apache-2.0
|
|
3
3
|
|
|
4
4
|
import argparse
|
|
@@ -302,6 +302,19 @@ class DependencyDrivenBuildArguments(GlobalArguments):
|
|
|
302
302
|
),
|
|
303
303
|
default=None, # type: ignore
|
|
304
304
|
)
|
|
305
|
+
common_components: t.Optional[t.List[str]] = field(
|
|
306
|
+
FieldMetadata(
|
|
307
|
+
validate_method=[ValidateMethod.TO_LIST],
|
|
308
|
+
type=semicolon_separated_str_to_list,
|
|
309
|
+
shorthand='-rc',
|
|
310
|
+
),
|
|
311
|
+
description='semicolon-separated list of components. '
|
|
312
|
+
'expand the `- *common_components` placeholder in manifests. '
|
|
313
|
+
'Must be specified together with --modified-components. '
|
|
314
|
+
'If set to "", the value would be considered as None. '
|
|
315
|
+
'If set to ";", the value would be considered as an empty list.',
|
|
316
|
+
default=None, # type: ignore
|
|
317
|
+
)
|
|
305
318
|
deactivate_dependency_driven_build_by_filepatterns: t.Optional[t.List[str]] = field(
|
|
306
319
|
FieldMetadata(
|
|
307
320
|
validate_method=[ValidateMethod.TO_LIST],
|
|
@@ -374,6 +387,7 @@ class DependencyDrivenBuildArguments(GlobalArguments):
|
|
|
374
387
|
App.MANIFEST = Manifest.from_files(
|
|
375
388
|
self.manifest_files,
|
|
376
389
|
root_path=to_absolute_path(self.manifest_rootpath),
|
|
390
|
+
common_components=self.common_components,
|
|
377
391
|
)
|
|
378
392
|
|
|
379
393
|
@property
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# PYTHON_ARGCOMPLETE_OK
|
|
2
2
|
|
|
3
|
-
# SPDX-FileCopyrightText: 2022-
|
|
3
|
+
# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD
|
|
4
4
|
# SPDX-License-Identifier: Apache-2.0
|
|
5
5
|
|
|
6
6
|
import argparse
|
|
@@ -386,23 +386,26 @@ def main():
|
|
|
386
386
|
sys.exit(0)
|
|
387
387
|
|
|
388
388
|
kwargs = vars(args)
|
|
389
|
+
kwargs_without_none = drop_none_kwargs(kwargs)
|
|
389
390
|
action = kwargs.pop('action')
|
|
390
391
|
config_file = kwargs.pop('config_file')
|
|
391
392
|
if config_file:
|
|
392
393
|
apply_config_file(config_file)
|
|
393
394
|
|
|
394
395
|
if action == 'dump-manifest-sha':
|
|
395
|
-
arguments = DumpManifestShaArguments(**
|
|
396
|
+
arguments = DumpManifestShaArguments(**kwargs_without_none)
|
|
396
397
|
Manifest.from_files(arguments.manifest_files).dump_sha_values(arguments.output)
|
|
397
398
|
sys.exit(0)
|
|
398
|
-
|
|
399
|
-
|
|
399
|
+
|
|
400
|
+
if action == 'find':
|
|
401
|
+
arguments = FindArguments(**kwargs_without_none)
|
|
400
402
|
else:
|
|
401
|
-
arguments = BuildArguments(**
|
|
403
|
+
arguments = BuildArguments(**kwargs_without_none)
|
|
402
404
|
|
|
403
405
|
# real call starts here
|
|
404
406
|
# build also needs to find first
|
|
405
|
-
apps = find_apps(args.paths, args.target, find_arguments=
|
|
407
|
+
apps = find_apps(args.paths, args.target, find_arguments=FindArguments.model_validate(kwargs_without_none))
|
|
408
|
+
|
|
406
409
|
if isinstance(arguments, FindArguments): # find only
|
|
407
410
|
if arguments.output:
|
|
408
411
|
os.makedirs(os.path.dirname(os.path.realpath(arguments.output)), exist_ok=True)
|
|
@@ -444,6 +447,12 @@ def main():
|
|
|
444
447
|
for app in failed_apps:
|
|
445
448
|
print(f' {app}')
|
|
446
449
|
|
|
450
|
+
disabled_apps = [app for app in apps if app.build_status == BuildStatus.DISABLED]
|
|
451
|
+
if disabled_apps:
|
|
452
|
+
print('Disabled the following apps:')
|
|
453
|
+
for app in disabled_apps:
|
|
454
|
+
print(f' {app}')
|
|
455
|
+
|
|
447
456
|
if ret_code != 0:
|
|
448
457
|
sys.exit(ret_code)
|
|
449
458
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# SPDX-FileCopyrightText: 2022-
|
|
1
|
+
# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD
|
|
2
2
|
# SPDX-License-Identifier: Apache-2.0
|
|
3
3
|
import contextvars
|
|
4
4
|
import logging
|
|
@@ -45,7 +45,7 @@ class IfClause:
|
|
|
45
45
|
try:
|
|
46
46
|
self.stmt: BoolStmt = parse_bool_expr(stmt)
|
|
47
47
|
self._stmt: str = stmt
|
|
48
|
-
except (ParseException, InvalidIfClause) as ex:
|
|
48
|
+
except (ParseException, InvalidIfClause, AttributeError) as ex:
|
|
49
49
|
raise InvalidIfClause(f'Invalid if clause: {stmt}. {ex}')
|
|
50
50
|
|
|
51
51
|
self.temporary = temporary
|
|
@@ -342,12 +342,19 @@ class Manifest:
|
|
|
342
342
|
self._rule_paths = {rule.folder: rule for rule in self.rules}
|
|
343
343
|
|
|
344
344
|
@classmethod
|
|
345
|
-
def from_files(
|
|
345
|
+
def from_files(
|
|
346
|
+
cls,
|
|
347
|
+
paths: t.Iterable[PathLike],
|
|
348
|
+
*,
|
|
349
|
+
root_path: str = os.curdir,
|
|
350
|
+
common_components: t.Optional[t.Sequence[str]] = None,
|
|
351
|
+
) -> 'Manifest':
|
|
346
352
|
"""
|
|
347
353
|
Create a Manifest instance from multiple manifest files
|
|
348
354
|
|
|
349
355
|
:param paths: manifest file paths
|
|
350
356
|
:param root_path: root path for relative paths in manifest files
|
|
357
|
+
:param common_components: sequence of strings to expand the ``- *common_components`` placeholder in manifests
|
|
351
358
|
:return: Manifest instance
|
|
352
359
|
"""
|
|
353
360
|
# folder, defined as dict
|
|
@@ -356,7 +363,7 @@ class Manifest:
|
|
|
356
363
|
rules: t.List[FolderRule] = []
|
|
357
364
|
for path in paths:
|
|
358
365
|
LOGGER.debug('Loading manifest file %s', path)
|
|
359
|
-
_manifest = cls.from_file(path, root_path=root_path)
|
|
366
|
+
_manifest = cls.from_file(path, root_path=root_path, common_components=common_components)
|
|
360
367
|
|
|
361
368
|
for rule in _manifest.rules:
|
|
362
369
|
if rule.folder in _known_folders:
|
|
@@ -373,15 +380,22 @@ class Manifest:
|
|
|
373
380
|
return Manifest(rules, root_path=root_path)
|
|
374
381
|
|
|
375
382
|
@classmethod
|
|
376
|
-
def from_file(
|
|
383
|
+
def from_file(
|
|
384
|
+
cls,
|
|
385
|
+
path: PathLike,
|
|
386
|
+
*,
|
|
387
|
+
root_path: str = os.curdir,
|
|
388
|
+
common_components: t.Optional[t.Sequence[str]] = None,
|
|
389
|
+
) -> 'Manifest':
|
|
377
390
|
"""
|
|
378
391
|
Create a Manifest instance from a manifest file
|
|
379
392
|
|
|
380
393
|
:param path: path to the manifest file
|
|
381
394
|
:param root_path: root path for relative paths in manifest file
|
|
395
|
+
:param common_components: sequence of strings to expand the ``{{root_components}}`` placeholder in manifests
|
|
382
396
|
:return: Manifest instance
|
|
383
397
|
"""
|
|
384
|
-
manifest_dict = parse(path)
|
|
398
|
+
manifest_dict = parse(path, common_components=common_components)
|
|
385
399
|
|
|
386
400
|
rules: t.List[FolderRule] = []
|
|
387
401
|
for folder, folder_rule in manifest_dict.items():
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# SPDX-FileCopyrightText: 2024-
|
|
1
|
+
# SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD
|
|
2
2
|
# SPDX-License-Identifier: Apache-2.0
|
|
3
3
|
|
|
4
4
|
import typing as t
|
|
@@ -62,8 +62,41 @@ def parse_postfixes(manifest_dict: t.Dict):
|
|
|
62
62
|
manifest_dict[folder] = updated_folder
|
|
63
63
|
|
|
64
64
|
|
|
65
|
-
def
|
|
66
|
-
|
|
67
|
-
|
|
65
|
+
def flatten_common_components(manifest_dict: t.Dict):
|
|
66
|
+
"""
|
|
67
|
+
Flattens nested lists under `depends_components` into a single list of strings.
|
|
68
|
+
"""
|
|
69
|
+
|
|
70
|
+
for folder, folder_rule in manifest_dict.items():
|
|
71
|
+
if not isinstance(folder_rule, t.Dict):
|
|
72
|
+
continue
|
|
73
|
+
|
|
74
|
+
depends = folder_rule.get('depends_components')
|
|
75
|
+
if not isinstance(depends, t.List):
|
|
76
|
+
continue
|
|
77
|
+
|
|
78
|
+
flattened: t.List[str] = []
|
|
79
|
+
for item in depends:
|
|
80
|
+
if isinstance(item, t.List):
|
|
81
|
+
flattened.extend(map(str, item))
|
|
82
|
+
else:
|
|
83
|
+
flattened.append(item)
|
|
84
|
+
|
|
85
|
+
folder_rule['depends_components'] = flattened
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def parse(path: PathLike, *, common_components: t.Optional[t.Sequence[str]] = None) -> t.Dict:
|
|
89
|
+
common_components_yaml = (
|
|
90
|
+
'.common_components: &common_components\n' + '\n'.join(f' - {component}' for component in common_components)
|
|
91
|
+
if common_components
|
|
92
|
+
else ''
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
with open(path, encoding='utf-8') as f:
|
|
96
|
+
user_yaml = f.read()
|
|
97
|
+
|
|
98
|
+
manifest_dict = yaml.safe_load(f'{common_components_yaml}\n{user_yaml}') or {}
|
|
99
|
+
|
|
100
|
+
flatten_common_components(manifest_dict)
|
|
68
101
|
parse_postfixes(manifest_dict)
|
|
69
102
|
return manifest_dict
|
|
@@ -65,7 +65,7 @@ idf-build-apps = "idf_build_apps:main.main"
|
|
|
65
65
|
|
|
66
66
|
[tool.commitizen]
|
|
67
67
|
name = "czespressif"
|
|
68
|
-
version = "2.
|
|
68
|
+
version = "2.14.0"
|
|
69
69
|
|
|
70
70
|
tag_format = "v$version"
|
|
71
71
|
version_scheme = "pep440"
|
|
@@ -172,4 +172,4 @@ docstring-code-format = true
|
|
|
172
172
|
ignore-variadic-names = true
|
|
173
173
|
|
|
174
174
|
[tool.mypy]
|
|
175
|
-
python_version = "3.
|
|
175
|
+
python_version = "3.10"
|
|
@@ -38,7 +38,7 @@ entry_points = \
|
|
|
38
38
|
{'console_scripts': ['idf-build-apps = idf_build_apps:main.main']}
|
|
39
39
|
|
|
40
40
|
setup(name='idf-build-apps',
|
|
41
|
-
version='2.
|
|
41
|
+
version='2.14.0',
|
|
42
42
|
description='Tools for building ESP-IDF related apps.',
|
|
43
43
|
author=None,
|
|
44
44
|
author_email='Fu Hanxi <fuhanxi@espressif.com>',
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# SPDX-FileCopyrightText: 2024-
|
|
1
|
+
# SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD
|
|
2
2
|
# SPDX-License-Identifier: Apache-2.0
|
|
3
3
|
import os
|
|
4
4
|
from tempfile import NamedTemporaryFile
|
|
@@ -170,6 +170,20 @@ modified_files = [
|
|
|
170
170
|
assert args.deactivate_dependency_driven_build_by_components == ['baz']
|
|
171
171
|
|
|
172
172
|
|
|
173
|
+
def test_func_common_components():
|
|
174
|
+
with open(IDF_BUILD_APPS_TOML_FN, 'w') as fw:
|
|
175
|
+
fw.write("""
|
|
176
|
+
common_components = [
|
|
177
|
+
'hello',
|
|
178
|
+
'world'
|
|
179
|
+
]
|
|
180
|
+
""")
|
|
181
|
+
|
|
182
|
+
args = FindArguments()
|
|
183
|
+
|
|
184
|
+
assert args.common_components == ['hello', 'world']
|
|
185
|
+
|
|
186
|
+
|
|
173
187
|
def test_combination_validation():
|
|
174
188
|
"""Test that target options can now be combined"""
|
|
175
189
|
# Mock targets for consistent testing
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# SPDX-FileCopyrightText: 2022-
|
|
1
|
+
# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD
|
|
2
2
|
# SPDX-License-Identifier: Apache-2.0
|
|
3
3
|
|
|
4
4
|
import json
|
|
@@ -253,7 +253,6 @@ class TestBuild:
|
|
|
253
253
|
|
|
254
254
|
expected_files = [
|
|
255
255
|
'libesp_timer.a:system_time.c.obj',
|
|
256
|
-
'libc.a:libc_a-vfprintf.o',
|
|
257
256
|
'libfreertos.a:tasks.c.obj',
|
|
258
257
|
'libheap.a:tlsf.c.obj',
|
|
259
258
|
]
|
|
@@ -1,11 +1,15 @@
|
|
|
1
|
-
# SPDX-FileCopyrightText: 2024-
|
|
1
|
+
# SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD
|
|
2
2
|
# SPDX-License-Identifier: Apache-2.0
|
|
3
3
|
import os
|
|
4
4
|
import sys
|
|
5
5
|
from pathlib import Path
|
|
6
|
+
from textwrap import dedent
|
|
7
|
+
from xml.etree import ElementTree
|
|
6
8
|
|
|
7
9
|
import pytest
|
|
10
|
+
from conftest import create_project
|
|
8
11
|
|
|
12
|
+
from idf_build_apps.constants import SUPPORTED_TARGETS
|
|
9
13
|
from idf_build_apps.main import main
|
|
10
14
|
from idf_build_apps.utils import InvalidCommand
|
|
11
15
|
|
|
@@ -95,3 +99,65 @@ bar:
|
|
|
95
99
|
assert f'Loading manifest file {os.path.join(tmp_path, "manifest.yml")}' in err
|
|
96
100
|
assert f'"{os.path.join(tmp_path, "foo")}" does not exist' in err
|
|
97
101
|
assert f'"{os.path.join(tmp_path, "bar")}" does not exist' in err
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def test_build_include_all_apps(tmp_path, monkeypatch, capsys):
|
|
105
|
+
create_project('foo', tmp_path)
|
|
106
|
+
|
|
107
|
+
manifest = tmp_path / 'manifest.yml'
|
|
108
|
+
manifest.write_text(
|
|
109
|
+
dedent("""\
|
|
110
|
+
foo:
|
|
111
|
+
disable:
|
|
112
|
+
- if: IDF_TARGET == "esp32"
|
|
113
|
+
""")
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
with monkeypatch.context() as m:
|
|
117
|
+
m.setattr(
|
|
118
|
+
sys,
|
|
119
|
+
'argv',
|
|
120
|
+
[
|
|
121
|
+
'idf-build-apps',
|
|
122
|
+
'build',
|
|
123
|
+
'--paths',
|
|
124
|
+
'foo',
|
|
125
|
+
'--manifest-files',
|
|
126
|
+
str(manifest),
|
|
127
|
+
'--check-manifest-rules',
|
|
128
|
+
'--include-all-apps',
|
|
129
|
+
'--junitxml',
|
|
130
|
+
str(tmp_path / 'junit.xml'),
|
|
131
|
+
'--dry-run',
|
|
132
|
+
],
|
|
133
|
+
)
|
|
134
|
+
main()
|
|
135
|
+
|
|
136
|
+
out, err = capsys.readouterr()
|
|
137
|
+
assert err == ''
|
|
138
|
+
assert 'Disabled the following apps' in out
|
|
139
|
+
assert out.count('Disabled by manifest rule: IDF_TARGET == "esp32"') == 1
|
|
140
|
+
|
|
141
|
+
with open(str(tmp_path / 'junit.xml')) as f:
|
|
142
|
+
xml = ElementTree.fromstring(f.read())
|
|
143
|
+
|
|
144
|
+
test_suite = xml.findall('testsuite')[0]
|
|
145
|
+
assert test_suite.attrib['tests'] == '0'
|
|
146
|
+
assert test_suite.attrib['failures'] == '0'
|
|
147
|
+
assert test_suite.attrib['errors'] == '0'
|
|
148
|
+
assert test_suite.attrib['skipped'] == str(len(SUPPORTED_TARGETS))
|
|
149
|
+
|
|
150
|
+
disabled_testcases = 0
|
|
151
|
+
|
|
152
|
+
for case in test_suite.findall('testcase'):
|
|
153
|
+
if case.get('name') != 'foo/build':
|
|
154
|
+
continue
|
|
155
|
+
|
|
156
|
+
skipped = case.find('skipped')
|
|
157
|
+
if skipped is None:
|
|
158
|
+
continue
|
|
159
|
+
|
|
160
|
+
if skipped.get('message') == 'Disabled by manifest rule: IDF_TARGET == "esp32"':
|
|
161
|
+
disabled_testcases += 1
|
|
162
|
+
|
|
163
|
+
assert disabled_testcases == 1
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# SPDX-FileCopyrightText: 2022-
|
|
1
|
+
# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD
|
|
2
2
|
# SPDX-License-Identifier: Apache-2.0
|
|
3
3
|
|
|
4
4
|
import os
|
|
@@ -138,7 +138,7 @@ examples/get-started:
|
|
|
138
138
|
for app in apps:
|
|
139
139
|
assert app.build_status == BuildStatus.DISABLED
|
|
140
140
|
app.build()
|
|
141
|
-
assert app.build_comment
|
|
141
|
+
assert app.build_comment.startswith('Not enabled by manifest rules:')
|
|
142
142
|
|
|
143
143
|
|
|
144
144
|
class TestFindWithModifiedFilesComponents:
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# SPDX-FileCopyrightText: 2022-
|
|
1
|
+
# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD
|
|
2
2
|
# SPDX-License-Identifier: Apache-2.0
|
|
3
3
|
import os
|
|
4
4
|
|
|
@@ -176,6 +176,33 @@ test5:
|
|
|
176
176
|
assert manifest.depends_components('test5', 'esp32', '123123') == ['some_1', 'some_2', 'some_3']
|
|
177
177
|
assert manifest.depends_components('test5', None, None) == ['some_1', 'some_2', 'some_3']
|
|
178
178
|
|
|
179
|
+
def test_manifest_common_components(self, tmp_path):
|
|
180
|
+
common_components = ['hello', 'world', 123]
|
|
181
|
+
|
|
182
|
+
yaml_file = tmp_path / 'test.yml'
|
|
183
|
+
yaml_file.write_text(
|
|
184
|
+
"""
|
|
185
|
+
test5:
|
|
186
|
+
depends_components:
|
|
187
|
+
- *common_components
|
|
188
|
+
- "some_1"
|
|
189
|
+
- "some_2"
|
|
190
|
+
- "some_3"
|
|
191
|
+
|
|
192
|
+
""",
|
|
193
|
+
encoding='utf8',
|
|
194
|
+
)
|
|
195
|
+
|
|
196
|
+
manifest = Manifest.from_file(yaml_file, common_components=common_components)
|
|
197
|
+
assert manifest.depends_components('test5', None, None) == [
|
|
198
|
+
'hello',
|
|
199
|
+
'world',
|
|
200
|
+
'123',
|
|
201
|
+
'some_1',
|
|
202
|
+
'some_2',
|
|
203
|
+
'some_3',
|
|
204
|
+
]
|
|
205
|
+
|
|
179
206
|
def test_manifest_switch_clause_with_postfix(self, tmp_path):
|
|
180
207
|
yaml_file = tmp_path / 'test.yml'
|
|
181
208
|
|
|
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
|