idf-build-apps 1.0.0.dev1__tar.gz → 1.0.1__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-1.0.0.dev1 → idf_build_apps-1.0.1}/.github/workflows/test-build-idf-apps.yml +6 -4
- {idf_build_apps-1.0.0.dev1 → idf_build_apps-1.0.1}/CHANGELOG.md +16 -2
- {idf_build_apps-1.0.0.dev1 → idf_build_apps-1.0.1}/CONTRIBUTING.md +3 -2
- {idf_build_apps-1.0.0.dev1 → idf_build_apps-1.0.1}/PKG-INFO +2 -1
- {idf_build_apps-1.0.0.dev1 → idf_build_apps-1.0.1}/docs/find_build.md +8 -9
- {idf_build_apps-1.0.0.dev1 → idf_build_apps-1.0.1}/docs/manifest.md +63 -6
- {idf_build_apps-1.0.0.dev1 → idf_build_apps-1.0.1}/idf_build_apps/__init__.py +1 -1
- {idf_build_apps-1.0.0.dev1 → idf_build_apps-1.0.1}/idf_build_apps/finder.py +7 -3
- {idf_build_apps-1.0.0.dev1 → idf_build_apps-1.0.1}/idf_build_apps/main.py +37 -72
- {idf_build_apps-1.0.0.dev1 → idf_build_apps-1.0.1}/idf_build_apps/manifest/if_parser.py +5 -0
- {idf_build_apps-1.0.0.dev1 → idf_build_apps-1.0.1}/idf_build_apps/utils.py +13 -4
- {idf_build_apps-1.0.0.dev1 → idf_build_apps-1.0.1}/pyproject.toml +1 -0
- {idf_build_apps-1.0.0.dev1 → idf_build_apps-1.0.1}/setup.py +2 -1
- {idf_build_apps-1.0.0.dev1 → idf_build_apps-1.0.1}/tests/test_build.py +17 -0
- {idf_build_apps-1.0.0.dev1 → idf_build_apps-1.0.1}/tests/test_finder.py +83 -3
- idf_build_apps-1.0.1/tests/test_utils.py +136 -0
- idf_build_apps-1.0.0.dev1/tests/test_utils.py +0 -84
- {idf_build_apps-1.0.0.dev1 → idf_build_apps-1.0.1}/.editorconfig +0 -0
- {idf_build_apps-1.0.0.dev1 → idf_build_apps-1.0.1}/.git-blame-ignore-revs +0 -0
- {idf_build_apps-1.0.0.dev1 → idf_build_apps-1.0.1}/.gitattributes +0 -0
- {idf_build_apps-1.0.0.dev1 → idf_build_apps-1.0.1}/.github/workflows/check-pre-commit.yml +0 -0
- {idf_build_apps-1.0.0.dev1 → idf_build_apps-1.0.1}/.github/workflows/issue_comment.yml +0 -0
- {idf_build_apps-1.0.0.dev1 → idf_build_apps-1.0.1}/.github/workflows/new_issues.yml +0 -0
- {idf_build_apps-1.0.0.dev1 → idf_build_apps-1.0.1}/.github/workflows/new_prs.yml +0 -0
- {idf_build_apps-1.0.0.dev1 → idf_build_apps-1.0.1}/.github/workflows/publish-pypi.yml +0 -0
- {idf_build_apps-1.0.0.dev1 → idf_build_apps-1.0.1}/.github/workflows/test-build-docs.yml +0 -0
- {idf_build_apps-1.0.0.dev1 → idf_build_apps-1.0.1}/.gitignore +0 -0
- {idf_build_apps-1.0.0.dev1 → idf_build_apps-1.0.1}/.pre-commit-config.yaml +0 -0
- {idf_build_apps-1.0.0.dev1 → idf_build_apps-1.0.1}/.readthedocs.yml +0 -0
- {idf_build_apps-1.0.0.dev1 → idf_build_apps-1.0.1}/LICENSE +0 -0
- {idf_build_apps-1.0.0.dev1 → idf_build_apps-1.0.1}/README.md +0 -0
- {idf_build_apps-1.0.0.dev1 → idf_build_apps-1.0.1}/docs/CHANGELOG.md +0 -0
- {idf_build_apps-1.0.0.dev1 → idf_build_apps-1.0.1}/docs/CONTRIBUTING.md +0 -0
- {idf_build_apps-1.0.0.dev1 → idf_build_apps-1.0.1}/docs/Makefile +0 -0
- {idf_build_apps-1.0.0.dev1 → idf_build_apps-1.0.1}/docs/_static/espressif-logo.svg +0 -0
- {idf_build_apps-1.0.0.dev1 → idf_build_apps-1.0.1}/docs/_static/theme_overrides.css +0 -0
- {idf_build_apps-1.0.0.dev1 → idf_build_apps-1.0.1}/docs/_templates/layout.html +0 -0
- {idf_build_apps-1.0.0.dev1 → idf_build_apps-1.0.1}/docs/api.rst +0 -0
- {idf_build_apps-1.0.0.dev1 → idf_build_apps-1.0.1}/docs/conf.py +0 -0
- {idf_build_apps-1.0.0.dev1 → idf_build_apps-1.0.1}/docs/config_file.md +0 -0
- {idf_build_apps-1.0.0.dev1 → idf_build_apps-1.0.1}/docs/index.rst +0 -0
- {idf_build_apps-1.0.0.dev1 → idf_build_apps-1.0.1}/idf_build_apps/__main__.py +0 -0
- {idf_build_apps-1.0.0.dev1 → idf_build_apps-1.0.1}/idf_build_apps/app.py +0 -0
- {idf_build_apps-1.0.0.dev1 → idf_build_apps-1.0.1}/idf_build_apps/config.py +0 -0
- {idf_build_apps-1.0.0.dev1 → idf_build_apps-1.0.1}/idf_build_apps/constants.py +0 -0
- {idf_build_apps-1.0.0.dev1 → idf_build_apps-1.0.1}/idf_build_apps/log.py +0 -0
- {idf_build_apps-1.0.0.dev1 → idf_build_apps-1.0.1}/idf_build_apps/manifest/__init__.py +0 -0
- {idf_build_apps-1.0.0.dev1 → idf_build_apps-1.0.1}/idf_build_apps/manifest/manifest.py +0 -0
- {idf_build_apps-1.0.0.dev1 → idf_build_apps-1.0.1}/idf_build_apps/manifest/soc_header.py +0 -0
- {idf_build_apps-1.0.0.dev1 → idf_build_apps-1.0.1}/license_header.txt +0 -0
- {idf_build_apps-1.0.0.dev1 → idf_build_apps-1.0.1}/tests/conftest.py +0 -0
- {idf_build_apps-1.0.0.dev1 → idf_build_apps-1.0.1}/tests/test_manifest.py +0 -0
{idf_build_apps-1.0.0.dev1 → idf_build_apps-1.0.1}/.github/workflows/test-build-idf-apps.yml
RENAMED
|
@@ -60,22 +60,24 @@ jobs:
|
|
|
60
60
|
export PYENV_ROOT="$HOME/.pyenv" && export PATH="$PYENV_ROOT/bin:$PATH" && eval "$(pyenv init --path)"
|
|
61
61
|
pyenv global ${{ matrix.python-version }}
|
|
62
62
|
rm $(which python3)
|
|
63
|
+
echo "urllib3<1.25,>=1.21.1" >> $IDF_PATH/requirements.txt
|
|
63
64
|
bash $IDF_PATH/install.sh
|
|
64
65
|
. $IDF_PATH/export.sh
|
|
65
66
|
pip install idf_build_apps-*-py2.py3-none-any.whl
|
|
66
67
|
python -m idf_build_apps build -vv -t esp32 \
|
|
67
68
|
-p $IDF_PATH/examples/get-started/hello_world \
|
|
68
69
|
--size-file size_info.json \
|
|
69
|
-
--ignore-warning-str
|
|
70
|
-
|
|
71
|
-
|
|
70
|
+
--ignore-warning-str \
|
|
71
|
+
"Python 3 versions older than 3.6 are not supported" \
|
|
72
|
+
"Python 2 is no longer supported" \
|
|
73
|
+
"Support for Python 2 is deprecated"
|
|
72
74
|
|
|
73
75
|
build-apps-on-idf-env:
|
|
74
76
|
if: ${{ github.ref == 'refs/heads/main' }}
|
|
75
77
|
needs: build-python-packages
|
|
76
78
|
strategy:
|
|
77
79
|
matrix:
|
|
78
|
-
idf-branch: [
|
|
80
|
+
idf-branch: [release-v4.3, release-v4.4, release-v5.0, release-v5.1]
|
|
79
81
|
runs-on: ubuntu-latest
|
|
80
82
|
container:
|
|
81
83
|
image: espressif/idf:${{ matrix.idf-branch }}
|
|
@@ -2,11 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
|
|
5
|
-
## [
|
|
5
|
+
## [1.0.1] (2023-06-12)
|
|
6
|
+
|
|
7
|
+
## Fixed
|
|
8
|
+
|
|
9
|
+
- glob patterns are matched recursively
|
|
10
|
+
|
|
11
|
+
## [1.0.0] (2023-05-25)
|
|
6
12
|
|
|
7
13
|
## Added
|
|
8
14
|
|
|
9
15
|
- Support keyword `depends_filepatterns` in the manifest file
|
|
16
|
+
- Support expanding environment variables in the manifest files
|
|
10
17
|
|
|
11
18
|
## BREAKING CHANGES
|
|
12
19
|
|
|
@@ -23,6 +30,13 @@ All notable changes to this project will be documented in this file.
|
|
|
23
30
|
- CLI Options Renamed
|
|
24
31
|
- `--depends-on-components` renamed to `--modified-components`
|
|
25
32
|
- `--depends-on-files` renamed to `--modified-files`
|
|
33
|
+
- `--ignore-components-dependencies-file-patterns` renamed to `--ignore-app-dependencies-filepatterns`
|
|
34
|
+
- Removed the deprecated CLI call methods, now these options only support space-separated list
|
|
35
|
+
- `--exclude`
|
|
36
|
+
- `--config`
|
|
37
|
+
- `--manifest-file`
|
|
38
|
+
- `--ignore-warning-str`
|
|
39
|
+
- `--default-build-targets`
|
|
26
40
|
|
|
27
41
|
## [0.6.1] (2023-05-10)
|
|
28
42
|
|
|
@@ -122,7 +136,7 @@ This is the last version to support ESP-IDF v4.1 since it's EOL on Feb. 24th, 20
|
|
|
122
136
|
|
|
123
137
|
### Fixed
|
|
124
138
|
|
|
125
|
-
-
|
|
139
|
+
- Relative path defined in the manifest files depend on the current work path
|
|
126
140
|
|
|
127
141
|
Added `manifest_rootpath` argument in `find_apps()`. Will use this value instead as the root folder for calculating absolute path
|
|
128
142
|
|
|
@@ -6,9 +6,10 @@ Please use python 3.7+ for developing, but keep in mind that we need to support
|
|
|
6
6
|
|-----------------|---------------------------|
|
|
7
7
|
| 4.1 | 2.7, 3.4+ |
|
|
8
8
|
| 4.2 | 2.7, 3.4+ |
|
|
9
|
-
| 4.3 | 3.
|
|
10
|
-
| 4.4 | 3.
|
|
9
|
+
| 4.3 | 2.7, 3.4+ |
|
|
10
|
+
| 4.4 | 2.7, 3.4+ |
|
|
11
11
|
| 5.0 | 3.7+ |
|
|
12
|
+
| 5.1 | 3.7+ |
|
|
12
13
|
| master | 3.7+ |
|
|
13
14
|
|
|
14
15
|
## Setup the Dev Environment
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: idf-build-apps
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.1
|
|
4
4
|
Summary: Tools for building ESP-IDF related apps.
|
|
5
5
|
Author-email: Fu Hanxi <fuhanxi@espressif.com>
|
|
6
6
|
Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*
|
|
@@ -17,6 +17,7 @@ Classifier: Programming Language :: Python :: 3.9
|
|
|
17
17
|
Classifier: Programming Language :: Python :: 3.10
|
|
18
18
|
Classifier: Programming Language :: Python :: 3.11
|
|
19
19
|
Requires-Dist: pathlib; python_version < '3.4'
|
|
20
|
+
Requires-Dist: glob2; python_version < '3.5'
|
|
20
21
|
Requires-Dist: pyparsing
|
|
21
22
|
Requires-Dist: pyyaml
|
|
22
23
|
Requires-Dist: packaging
|
|
@@ -59,6 +59,7 @@ flowchart TB
|
|
|
59
59
|
end
|
|
60
60
|
```
|
|
61
61
|
|
|
62
|
+
(config-rules)=
|
|
62
63
|
### Config Rules
|
|
63
64
|
|
|
64
65
|
Config rule represents the sdkconfig file pattern and the config name. The syntax is simple: `[FILE_PATTERN]=[CONFIG_NAME]`.
|
|
@@ -96,10 +97,10 @@ For example, in project `test-1`:
|
|
|
96
97
|
- The wildcard matches two files. Build two apps based on each sdkconfig file.
|
|
97
98
|
- - ``sdkconfig.ci.foo``
|
|
98
99
|
- ``sdkconfig.ci.bar``
|
|
100
|
+
```
|
|
99
101
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
For each config rule, only one wildcard is supported.
|
|
102
|
+
```{note}
|
|
103
|
+
For each config rule, only one wildcard is supported.
|
|
103
104
|
```
|
|
104
105
|
|
|
105
106
|
### Placeholders for Work Directory and Build Directory
|
|
@@ -114,7 +115,7 @@ By default, `idf-build-apps` would use the project directory as the work directo
|
|
|
114
115
|
|
|
115
116
|
#### Build Directory
|
|
116
117
|
|
|
117
|
-
Build directory is the directory where the binary files output would be generated. If it is set to a relative path, the full path would be calculated based on the work directory. If it is
|
|
118
|
+
Build directory is the directory where the binary files output would be generated. If it is set to a relative path, the full path would be calculated based on the work directory. If it is an absolute path, it would override the work directory settings.
|
|
118
119
|
|
|
119
120
|
By default, `idf-build-apps` would follow what ESP-IDF does, use `build` as the build directory.
|
|
120
121
|
|
|
@@ -127,6 +128,7 @@ Placeholders are a set of symbols, which could be used when setting work directo
|
|
|
127
128
|
- `@n`: Would be replaced by the project name.
|
|
128
129
|
- `@f`: Would be replaced by the escaped project path (replaced "/" to "_").
|
|
129
130
|
- `@i`: Would be replaced by the build index. (only available in `build` command)
|
|
131
|
+
- `@p`: Would be replaced by the parallel build index. (default to `1`, only available in `build` command)
|
|
130
132
|
|
|
131
133
|
For example,
|
|
132
134
|
|
|
@@ -160,11 +162,8 @@ The output would be:
|
|
|
160
162
|
|
|
161
163
|
Building apps is a process that build all the applications that are collected by the "finding apps" process.
|
|
162
164
|
|
|
163
|
-
```{
|
|
164
|
-
|
|
165
|
-
.. note::
|
|
166
|
-
|
|
167
|
-
Almost all CLI options that ``find`` supported are also supported in ``build`` command. You may call ``idf-build-apps find -h`` or ``idf-build-apps build -h`` for all possible CLI options.
|
|
165
|
+
```{note}
|
|
166
|
+
Almost all CLI options that ``find`` supported are also supported in ``build`` command. You may call ``idf-build-apps find -h`` or ``idf-build-apps build -h`` for all possible CLI options.
|
|
168
167
|
```
|
|
169
168
|
|
|
170
169
|
### Tips on `build` CLI Options
|
|
@@ -23,12 +23,15 @@ One typical manifest file look like this:
|
|
|
23
23
|
|
|
24
24
|
### Operands
|
|
25
25
|
|
|
26
|
-
-
|
|
27
|
-
- `
|
|
28
|
-
- `
|
|
29
|
-
- `
|
|
30
|
-
- `
|
|
31
|
-
- `
|
|
26
|
+
- Capitalized Words
|
|
27
|
+
- Variables start with `SOC_`. The value would be parsed from `IDF_PATH/components/soc/[TARGET]/include/soc/*_caps.h`
|
|
28
|
+
- `IDF_TARGET`
|
|
29
|
+
- `IDF_VERSION_MAJOR`
|
|
30
|
+
- `IDF_VERSION_MINOR`
|
|
31
|
+
- `IDF_VERSION_PATCH`
|
|
32
|
+
- `INCLUDE_DEFAULT` (The default value of officially supported targets is 1, otherwise is 0)
|
|
33
|
+
- `CONFIG_NAME` (config name defined in [](project:#config-rules))
|
|
34
|
+
- environment variables, default to `0` if not set
|
|
32
35
|
- String, must be double-quoted. e.g., `"esp32"`, `"12345"`
|
|
33
36
|
- Integer, support decimal and hex. e.g., `1`, `0xAB`
|
|
34
37
|
- List of strings or integers, or both types at the same time. e.g., `["esp32", 1]`
|
|
@@ -112,3 +115,57 @@ examples/get-started/blink:
|
|
|
112
115
|
- if: INCLUDE_DEFAULT == 1 or IDF_TARGET == "linux"
|
|
113
116
|
reason: This one supports all supported targets and linux
|
|
114
117
|
```
|
|
118
|
+
|
|
119
|
+
## Check App Dependencies
|
|
120
|
+
|
|
121
|
+
`idf-build-apps` also supports building only related apps by checking app dependencies via modified components and modified files.
|
|
122
|
+
|
|
123
|
+
### Basic Usage
|
|
124
|
+
|
|
125
|
+
To enable this feature, you need to declare the modified files or components using the CLI option:
|
|
126
|
+
|
|
127
|
+
- `--modified-files`
|
|
128
|
+
- `--modified-components`
|
|
129
|
+
|
|
130
|
+
To declare the dependencies for an app, you could add two more keywords in the corresponding manifest file:
|
|
131
|
+
|
|
132
|
+
- `depends_components`
|
|
133
|
+
- `depends_filepatterns`
|
|
134
|
+
|
|
135
|
+
One app will be built when:
|
|
136
|
+
|
|
137
|
+
- The app itself is modified (`.md` files are excluded)
|
|
138
|
+
- Any of the specified `depends_components` in the corresponding manifest file are modified
|
|
139
|
+
- Files that matches any of the specified `depends_filepatterns` in the corresponding manifest file are modified
|
|
140
|
+
- Any of the `build_components` are modified. `build_components` are defined in the `project_description.json`, which is generated by running `idf.py reconfigure` or `idf.py build`
|
|
141
|
+
|
|
142
|
+
For example, this is an app `example/foo`, which depends on `comp1`, `comp2`, `comp3` and all files under `common_header_files`:
|
|
143
|
+
|
|
144
|
+
```yaml
|
|
145
|
+
examples/foo:
|
|
146
|
+
depends_components:
|
|
147
|
+
- comp1
|
|
148
|
+
- comp2
|
|
149
|
+
- comp3
|
|
150
|
+
depends_files:
|
|
151
|
+
- "common_header_files/**/*"
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
This app will be built with the following CLI options:
|
|
155
|
+
|
|
156
|
+
- `--modified-files examples/foo/main/foo.c`
|
|
157
|
+
- `--modified-components comp1`
|
|
158
|
+
- `--modified-components comp2 comp3`
|
|
159
|
+
- `--modified-files common_header_files/foo.h`
|
|
160
|
+
|
|
161
|
+
This app will not be built with the following CLI options:
|
|
162
|
+
|
|
163
|
+
- `--modified-files examples/foo/main/foo.md`
|
|
164
|
+
- `--modified-components bar`
|
|
165
|
+
- `/tmp/foo.c`
|
|
166
|
+
|
|
167
|
+
### Advanced Usage
|
|
168
|
+
|
|
169
|
+
Sometimes, we have some root dependencies. All apps should be built if these root dependencies are modified.
|
|
170
|
+
|
|
171
|
+
After adding `--ignore-app-dependencies-filepatterns` to the CLI options, if files that matches any of the specified patterns are modified, the check app dependency feature will be disabled.
|
|
@@ -17,6 +17,7 @@ from .app import (
|
|
|
17
17
|
)
|
|
18
18
|
from .utils import (
|
|
19
19
|
config_rules_from_str,
|
|
20
|
+
to_absolute_path,
|
|
20
21
|
to_list,
|
|
21
22
|
)
|
|
22
23
|
|
|
@@ -165,15 +166,18 @@ def _find_apps(
|
|
|
165
166
|
|
|
166
167
|
# The remaining part is for recursive == True
|
|
167
168
|
apps = []
|
|
169
|
+
# handle the exclude list, since the config file might use linux style, but run in windows
|
|
170
|
+
exclude_list = [to_absolute_path(p) for p in exclude_list]
|
|
168
171
|
for root, dirs, _ in os.walk(path):
|
|
169
172
|
LOGGER.debug('Entering %s', root)
|
|
170
|
-
|
|
173
|
+
root_path = to_absolute_path(root)
|
|
174
|
+
if root_path in exclude_list:
|
|
171
175
|
LOGGER.debug('=> Skipping %s (excluded)', root)
|
|
172
176
|
del dirs[:]
|
|
173
177
|
continue
|
|
174
178
|
|
|
175
|
-
if
|
|
176
|
-
LOGGER.debug('=> Skipping %s (managed components)',
|
|
179
|
+
if root_path.parts[-1] == 'managed_components': # idf-component-manager
|
|
180
|
+
LOGGER.debug('=> Skipping %s (managed components)', root_path)
|
|
177
181
|
del dirs[:]
|
|
178
182
|
continue
|
|
179
183
|
|
|
@@ -2,14 +2,12 @@
|
|
|
2
2
|
# SPDX-License-Identifier: Apache-2.0
|
|
3
3
|
|
|
4
4
|
import argparse
|
|
5
|
-
import io
|
|
6
5
|
import json
|
|
7
6
|
import os
|
|
8
7
|
import re
|
|
9
8
|
import shutil
|
|
10
9
|
import sys
|
|
11
10
|
import textwrap
|
|
12
|
-
import warnings
|
|
13
11
|
from pathlib import (
|
|
14
12
|
Path,
|
|
15
13
|
)
|
|
@@ -55,22 +53,22 @@ def _check_app_dependency(
|
|
|
55
53
|
manifest_rootpath, # type: str
|
|
56
54
|
modified_components, # type: list[str] | None
|
|
57
55
|
modified_files, # type: list[str] | None
|
|
58
|
-
|
|
56
|
+
ignore_app_dependencies_filepatterns, # type: list[str] | None
|
|
59
57
|
): # type: (...) -> bool
|
|
60
58
|
# not check since modified_components and modified_files are not passed
|
|
61
59
|
if modified_components is None and modified_files is None:
|
|
62
60
|
return False
|
|
63
61
|
|
|
64
|
-
# not check since
|
|
62
|
+
# not check since ignore_app_dependencies_filepatterns is passed and matched
|
|
65
63
|
if (
|
|
66
|
-
|
|
64
|
+
ignore_app_dependencies_filepatterns
|
|
67
65
|
and modified_files is not None
|
|
68
|
-
and files_matches_patterns(modified_files,
|
|
66
|
+
and files_matches_patterns(modified_files, ignore_app_dependencies_filepatterns, manifest_rootpath)
|
|
69
67
|
):
|
|
70
68
|
LOGGER.debug(
|
|
71
69
|
'Skipping check component dependencies for apps since files %s matches patterns: %s',
|
|
72
70
|
', '.join(modified_files),
|
|
73
|
-
', '.join(
|
|
71
|
+
', '.join(ignore_app_dependencies_filepatterns),
|
|
74
72
|
)
|
|
75
73
|
return False
|
|
76
74
|
|
|
@@ -95,7 +93,7 @@ def find_apps(
|
|
|
95
93
|
default_build_targets=None, # type: list[str] | str | None
|
|
96
94
|
modified_components=None, # type: list[str] | str | None
|
|
97
95
|
modified_files=None, # type: list[str] | str | None
|
|
98
|
-
|
|
96
|
+
ignore_app_dependencies_filepatterns=None, # type: list[str] | str | None
|
|
99
97
|
sdkconfig_defaults=None, # type: str | None
|
|
100
98
|
): # type: (...) -> list[App]
|
|
101
99
|
"""
|
|
@@ -139,9 +137,9 @@ def find_apps(
|
|
|
139
137
|
:type modified_components: list[str] | str | None
|
|
140
138
|
:param modified_files: modified files
|
|
141
139
|
:type modified_files: list[str] | str | None
|
|
142
|
-
:param
|
|
140
|
+
:param ignore_app_dependencies_filepatterns: file patterns that used for ignoring checking the component
|
|
143
141
|
dependencies
|
|
144
|
-
:type
|
|
142
|
+
:type ignore_app_dependencies_filepatterns: list[str] | str | None
|
|
145
143
|
:param sdkconfig_defaults: semicolon-separated string, pass to idf.py -DSDKCONFIG_DEFAULTS if specified,
|
|
146
144
|
also could be set via environment variables "SDKCONFIG_DEFAULTS"
|
|
147
145
|
:type sdkconfig_defaults: str | None
|
|
@@ -166,7 +164,7 @@ def find_apps(
|
|
|
166
164
|
|
|
167
165
|
modified_components = to_list(modified_components)
|
|
168
166
|
modified_files = to_list(modified_files)
|
|
169
|
-
|
|
167
|
+
ignore_app_dependencies_filepatterns = to_list(ignore_app_dependencies_filepatterns)
|
|
170
168
|
|
|
171
169
|
apps = []
|
|
172
170
|
if target == 'all':
|
|
@@ -195,7 +193,7 @@ def find_apps(
|
|
|
195
193
|
manifest_rootpath=manifest_rootpath,
|
|
196
194
|
modified_components=modified_components,
|
|
197
195
|
modified_files=modified_files,
|
|
198
|
-
|
|
196
|
+
ignore_app_dependencies_filepatterns=ignore_app_dependencies_filepatterns,
|
|
199
197
|
),
|
|
200
198
|
modified_components=modified_components,
|
|
201
199
|
modified_files=modified_files,
|
|
@@ -223,7 +221,7 @@ def build_apps(
|
|
|
223
221
|
manifest_rootpath=None, # type: str | None
|
|
224
222
|
modified_components=None, # type: list[str] | str | None
|
|
225
223
|
modified_files=None, # type: list[str] | str | None
|
|
226
|
-
|
|
224
|
+
ignore_app_dependencies_filepatterns=None, # type: list[str] | str | None
|
|
227
225
|
): # type: (...) -> (int, list[App]) | int
|
|
228
226
|
"""
|
|
229
227
|
Build all the specified apps
|
|
@@ -258,9 +256,9 @@ def build_apps(
|
|
|
258
256
|
:type modified_components: list[str] | str | None
|
|
259
257
|
:param modified_files: modified files
|
|
260
258
|
:type modified_files: list[str] | str | None
|
|
261
|
-
:param
|
|
259
|
+
:param ignore_app_dependencies_filepatterns: file patterns that used for ignoring checking the component
|
|
262
260
|
dependencies
|
|
263
|
-
:type
|
|
261
|
+
:type ignore_app_dependencies_filepatterns: list[str] | str | None
|
|
264
262
|
:return: (exit_code, built_apps) if specified ``modified_components``
|
|
265
263
|
:rtype: int, list[App]
|
|
266
264
|
:return: exit_code if not specified ``modified_components``
|
|
@@ -269,7 +267,7 @@ def build_apps(
|
|
|
269
267
|
apps = to_list(apps) # type: list[App]
|
|
270
268
|
modified_components = to_list(modified_components)
|
|
271
269
|
modified_files = to_list(modified_files)
|
|
272
|
-
|
|
270
|
+
ignore_app_dependencies_filepatterns = to_list(ignore_app_dependencies_filepatterns)
|
|
273
271
|
|
|
274
272
|
ignore_warnings_regexes = []
|
|
275
273
|
if ignore_warning_strs:
|
|
@@ -300,27 +298,13 @@ def build_apps(
|
|
|
300
298
|
app.parallel_count = parallel_count
|
|
301
299
|
|
|
302
300
|
if collect_app_info:
|
|
303
|
-
|
|
304
|
-
warnings.warn(
|
|
305
|
-
'"collect_app_info" does not support file stream in idf-build-apps 1.0.0, Please use str instead',
|
|
306
|
-
DeprecationWarning,
|
|
307
|
-
)
|
|
308
|
-
app._collect_app_info = collect_app_info.name
|
|
309
|
-
else:
|
|
310
|
-
app._collect_app_info = collect_app_info
|
|
301
|
+
app._collect_app_info = collect_app_info
|
|
311
302
|
|
|
312
303
|
if app.collect_app_info not in collect_files:
|
|
313
304
|
collect_files.append(app.collect_app_info)
|
|
314
305
|
|
|
315
306
|
if collect_size_info:
|
|
316
|
-
|
|
317
|
-
warnings.warn(
|
|
318
|
-
'"collect_size_info" does not support file stream in idf-build-apps 1.0.0, Please use str instead',
|
|
319
|
-
DeprecationWarning,
|
|
320
|
-
)
|
|
321
|
-
app._collect_size_info = collect_size_info.name
|
|
322
|
-
else:
|
|
323
|
-
app._collect_size_info = collect_size_info
|
|
307
|
+
app._collect_size_info = collect_size_info
|
|
324
308
|
|
|
325
309
|
if app.collect_size_info not in collect_files:
|
|
326
310
|
collect_files.append(app.collect_size_info)
|
|
@@ -352,7 +336,7 @@ def build_apps(
|
|
|
352
336
|
modified_components=modified_components,
|
|
353
337
|
modified_files=modified_files,
|
|
354
338
|
check_app_dependencies=_check_app_dependency(
|
|
355
|
-
manifest_rootpath, modified_components, modified_files,
|
|
339
|
+
manifest_rootpath, modified_components, modified_files, ignore_app_dependencies_filepatterns
|
|
356
340
|
),
|
|
357
341
|
)
|
|
358
342
|
except BuildError as e:
|
|
@@ -468,15 +452,7 @@ class IdfBuildAppsCliFormatter(argparse.HelpFormatter):
|
|
|
468
452
|
else:
|
|
469
453
|
default_type = type(action.default)
|
|
470
454
|
|
|
471
|
-
if
|
|
472
|
-
_help += (
|
|
473
|
-
'. Could be specified for multiple times'
|
|
474
|
-
'{} ! DeprecationWarning: will change to space-separated list in idf-build-apps 1.0.0 version'.format(
|
|
475
|
-
self.LINE_SEP
|
|
476
|
-
)
|
|
477
|
-
)
|
|
478
|
-
_type = 'list[{}]'.format(default_type.__name__)
|
|
479
|
-
elif action.nargs in [argparse.ZERO_OR_MORE, argparse.ONE_OR_MORE]:
|
|
455
|
+
if action.nargs in [argparse.ZERO_OR_MORE, argparse.ONE_OR_MORE]:
|
|
480
456
|
_type = 'list[{}]'.format(default_type.__name__)
|
|
481
457
|
else:
|
|
482
458
|
_type = default_type.__name__
|
|
@@ -522,11 +498,7 @@ def get_parser(): # type: () -> argparse.ArgumentParser
|
|
|
522
498
|
action='store_true',
|
|
523
499
|
help='Look for apps in the specified paths recursively',
|
|
524
500
|
)
|
|
525
|
-
common_args.add_argument(
|
|
526
|
-
'--exclude',
|
|
527
|
-
action='append',
|
|
528
|
-
help='Ignore specified directory (if --recursive is given)',
|
|
529
|
-
)
|
|
501
|
+
common_args.add_argument('--exclude', nargs='+', help='Ignore specified path (if --recursive is given)')
|
|
530
502
|
common_args.add_argument(
|
|
531
503
|
'--work-dir',
|
|
532
504
|
help='If set, the app is first copied into the specified directory, and then built. '
|
|
@@ -548,7 +520,7 @@ def get_parser(): # type: () -> argparse.ArgumentParser
|
|
|
548
520
|
)
|
|
549
521
|
common_args.add_argument(
|
|
550
522
|
'--config',
|
|
551
|
-
|
|
523
|
+
nargs='+',
|
|
552
524
|
help='Adds configurations (sdkconfig file names) to build. '
|
|
553
525
|
'This can either be FILENAME[=NAME] or FILEPATTERN. FILENAME is the name of the sdkconfig file, '
|
|
554
526
|
'relative to the project directory, to be used. Optional NAME can be specified, '
|
|
@@ -578,7 +550,7 @@ def get_parser(): # type: () -> argparse.ArgumentParser
|
|
|
578
550
|
)
|
|
579
551
|
common_args.add_argument(
|
|
580
552
|
'--manifest-file',
|
|
581
|
-
|
|
553
|
+
nargs='+',
|
|
582
554
|
help='Manifest files which specify the build test rules of the apps',
|
|
583
555
|
)
|
|
584
556
|
common_args.add_argument(
|
|
@@ -590,10 +562,7 @@ def get_parser(): # type: () -> argparse.ArgumentParser
|
|
|
590
562
|
'--default-build-targets',
|
|
591
563
|
nargs='+',
|
|
592
564
|
help='space-separated list of supported targets. Targets supported in current ESP-IDF branch '
|
|
593
|
-
'(except preview ones) would be used if this option is not set.'
|
|
594
|
-
'{} ! DeprecationWarning: comma-separated list support will be removed in idf-build-apps 1.0.0 version'.format(
|
|
595
|
-
IdfBuildAppsCliFormatter.LINE_SEP
|
|
596
|
-
),
|
|
565
|
+
'(except preview ones) would be used if this option is not set.',
|
|
597
566
|
)
|
|
598
567
|
common_args.add_argument(
|
|
599
568
|
'--modified-components',
|
|
@@ -612,13 +581,12 @@ def get_parser(): # type: () -> argparse.ArgumentParser
|
|
|
612
581
|
)
|
|
613
582
|
common_args.add_argument(
|
|
614
583
|
'-if',
|
|
615
|
-
'--ignore-
|
|
584
|
+
'--ignore-app-dependencies-filepatterns',
|
|
616
585
|
nargs='*',
|
|
617
586
|
default=None,
|
|
618
|
-
help='space-separated list which specifies the file patterns used for ignoring the
|
|
619
|
-
'The `depends_components` and `depends_filepatterns` set in the manifest files will be ignored when any of '
|
|
620
|
-
'
|
|
621
|
-
'--modified-files',
|
|
587
|
+
help='space-separated list which specifies the file patterns used for ignoring checking the app dependencies. '
|
|
588
|
+
'The `depends_components` and `depends_filepatterns` set in the manifest files will be ignored when any of the '
|
|
589
|
+
'specified file patterns matches any of the modified files. Must be used together with --modified-files',
|
|
622
590
|
)
|
|
623
591
|
|
|
624
592
|
common_args.add_argument(
|
|
@@ -675,7 +643,7 @@ def get_parser(): # type: () -> argparse.ArgumentParser
|
|
|
675
643
|
)
|
|
676
644
|
build_parser.add_argument(
|
|
677
645
|
'--ignore-warning-str',
|
|
678
|
-
|
|
646
|
+
nargs='+',
|
|
679
647
|
help='Ignore the warning string that match the specified regex in the build output',
|
|
680
648
|
)
|
|
681
649
|
build_parser.add_argument(
|
|
@@ -712,20 +680,17 @@ def validate_args(parser, args): # type: (argparse.ArgumentParser, argparse.Nam
|
|
|
712
680
|
default_build_targets = []
|
|
713
681
|
if args.default_build_targets:
|
|
714
682
|
for target in args.default_build_targets:
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
'Current ESP-IDF available targets: {}'.format(_t, ALL_TARGETS)
|
|
721
|
-
)
|
|
722
|
-
|
|
723
|
-
if _t not in default_build_targets:
|
|
724
|
-
default_build_targets.append(_t)
|
|
683
|
+
if target not in ALL_TARGETS:
|
|
684
|
+
raise InvalidCommand(
|
|
685
|
+
'Unrecognizable target {} specified with "--default-build-targets". '
|
|
686
|
+
'Current ESP-IDF available targets: {}'.format(target, ALL_TARGETS)
|
|
687
|
+
)
|
|
725
688
|
|
|
689
|
+
if target not in default_build_targets:
|
|
690
|
+
default_build_targets.append(target)
|
|
726
691
|
args.default_build_targets = default_build_targets
|
|
727
692
|
|
|
728
|
-
if args.
|
|
693
|
+
if args.ignore_app_dependencies_filepatterns:
|
|
729
694
|
if args.modified_files is None:
|
|
730
695
|
raise InvalidCommand(
|
|
731
696
|
'Must specify "--ignore-component-dependencies-file-patterns" with "--modified-files", '
|
|
@@ -767,7 +732,7 @@ def main():
|
|
|
767
732
|
default_build_targets=args.default_build_targets,
|
|
768
733
|
modified_components=args.modified_components,
|
|
769
734
|
modified_files=args.modified_files,
|
|
770
|
-
|
|
735
|
+
ignore_app_dependencies_filepatterns=args.ignore_app_dependencies_filepatterns,
|
|
771
736
|
sdkconfig_defaults=args.sdkconfig_defaults,
|
|
772
737
|
)
|
|
773
738
|
|
|
@@ -801,7 +766,7 @@ def main():
|
|
|
801
766
|
manifest_rootpath=args.manifest_rootpath,
|
|
802
767
|
modified_components=args.modified_components,
|
|
803
768
|
modified_files=args.modified_files,
|
|
804
|
-
|
|
769
|
+
ignore_app_dependencies_filepatterns=args.ignore_app_dependencies_filepatterns,
|
|
805
770
|
)
|
|
806
771
|
|
|
807
772
|
if args.modified_components is not None:
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
|
2
2
|
# SPDX-License-Identifier: Apache-2.0
|
|
3
3
|
|
|
4
|
+
import os
|
|
4
5
|
from ast import (
|
|
5
6
|
literal_eval,
|
|
6
7
|
)
|
|
@@ -86,6 +87,10 @@ class ChipAttr(Stmt):
|
|
|
86
87
|
if self.attr in SOC_HEADERS[target]:
|
|
87
88
|
return SOC_HEADERS[target][self.attr]
|
|
88
89
|
|
|
90
|
+
# for non-keyword cap words, check if it is defined in the environment variables
|
|
91
|
+
if self.attr in os.environ:
|
|
92
|
+
return os.environ[self.attr]
|
|
93
|
+
|
|
89
94
|
return 0 # default return 0 as false
|
|
90
95
|
|
|
91
96
|
|
|
@@ -23,6 +23,12 @@ except ImportError:
|
|
|
23
23
|
pass
|
|
24
24
|
|
|
25
25
|
|
|
26
|
+
if sys.version_info < (3, 5):
|
|
27
|
+
import glob2 as glob
|
|
28
|
+
else:
|
|
29
|
+
import glob
|
|
30
|
+
|
|
31
|
+
|
|
26
32
|
class ConfigRule:
|
|
27
33
|
def __init__(self, file_name, config_name): # type: (str, str) -> None
|
|
28
34
|
"""
|
|
@@ -213,14 +219,17 @@ def files_matches_patterns(
|
|
|
213
219
|
patterns, # type: list[str] | str
|
|
214
220
|
rootpath=None, # type: str
|
|
215
221
|
): # type: (...) -> bool
|
|
216
|
-
# can't match
|
|
222
|
+
# can't match an absolute pattern with a relative path
|
|
217
223
|
# change all to absolute paths
|
|
218
224
|
files = [to_absolute_path(f, rootpath) for f in to_list(files)]
|
|
219
225
|
patterns = [to_absolute_path(p, rootpath) for p in to_list(patterns)]
|
|
220
226
|
|
|
227
|
+
matched_paths = set()
|
|
228
|
+
for pat in patterns:
|
|
229
|
+
matched_paths.update(glob.glob(str(pat), recursive=True))
|
|
230
|
+
|
|
221
231
|
for f in files:
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
return True
|
|
232
|
+
if str(f) in matched_paths:
|
|
233
|
+
return True
|
|
225
234
|
|
|
226
235
|
return False
|
|
@@ -15,6 +15,7 @@ install_requires = \
|
|
|
15
15
|
extras_require = \
|
|
16
16
|
{":python_version < '3.11'": ['toml'],
|
|
17
17
|
":python_version < '3.4'": ['pathlib'],
|
|
18
|
+
":python_version < '3.5'": ['glob2'],
|
|
18
19
|
'doc': ['sphinx',
|
|
19
20
|
'sphinx-rtd-theme',
|
|
20
21
|
'sphinx_copybutton',
|
|
@@ -26,7 +27,7 @@ entry_points = \
|
|
|
26
27
|
{'console_scripts': ['idf-build-apps = idf_build_apps:main.main']}
|
|
27
28
|
|
|
28
29
|
setup(name='idf-build-apps',
|
|
29
|
-
version='1.0.
|
|
30
|
+
version='1.0.1',
|
|
30
31
|
description='Tools for building ESP-IDF related apps.',
|
|
31
32
|
author=None,
|
|
32
33
|
author_email='Fu Hanxi <fuhanxi@espressif.com>',
|
|
@@ -4,6 +4,9 @@ import shutil
|
|
|
4
4
|
|
|
5
5
|
import pytest
|
|
6
6
|
|
|
7
|
+
from idf_build_apps import (
|
|
8
|
+
find_apps,
|
|
9
|
+
)
|
|
7
10
|
from idf_build_apps.app import (
|
|
8
11
|
CMakeApp,
|
|
9
12
|
)
|
|
@@ -74,6 +77,20 @@ class TestBuild:
|
|
|
74
77
|
|
|
75
78
|
assert built == is_built
|
|
76
79
|
|
|
80
|
+
def test_build_without_modified_components_but_ignored_app_dependency_check(self):
|
|
81
|
+
test_dir = str(IDF_PATH / 'examples' / 'get-started' / 'hello_world')
|
|
82
|
+
|
|
83
|
+
apps = find_apps(
|
|
84
|
+
test_dir,
|
|
85
|
+
'esp32',
|
|
86
|
+
modified_components=[],
|
|
87
|
+
modified_files=['foo.c'],
|
|
88
|
+
ignore_app_dependencies_filepatterns=['foo.c'],
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
for app in apps:
|
|
92
|
+
assert app.build()
|
|
93
|
+
|
|
77
94
|
|
|
78
95
|
@pytest.mark.skipif(not shutil.which('idf.py'), reason='idf.py not found')
|
|
79
96
|
def test_idf_version_keywords_type():
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
import logging
|
|
5
5
|
import os
|
|
6
|
+
import tempfile
|
|
6
7
|
from pathlib import (
|
|
7
8
|
Path,
|
|
8
9
|
)
|
|
@@ -185,9 +186,8 @@ get-started:
|
|
|
185
186
|
@pytest.mark.parametrize(
|
|
186
187
|
'modified_components, modified_files, could_find_apps',
|
|
187
188
|
[
|
|
188
|
-
([], '/foo', True),
|
|
189
189
|
([], str(IDF_PATH / 'examples' / 'README.md'), False),
|
|
190
|
-
(None, [str(IDF_PATH / 'examples' / 'get-started' / 'hello_world' / 'a.md')],
|
|
190
|
+
(None, [str(IDF_PATH / 'examples' / 'get-started' / 'hello_world' / 'a.md')], False),
|
|
191
191
|
(
|
|
192
192
|
[],
|
|
193
193
|
[
|
|
@@ -208,7 +208,6 @@ get-started:
|
|
|
208
208
|
f'''
|
|
209
209
|
{test_dir}:
|
|
210
210
|
depends_filepatterns:
|
|
211
|
-
- /foo
|
|
212
211
|
- examples/get-started/hello_world/**
|
|
213
212
|
- examples/foo/**
|
|
214
213
|
''',
|
|
@@ -417,3 +416,84 @@ class TestFindWithSdkconfigFiles:
|
|
|
417
416
|
assert apps[0].sdkconfig_files == [
|
|
418
417
|
str(tmp_path / 'test1' / 'sdkconfig.defaults'),
|
|
419
418
|
]
|
|
419
|
+
|
|
420
|
+
def test_env_var(self, tmp_path, monkeypatch):
|
|
421
|
+
create_project('test1', tmp_path)
|
|
422
|
+
|
|
423
|
+
(tmp_path / 'test1' / 'sdkconfig.ci.foo').touch()
|
|
424
|
+
(tmp_path / 'test1' / 'sdkconfig.ci.bar').touch()
|
|
425
|
+
(tmp_path / 'test1' / 'sdkconfig.ci.baz').touch()
|
|
426
|
+
|
|
427
|
+
yaml_file = tmp_path / 'test.yml'
|
|
428
|
+
yaml_file.write_text(
|
|
429
|
+
f'''
|
|
430
|
+
{tmp_path}:
|
|
431
|
+
enable:
|
|
432
|
+
- if: CONFIG_NAME == "foo" and IDF_TARGET == "esp32"
|
|
433
|
+
- if: CONFIG_NAME == "bar" and IDF_TARGET == "esp32s2"
|
|
434
|
+
- if: TEST_ENV_VAR == "1"
|
|
435
|
+
- if: CONFIG_NAME == "baz" and TEST_ENV_VAR == 0
|
|
436
|
+
''',
|
|
437
|
+
encoding='utf8',
|
|
438
|
+
)
|
|
439
|
+
|
|
440
|
+
# in case you set it...
|
|
441
|
+
monkeypatch.delenv('CONFIG_NAME', raising=False)
|
|
442
|
+
monkeypatch.delenv('TEST_ENV_VAR', raising=False)
|
|
443
|
+
|
|
444
|
+
# CONFIG_NAME should NOT be overridden by env var
|
|
445
|
+
monkeypatch.setenv('CONFIG_NAME', 'bar')
|
|
446
|
+
apps = find_apps(
|
|
447
|
+
str(tmp_path / 'test1'),
|
|
448
|
+
'esp32',
|
|
449
|
+
config_rules_str=['sdkconfig.ci=default', 'sdkconfig.ci.*='],
|
|
450
|
+
manifest_files=yaml_file,
|
|
451
|
+
)
|
|
452
|
+
assert len(apps) == 2
|
|
453
|
+
assert apps[0].sdkconfig_files == [
|
|
454
|
+
str(tmp_path / 'test1' / 'sdkconfig.ci.baz'),
|
|
455
|
+
]
|
|
456
|
+
assert apps[1].sdkconfig_files == [
|
|
457
|
+
str(tmp_path / 'test1' / 'sdkconfig.ci.foo'),
|
|
458
|
+
]
|
|
459
|
+
monkeypatch.delenv('CONFIG_NAME')
|
|
460
|
+
|
|
461
|
+
# env var should be expanded
|
|
462
|
+
monkeypatch.setenv('TEST_ENV_VAR', '1')
|
|
463
|
+
apps = find_apps(
|
|
464
|
+
str(tmp_path / 'test1'),
|
|
465
|
+
'esp32',
|
|
466
|
+
config_rules_str=['sdkconfig.ci=default', 'sdkconfig.ci.*='],
|
|
467
|
+
manifest_files=yaml_file,
|
|
468
|
+
)
|
|
469
|
+
assert len(apps) == 3
|
|
470
|
+
monkeypatch.delenv('TEST_ENV_VAR')
|
|
471
|
+
|
|
472
|
+
|
|
473
|
+
@pytest.mark.parametrize(
|
|
474
|
+
'exclude_list, apps_count',
|
|
475
|
+
[
|
|
476
|
+
(['test1'], 3), # not excluded
|
|
477
|
+
(['folder1/test2'], 2),
|
|
478
|
+
(['folder1'], 1),
|
|
479
|
+
(['folder2/test2'], 2),
|
|
480
|
+
],
|
|
481
|
+
)
|
|
482
|
+
def test_find_apps_with_exclude(tmp_path, exclude_list, apps_count):
|
|
483
|
+
(tmp_path / 'folder1').mkdir()
|
|
484
|
+
(tmp_path / 'folder2').mkdir()
|
|
485
|
+
|
|
486
|
+
create_project('test1', tmp_path / 'folder1')
|
|
487
|
+
create_project('test2', tmp_path / 'folder1')
|
|
488
|
+
create_project('test2', tmp_path / 'folder2')
|
|
489
|
+
|
|
490
|
+
os.chdir(tmp_path)
|
|
491
|
+
apps = find_apps(str(tmp_path), 'esp32', recursive=True, exclude_list=exclude_list)
|
|
492
|
+
assert len(apps) == apps_count
|
|
493
|
+
|
|
494
|
+
# or with absolute_path
|
|
495
|
+
exclude_list = [os.path.abspath(x) for x in exclude_list]
|
|
496
|
+
tmp_path = os.path.abspath(tmp_path)
|
|
497
|
+
os.chdir(tempfile.tempdir)
|
|
498
|
+
apps = find_apps(str(tmp_path), 'esp32', recursive=True, exclude_list=exclude_list)
|
|
499
|
+
assert len(apps) == apps_count
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
|
2
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
import os
|
|
4
|
+
from pathlib import (
|
|
5
|
+
Path,
|
|
6
|
+
)
|
|
7
|
+
|
|
8
|
+
import pytest
|
|
9
|
+
|
|
10
|
+
from idf_build_apps.utils import (
|
|
11
|
+
files_matches_patterns,
|
|
12
|
+
get_parallel_start_stop,
|
|
13
|
+
rmdir,
|
|
14
|
+
to_absolute_path,
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@pytest.mark.parametrize(
|
|
19
|
+
'patterns, expected',
|
|
20
|
+
[
|
|
21
|
+
('*.txt', ['test/inner', 'test/inner/test.txt', 'test/test.txt']),
|
|
22
|
+
(
|
|
23
|
+
['*.txt', '*.log'],
|
|
24
|
+
[
|
|
25
|
+
'test/inner',
|
|
26
|
+
'test/inner/build.log',
|
|
27
|
+
'test/inner/test.txt',
|
|
28
|
+
'test/test.txt',
|
|
29
|
+
],
|
|
30
|
+
),
|
|
31
|
+
],
|
|
32
|
+
)
|
|
33
|
+
def test_rmdir(tmpdir, patterns, expected):
|
|
34
|
+
test_dir = tmpdir.mkdir('test')
|
|
35
|
+
dir1 = test_dir.mkdir('inner')
|
|
36
|
+
test_dir.mkdir('inner2')
|
|
37
|
+
|
|
38
|
+
Path(dir1 / 'test.txt').touch()
|
|
39
|
+
Path(dir1 / 'build.log').touch()
|
|
40
|
+
Path(test_dir / 'test.txt').touch()
|
|
41
|
+
|
|
42
|
+
rmdir(test_dir, exclude_file_patterns=patterns)
|
|
43
|
+
|
|
44
|
+
assert sorted(Path(test_dir).glob('**/*')) == [Path(tmpdir / i) for i in expected]
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
@pytest.mark.parametrize(
|
|
48
|
+
'total, parallel_count, parallel_index, start, stop',
|
|
49
|
+
[
|
|
50
|
+
(1, 1, 1, 1, 1),
|
|
51
|
+
(1, 2, 2, 2, 1),
|
|
52
|
+
(1, 10, 1, 1, 1),
|
|
53
|
+
(6, 4, 1, 1, 2),
|
|
54
|
+
(6, 4, 2, 3, 4),
|
|
55
|
+
(6, 4, 3, 5, 6),
|
|
56
|
+
(6, 4, 4, 7, 6),
|
|
57
|
+
(10, 10, 9, 9, 9),
|
|
58
|
+
(33, 2, 1, 1, 17),
|
|
59
|
+
(33, 2, 2, 18, 33),
|
|
60
|
+
],
|
|
61
|
+
)
|
|
62
|
+
def test_get_parallel_start_stop(total, parallel_count, parallel_index, start, stop):
|
|
63
|
+
assert (start, stop) == get_parallel_start_stop(total, parallel_count, parallel_index)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def test_files_matches_patterns(tmpdir):
|
|
67
|
+
# used for testing absolute paths
|
|
68
|
+
temp_dir = tmpdir.mkdir('temp')
|
|
69
|
+
os.chdir(temp_dir)
|
|
70
|
+
|
|
71
|
+
# create real files
|
|
72
|
+
test_dir = tmpdir.mkdir('test')
|
|
73
|
+
a_dir = test_dir.mkdir('a')
|
|
74
|
+
b_dir = a_dir.mkdir('b')
|
|
75
|
+
c_dir = b_dir.mkdir('c')
|
|
76
|
+
b_py = Path(a_dir / 'b.py')
|
|
77
|
+
c_py = Path(b_dir / 'c.py')
|
|
78
|
+
d_py = Path(c_dir / 'd.py')
|
|
79
|
+
b_py.touch()
|
|
80
|
+
c_py.touch()
|
|
81
|
+
d_py.touch()
|
|
82
|
+
|
|
83
|
+
# ├── temp
|
|
84
|
+
# └── test
|
|
85
|
+
# └── a
|
|
86
|
+
# ├── b
|
|
87
|
+
# │ ├── c
|
|
88
|
+
# │ │ └── d.py
|
|
89
|
+
# │ └── c.py
|
|
90
|
+
# ├── .hidden
|
|
91
|
+
# └── b.py
|
|
92
|
+
#
|
|
93
|
+
|
|
94
|
+
# in correct relative path
|
|
95
|
+
for matched_files, pat, rootpath in [
|
|
96
|
+
([b_py], '*.py', a_dir),
|
|
97
|
+
([b_py, c_py, d_py], '**/*.py', a_dir),
|
|
98
|
+
([c_py], '*.py', b_dir),
|
|
99
|
+
([c_py, d_py], '**/*.py', b_dir),
|
|
100
|
+
([d_py], '*.py', c_dir),
|
|
101
|
+
([d_py], '**/*.py', c_dir),
|
|
102
|
+
]:
|
|
103
|
+
for f in matched_files:
|
|
104
|
+
assert files_matches_patterns(f, pat, rootpath)
|
|
105
|
+
|
|
106
|
+
# in None root path with relative pattern
|
|
107
|
+
for matched_files, pat in [
|
|
108
|
+
([b_py], 'a/*.py'),
|
|
109
|
+
([b_py, c_py, d_py], 'a/**/*.py'),
|
|
110
|
+
([c_py], 'a/b/*.py'),
|
|
111
|
+
([c_py, d_py], 'a/b/**/*.py'),
|
|
112
|
+
([d_py], 'a/b/c/*.py'),
|
|
113
|
+
([d_py], 'a/b/c/**/*.py'),
|
|
114
|
+
]:
|
|
115
|
+
for f in matched_files:
|
|
116
|
+
# with correct pwd
|
|
117
|
+
os.chdir(test_dir)
|
|
118
|
+
assert files_matches_patterns(f, pat)
|
|
119
|
+
|
|
120
|
+
# with wrong pwd
|
|
121
|
+
os.chdir(temp_dir)
|
|
122
|
+
assert not files_matches_patterns(f, pat)
|
|
123
|
+
|
|
124
|
+
# use correct absolute path, in wrong pwd
|
|
125
|
+
for matched_files, pat in [
|
|
126
|
+
([b_py], 'a/*.py'),
|
|
127
|
+
([b_py, c_py, d_py], 'a/**/*.py'),
|
|
128
|
+
([c_py], 'a/b/*.py'),
|
|
129
|
+
([c_py, d_py], 'a/b/**/*.py'),
|
|
130
|
+
([d_py], 'a/b/c/*.py'),
|
|
131
|
+
([d_py], 'a/b/c/**/*.py'),
|
|
132
|
+
]:
|
|
133
|
+
abs_pat = to_absolute_path(pat, test_dir)
|
|
134
|
+
os.chdir(temp_dir)
|
|
135
|
+
for f in matched_files:
|
|
136
|
+
assert files_matches_patterns(f, abs_pat)
|
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
|
2
|
-
# SPDX-License-Identifier: Apache-2.0
|
|
3
|
-
|
|
4
|
-
from pathlib import (
|
|
5
|
-
Path,
|
|
6
|
-
)
|
|
7
|
-
|
|
8
|
-
import pytest
|
|
9
|
-
|
|
10
|
-
from idf_build_apps.utils import (
|
|
11
|
-
files_matches_patterns,
|
|
12
|
-
get_parallel_start_stop,
|
|
13
|
-
rmdir,
|
|
14
|
-
)
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
@pytest.mark.parametrize(
|
|
18
|
-
'patterns, expected',
|
|
19
|
-
[
|
|
20
|
-
('*.txt', ['test/inner', 'test/inner/test.txt', 'test/test.txt']),
|
|
21
|
-
(
|
|
22
|
-
['*.txt', '*.log'],
|
|
23
|
-
[
|
|
24
|
-
'test/inner',
|
|
25
|
-
'test/inner/build.log',
|
|
26
|
-
'test/inner/test.txt',
|
|
27
|
-
'test/test.txt',
|
|
28
|
-
],
|
|
29
|
-
),
|
|
30
|
-
],
|
|
31
|
-
)
|
|
32
|
-
def test_rmdir(tmpdir, patterns, expected):
|
|
33
|
-
test_dir = tmpdir.mkdir('test')
|
|
34
|
-
dir1 = test_dir.mkdir('inner')
|
|
35
|
-
test_dir.mkdir('inner2')
|
|
36
|
-
|
|
37
|
-
Path(dir1 / 'test.txt').touch()
|
|
38
|
-
Path(dir1 / 'build.log').touch()
|
|
39
|
-
Path(test_dir / 'test.txt').touch()
|
|
40
|
-
|
|
41
|
-
rmdir(test_dir, exclude_file_patterns=patterns)
|
|
42
|
-
|
|
43
|
-
assert sorted(Path(test_dir).glob('**/*')) == [Path(tmpdir / i) for i in expected]
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
@pytest.mark.parametrize(
|
|
47
|
-
'total, parallel_count, parallel_index, start, stop',
|
|
48
|
-
[
|
|
49
|
-
(1, 1, 1, 1, 1),
|
|
50
|
-
(1, 2, 2, 2, 1),
|
|
51
|
-
(1, 10, 1, 1, 1),
|
|
52
|
-
(6, 4, 1, 1, 2),
|
|
53
|
-
(6, 4, 2, 3, 4),
|
|
54
|
-
(6, 4, 3, 5, 6),
|
|
55
|
-
(6, 4, 4, 7, 6),
|
|
56
|
-
(10, 10, 9, 9, 9),
|
|
57
|
-
(33, 2, 1, 1, 17),
|
|
58
|
-
(33, 2, 2, 18, 33),
|
|
59
|
-
],
|
|
60
|
-
)
|
|
61
|
-
def test_get_parallel_start_stop(total, parallel_count, parallel_index, start, stop):
|
|
62
|
-
assert (start, stop) == get_parallel_start_stop(total, parallel_count, parallel_index)
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
@pytest.mark.parametrize(
|
|
66
|
-
'files, patterns, rootpath, result',
|
|
67
|
-
[
|
|
68
|
-
('c.py', '*.py', None, True),
|
|
69
|
-
('c.py', '*.py', '/a', True),
|
|
70
|
-
('/a/b/c.py', 'c.py', None, False),
|
|
71
|
-
('/a/b/c.py', 'c.py', '/a/b', True),
|
|
72
|
-
('/a/b/../b/c.py', '*.py', None, False),
|
|
73
|
-
('/a/b/../b/c.py', '*.py', '/a/b', True),
|
|
74
|
-
('/a/b/../b/c.py', '**/*.py', None, False),
|
|
75
|
-
('/a/b/../b/c.py', '**/*.py', '/a', True),
|
|
76
|
-
('c.py', '/a/**/*.py', None, False),
|
|
77
|
-
('c.py', '/a/**/*.py', '/a', False),
|
|
78
|
-
('c.py', '/a/**/*.py', '/a/b', True),
|
|
79
|
-
('/a/b/c.py', '/a/**/*.py', None, True),
|
|
80
|
-
('/a/b/c.py', '/a/**/*.py', 'foo', True),
|
|
81
|
-
],
|
|
82
|
-
)
|
|
83
|
-
def test_files_matches_patterns(files, patterns, rootpath, result):
|
|
84
|
-
assert files_matches_patterns(files, patterns, rootpath) == result
|
|
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
|