idf-build-apps 2.4.2__py3-none-any.whl → 2.5.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- idf_build_apps/__init__.py +1 -1
- idf_build_apps/app.py +31 -27
- idf_build_apps/args.py +846 -0
- idf_build_apps/constants.py +18 -28
- idf_build_apps/finder.py +34 -54
- idf_build_apps/log.py +2 -0
- idf_build_apps/main.py +159 -622
- idf_build_apps/manifest/if_parser.py +14 -13
- idf_build_apps/manifest/manifest.py +124 -28
- idf_build_apps/utils.py +27 -1
- idf_build_apps/vendors/__init__.py +0 -0
- idf_build_apps/vendors/pydantic_sources.py +120 -0
- idf_build_apps/yaml/parser.py +3 -1
- {idf_build_apps-2.4.2.dist-info → idf_build_apps-2.5.0.dist-info}/METADATA +4 -4
- idf_build_apps-2.5.0.dist-info/RECORD +27 -0
- idf_build_apps/build_apps_args.py +0 -64
- idf_build_apps/config.py +0 -91
- idf_build_apps-2.4.2.dist-info/RECORD +0 -26
- {idf_build_apps-2.4.2.dist-info → idf_build_apps-2.5.0.dist-info}/LICENSE +0 -0
- {idf_build_apps-2.4.2.dist-info → idf_build_apps-2.5.0.dist-info}/WHEEL +0 -0
- {idf_build_apps-2.4.2.dist-info → idf_build_apps-2.5.0.dist-info}/entry_points.txt +0 -0
idf_build_apps/main.py
CHANGED
|
@@ -7,11 +7,9 @@ import argparse
|
|
|
7
7
|
import json
|
|
8
8
|
import logging
|
|
9
9
|
import os
|
|
10
|
-
import re
|
|
11
10
|
import sys
|
|
12
11
|
import textwrap
|
|
13
12
|
import typing as t
|
|
14
|
-
from copy import deepcopy
|
|
15
13
|
|
|
16
14
|
import argcomplete
|
|
17
15
|
from pydantic import (
|
|
@@ -19,9 +17,14 @@ from pydantic import (
|
|
|
19
17
|
create_model,
|
|
20
18
|
)
|
|
21
19
|
|
|
22
|
-
from . import (
|
|
23
|
-
|
|
20
|
+
from idf_build_apps.args import (
|
|
21
|
+
BuildArguments,
|
|
22
|
+
DumpManifestShaArguments,
|
|
23
|
+
FindArguments,
|
|
24
|
+
add_args_to_parser,
|
|
25
|
+
apply_config_file,
|
|
24
26
|
)
|
|
27
|
+
|
|
25
28
|
from .app import (
|
|
26
29
|
App,
|
|
27
30
|
AppDeserializer,
|
|
@@ -29,12 +32,6 @@ from .app import (
|
|
|
29
32
|
MakeApp,
|
|
30
33
|
)
|
|
31
34
|
from .autocompletions import activate_completions
|
|
32
|
-
from .build_apps_args import (
|
|
33
|
-
BuildAppsArgs,
|
|
34
|
-
)
|
|
35
|
-
from .config import (
|
|
36
|
-
get_valid_config,
|
|
37
|
-
)
|
|
38
35
|
from .constants import ALL_TARGETS, BuildStatus, completion_instructions
|
|
39
36
|
from .finder import (
|
|
40
37
|
_find_apps,
|
|
@@ -44,189 +41,77 @@ from .junit import (
|
|
|
44
41
|
TestReport,
|
|
45
42
|
TestSuite,
|
|
46
43
|
)
|
|
47
|
-
from .log import (
|
|
48
|
-
setup_logging,
|
|
49
|
-
)
|
|
50
44
|
from .manifest.manifest import (
|
|
51
|
-
FolderRule,
|
|
52
45
|
Manifest,
|
|
53
46
|
)
|
|
54
47
|
from .utils import (
|
|
55
48
|
AutocompleteActivationError,
|
|
56
49
|
InvalidCommand,
|
|
57
|
-
|
|
50
|
+
drop_none_kwargs,
|
|
58
51
|
get_parallel_start_stop,
|
|
59
|
-
semicolon_separated_str_to_list,
|
|
60
|
-
to_absolute_path,
|
|
61
52
|
to_list,
|
|
62
53
|
)
|
|
63
54
|
|
|
64
55
|
LOGGER = logging.getLogger(__name__)
|
|
65
56
|
|
|
66
57
|
|
|
67
|
-
def _check_app_dependency(
|
|
68
|
-
manifest_rootpath: t.Optional[str] = None,
|
|
69
|
-
modified_components: t.Optional[t.List[str]] = None,
|
|
70
|
-
modified_files: t.Optional[t.List[str]] = None,
|
|
71
|
-
ignore_app_dependencies_components: t.Optional[t.List[str]] = None,
|
|
72
|
-
ignore_app_dependencies_filepatterns: t.Optional[t.List[str]] = None,
|
|
73
|
-
) -> bool:
|
|
74
|
-
# not check since modified_components and modified_files are not passed
|
|
75
|
-
if modified_components is None and modified_files is None:
|
|
76
|
-
return False
|
|
77
|
-
|
|
78
|
-
# not check since ignore_app_dependencies_components is passed and matched
|
|
79
|
-
if (
|
|
80
|
-
ignore_app_dependencies_components
|
|
81
|
-
and modified_components is not None
|
|
82
|
-
and set(modified_components).intersection(ignore_app_dependencies_components)
|
|
83
|
-
):
|
|
84
|
-
LOGGER.info(
|
|
85
|
-
'Build all apps since modified components %s matches ignored components %s',
|
|
86
|
-
', '.join(modified_components),
|
|
87
|
-
', '.join(ignore_app_dependencies_components),
|
|
88
|
-
)
|
|
89
|
-
return False
|
|
90
|
-
|
|
91
|
-
# not check since ignore_app_dependencies_filepatterns is passed and matched
|
|
92
|
-
if (
|
|
93
|
-
ignore_app_dependencies_filepatterns
|
|
94
|
-
and modified_files is not None
|
|
95
|
-
and files_matches_patterns(modified_files, ignore_app_dependencies_filepatterns, manifest_rootpath)
|
|
96
|
-
):
|
|
97
|
-
LOGGER.info(
|
|
98
|
-
'Build all apps since modified files %s matches ignored file patterns %s',
|
|
99
|
-
', '.join(modified_files),
|
|
100
|
-
', '.join(ignore_app_dependencies_filepatterns),
|
|
101
|
-
)
|
|
102
|
-
return False
|
|
103
|
-
|
|
104
|
-
return True
|
|
105
|
-
|
|
106
|
-
|
|
107
58
|
def find_apps(
|
|
108
|
-
paths: t.Union[t.List[str], str],
|
|
109
|
-
target: str,
|
|
59
|
+
paths: t.Union[t.List[str], str, None] = None,
|
|
60
|
+
target: t.Optional[str] = None,
|
|
110
61
|
*,
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
work_dir: t.Optional[str] = None,
|
|
115
|
-
build_dir: str = 'build',
|
|
116
|
-
config_rules_str: t.Optional[t.Union[t.List[str], str]] = None,
|
|
117
|
-
build_log_filename: t.Optional[str] = None,
|
|
118
|
-
size_json_filename: t.Optional[str] = None,
|
|
119
|
-
check_warnings: bool = False,
|
|
120
|
-
preserve: bool = True,
|
|
121
|
-
manifest_rootpath: t.Optional[str] = None,
|
|
122
|
-
manifest_files: t.Optional[t.Union[t.List[str], str]] = None,
|
|
123
|
-
check_manifest_rules: bool = False,
|
|
124
|
-
default_build_targets: t.Optional[t.Union[t.List[str], str]] = None,
|
|
125
|
-
modified_components: t.Optional[t.Union[t.List[str], str]] = None,
|
|
126
|
-
modified_files: t.Optional[t.Union[t.List[str], str]] = None,
|
|
127
|
-
ignore_app_dependencies_components: t.Optional[t.Union[t.List[str], str]] = None,
|
|
128
|
-
ignore_app_dependencies_filepatterns: t.Optional[t.Union[t.List[str], str]] = None,
|
|
129
|
-
sdkconfig_defaults: t.Optional[str] = None,
|
|
130
|
-
include_skipped_apps: bool = False,
|
|
131
|
-
include_disabled_apps: bool = False,
|
|
62
|
+
find_arguments: t.Optional[FindArguments] = None,
|
|
63
|
+
config_file: t.Optional[str] = None,
|
|
64
|
+
**kwargs,
|
|
132
65
|
) -> t.List[App]:
|
|
133
66
|
"""
|
|
134
|
-
Find
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
:param paths: list of app directories (can be / usually will be a relative path)
|
|
138
|
-
:param target: desired value of IDF_TARGET; apps incompatible with the given target are skipped.
|
|
139
|
-
:param build_system: class of the build system, default CMakeApp
|
|
140
|
-
:param recursive: Recursively search into the nested sub-folders if no app is found or not
|
|
141
|
-
:param exclude_list: list of paths to be excluded from the recursive search
|
|
142
|
-
:param work_dir: directory where the app should be copied before building. Support placeholders
|
|
143
|
-
:param build_dir: directory where the build will be done. Support placeholders.
|
|
144
|
-
:param config_rules_str: mapping of sdkconfig file name patterns to configuration names
|
|
145
|
-
:param build_log_filename: filename of the build log. Will be placed under the app.build_path.
|
|
146
|
-
Support placeholders. The logs will go to stdout/stderr if not specified
|
|
147
|
-
:param size_json_filename: filename to collect the app's size information. Will be placed under the app.build_path.
|
|
148
|
-
Support placeholders. The app's size information won't be collected if not specified
|
|
149
|
-
:param check_warnings: Check for warnings in the build log or not
|
|
150
|
-
:param preserve: Preserve the built binaries or not
|
|
151
|
-
:param manifest_rootpath: The root path of the manifest files. Usually the folders specified in the manifest files
|
|
152
|
-
are relative paths. Use the current directory if not specified
|
|
153
|
-
:param manifest_files: paths of the manifest files
|
|
154
|
-
:param check_manifest_rules: check the manifest rules or not
|
|
155
|
-
:param default_build_targets: default build targets used in manifest files
|
|
156
|
-
:param modified_components: modified components
|
|
157
|
-
:param modified_files: modified files
|
|
158
|
-
:param ignore_app_dependencies_components: components used for ignoring checking the app dependencies
|
|
159
|
-
:param ignore_app_dependencies_filepatterns: file patterns used for ignoring checking the app dependencies
|
|
160
|
-
:param sdkconfig_defaults: semicolon-separated string, pass to idf.py -DSDKCONFIG_DEFAULTS if specified,
|
|
161
|
-
also could be set via environment variables "SDKCONFIG_DEFAULTS"
|
|
162
|
-
:param include_skipped_apps: include skipped apps or not
|
|
163
|
-
:param include_disabled_apps: include disabled apps or not
|
|
67
|
+
Find apps in the given paths for the specified target. For all kwargs, please refer to `FindArguments`
|
|
68
|
+
|
|
164
69
|
:return: list of found apps
|
|
165
70
|
"""
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
71
|
+
apply_config_file(config_file)
|
|
72
|
+
|
|
73
|
+
# compatible with old usage
|
|
74
|
+
## `preserve`
|
|
75
|
+
if 'preserve' in kwargs:
|
|
76
|
+
LOGGER.warning(
|
|
77
|
+
'Passing "preserve" directly is deprecated. '
|
|
78
|
+
'Pass "no_preserve" instead to disable preserving the build directory'
|
|
79
|
+
)
|
|
80
|
+
kwargs['no_preserve'] = not kwargs.pop('preserve')
|
|
81
|
+
|
|
82
|
+
if find_arguments is None:
|
|
83
|
+
find_arguments = FindArguments(
|
|
84
|
+
paths=to_list(paths), # type: ignore
|
|
85
|
+
target=target, # type: ignore
|
|
86
|
+
**kwargs,
|
|
87
|
+
)
|
|
170
88
|
|
|
171
|
-
|
|
89
|
+
app_cls: t.Type[App]
|
|
90
|
+
if isinstance(find_arguments.build_system, str):
|
|
172
91
|
# backwards compatible
|
|
173
|
-
if build_system == 'cmake':
|
|
174
|
-
|
|
175
|
-
elif build_system == 'make':
|
|
176
|
-
|
|
92
|
+
if find_arguments.build_system == 'cmake':
|
|
93
|
+
app_cls = CMakeApp
|
|
94
|
+
elif find_arguments.build_system == 'make':
|
|
95
|
+
app_cls = MakeApp
|
|
177
96
|
else:
|
|
178
97
|
raise ValueError('Only Support "make" and "cmake"')
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
# always set the manifest rootpath at the very beginning of find_apps in case ESP-IDF switches the branch.
|
|
182
|
-
Manifest.ROOTPATH = to_absolute_path(manifest_rootpath or os.curdir)
|
|
183
|
-
Manifest.CHECK_MANIFEST_RULES = check_manifest_rules
|
|
184
|
-
|
|
185
|
-
if manifest_files:
|
|
186
|
-
App.MANIFEST = Manifest.from_files(to_list(manifest_files))
|
|
187
|
-
|
|
188
|
-
modified_components = to_list(modified_components)
|
|
189
|
-
modified_files = to_list(modified_files)
|
|
190
|
-
ignore_app_dependencies_components = to_list(ignore_app_dependencies_components)
|
|
191
|
-
ignore_app_dependencies_filepatterns = to_list(ignore_app_dependencies_filepatterns)
|
|
192
|
-
config_rules_str = to_list(config_rules_str)
|
|
98
|
+
else:
|
|
99
|
+
app_cls = find_arguments.build_system
|
|
193
100
|
|
|
194
101
|
apps = []
|
|
195
|
-
if target == 'all':
|
|
102
|
+
if find_arguments.target == 'all':
|
|
196
103
|
targets = ALL_TARGETS
|
|
197
104
|
else:
|
|
198
|
-
targets = [target]
|
|
105
|
+
targets = [find_arguments.target]
|
|
199
106
|
|
|
200
|
-
for
|
|
201
|
-
for
|
|
202
|
-
path = path.strip()
|
|
107
|
+
for _t in targets:
|
|
108
|
+
for _p in find_arguments.paths:
|
|
203
109
|
apps.extend(
|
|
204
110
|
_find_apps(
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
app_cls,
|
|
208
|
-
|
|
209
|
-
exclude_list or [],
|
|
210
|
-
work_dir=work_dir,
|
|
211
|
-
build_dir=build_dir or 'build',
|
|
212
|
-
config_rules_str=config_rules_str,
|
|
213
|
-
build_log_filename=build_log_filename,
|
|
214
|
-
size_json_filename=size_json_filename,
|
|
215
|
-
check_warnings=check_warnings,
|
|
216
|
-
preserve=preserve,
|
|
217
|
-
manifest_rootpath=manifest_rootpath,
|
|
218
|
-
check_app_dependencies=_check_app_dependency(
|
|
219
|
-
manifest_rootpath=manifest_rootpath,
|
|
220
|
-
modified_components=modified_components,
|
|
221
|
-
modified_files=modified_files,
|
|
222
|
-
ignore_app_dependencies_components=ignore_app_dependencies_components,
|
|
223
|
-
ignore_app_dependencies_filepatterns=ignore_app_dependencies_filepatterns,
|
|
224
|
-
),
|
|
225
|
-
modified_components=modified_components,
|
|
226
|
-
modified_files=modified_files,
|
|
227
|
-
sdkconfig_defaults_str=sdkconfig_defaults,
|
|
228
|
-
include_skipped_apps=include_skipped_apps,
|
|
229
|
-
include_disabled_apps=include_disabled_apps,
|
|
111
|
+
_p,
|
|
112
|
+
_t,
|
|
113
|
+
app_cls=app_cls,
|
|
114
|
+
args=find_arguments,
|
|
230
115
|
)
|
|
231
116
|
)
|
|
232
117
|
|
|
@@ -236,85 +121,48 @@ def find_apps(
|
|
|
236
121
|
|
|
237
122
|
|
|
238
123
|
def build_apps(
|
|
239
|
-
apps: t.Union[t.List[App], App],
|
|
124
|
+
apps: t.Union[t.List[App], App, None] = None,
|
|
240
125
|
*,
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
ignore_warning_strs: t.Optional[t.List[str]] = None,
|
|
245
|
-
ignore_warning_file: t.Optional[t.TextIO] = None,
|
|
246
|
-
copy_sdkconfig: bool = False,
|
|
247
|
-
manifest_rootpath: t.Optional[str] = None,
|
|
248
|
-
modified_components: t.Optional[t.Union[t.List[str], str]] = None,
|
|
249
|
-
modified_files: t.Optional[t.Union[t.List[str], str]] = None,
|
|
250
|
-
ignore_app_dependencies_components: t.Optional[t.Union[t.List[str], str]] = None,
|
|
251
|
-
ignore_app_dependencies_filepatterns: t.Optional[t.Union[t.List[str], str]] = None,
|
|
252
|
-
check_app_dependencies: t.Optional[bool] = None,
|
|
253
|
-
# BuildAppsArgs
|
|
254
|
-
parallel_count: int = 1,
|
|
255
|
-
parallel_index: int = 1,
|
|
256
|
-
collect_size_info: t.Optional[str] = None,
|
|
257
|
-
collect_app_info: t.Optional[str] = None,
|
|
258
|
-
junitxml: t.Optional[str] = None,
|
|
126
|
+
build_arguments: t.Optional[BuildArguments] = None,
|
|
127
|
+
config_file: t.Optional[str] = None,
|
|
128
|
+
**kwargs,
|
|
259
129
|
) -> int:
|
|
260
130
|
"""
|
|
261
|
-
Build all the specified apps
|
|
262
|
-
|
|
263
|
-
:param apps: list of apps to be built
|
|
264
|
-
:param build_verbose: call ``--verbose`` in ``idf.py build`` or not
|
|
265
|
-
:param dry_run: simulate this run or not
|
|
266
|
-
:param keep_going: keep building or not if one app's build failed
|
|
267
|
-
:param ignore_warning_strs: ignore build warnings that matches any of the specified regex patterns
|
|
268
|
-
:param ignore_warning_file: ignore build warnings that matches any of the lines of the regex patterns in the
|
|
269
|
-
specified file
|
|
270
|
-
:param copy_sdkconfig: copy the sdkconfig file to the build directory or not
|
|
271
|
-
:param manifest_rootpath: The root path of the manifest files. Usually the folders specified in the manifest files
|
|
272
|
-
are relative paths. Use the current directory if not specified
|
|
273
|
-
:param modified_components: modified components
|
|
274
|
-
:param modified_files: modified files
|
|
275
|
-
:param ignore_app_dependencies_components: components used for ignoring checking the app dependencies
|
|
276
|
-
:param ignore_app_dependencies_filepatterns: file patterns used for ignoring checking the app dependencies
|
|
277
|
-
:param check_app_dependencies: check app dependencies or not. if not set, will be calculated by modified_components,
|
|
278
|
-
modified_files, and ignore_app_dependencies_filepatterns
|
|
279
|
-
:param parallel_count: number of parallel tasks to run
|
|
280
|
-
:param parallel_index: index of the parallel task to run
|
|
281
|
-
:param collect_size_info: file path to record all generated size files' paths if specified
|
|
282
|
-
:param collect_app_info: file path to record all the built apps' info if specified
|
|
283
|
-
:param junitxml: path of the junitxml file
|
|
131
|
+
Build all the specified apps. For all kwargs, please refer to `BuildArguments`
|
|
132
|
+
|
|
284
133
|
:return: exit code
|
|
285
134
|
"""
|
|
135
|
+
apply_config_file(config_file)
|
|
136
|
+
|
|
137
|
+
# compatible with old usage
|
|
138
|
+
## `check_app_dependencies`
|
|
139
|
+
if 'check_app_dependencies' in kwargs:
|
|
140
|
+
LOGGER.warning(
|
|
141
|
+
'Passing "check_app_dependencies" directly is deprecated. '
|
|
142
|
+
'Pass "modified_components" instead to enable dependency-driven build feature'
|
|
143
|
+
)
|
|
144
|
+
kwargs.pop('check_app_dependencies')
|
|
145
|
+
|
|
146
|
+
if build_arguments is None:
|
|
147
|
+
build_arguments = BuildArguments(
|
|
148
|
+
**kwargs,
|
|
149
|
+
)
|
|
150
|
+
|
|
286
151
|
apps = to_list(apps)
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
152
|
+
if apps is None:
|
|
153
|
+
apps = find_apps(
|
|
154
|
+
find_arguments=FindArguments(
|
|
155
|
+
**{k: v for k, v in build_arguments.model_dump().items() if k in FindArguments.model_fields}
|
|
156
|
+
)
|
|
157
|
+
)
|
|
291
158
|
|
|
292
159
|
test_suite = TestSuite('build_apps')
|
|
293
160
|
|
|
294
|
-
|
|
295
|
-
if ignore_warning_strs:
|
|
296
|
-
for s in ignore_warning_strs:
|
|
297
|
-
ignore_warnings_regexes.append(re.compile(s))
|
|
298
|
-
if ignore_warning_file:
|
|
299
|
-
for s in ignore_warning_file:
|
|
300
|
-
ignore_warnings_regexes.append(re.compile(s.strip()))
|
|
301
|
-
App.IGNORE_WARNS_REGEXES = ignore_warnings_regexes
|
|
302
|
-
|
|
303
|
-
start, stop = get_parallel_start_stop(len(apps), parallel_count, parallel_index)
|
|
161
|
+
start, stop = get_parallel_start_stop(len(apps), build_arguments.parallel_count, build_arguments.parallel_index)
|
|
304
162
|
LOGGER.info('Total %s apps. running build for app %s-%s', len(apps), start, stop)
|
|
305
163
|
|
|
306
|
-
build_apps_args = BuildAppsArgs(
|
|
307
|
-
parallel_count=parallel_count,
|
|
308
|
-
parallel_index=parallel_index,
|
|
309
|
-
collect_size_info=collect_size_info,
|
|
310
|
-
collect_app_info=collect_app_info,
|
|
311
|
-
junitxml=junitxml,
|
|
312
|
-
)
|
|
313
|
-
for app in apps[start - 1 : stop]: # we use 1-based
|
|
314
|
-
app.build_apps_args = build_apps_args
|
|
315
|
-
|
|
316
164
|
# cleanup collect files if exists at this early-stage
|
|
317
|
-
for f in (
|
|
165
|
+
for f in (build_arguments.collect_app_info, build_arguments.collect_size_info, build_arguments.junitxml):
|
|
318
166
|
if f and os.path.isfile(f):
|
|
319
167
|
os.remove(f)
|
|
320
168
|
LOGGER.debug('Remove existing collect file %s', f)
|
|
@@ -326,26 +174,18 @@ def build_apps(
|
|
|
326
174
|
continue
|
|
327
175
|
|
|
328
176
|
# attrs
|
|
329
|
-
app.dry_run = dry_run
|
|
177
|
+
app.dry_run = build_arguments.dry_run
|
|
330
178
|
app.index = index
|
|
331
|
-
app.verbose = build_verbose
|
|
332
|
-
app.copy_sdkconfig = copy_sdkconfig
|
|
179
|
+
app.verbose = build_arguments.build_verbose
|
|
180
|
+
app.copy_sdkconfig = build_arguments.copy_sdkconfig
|
|
333
181
|
|
|
334
182
|
LOGGER.info('(%s/%s) Building app: %s', index, len(apps), app)
|
|
335
183
|
|
|
336
184
|
app.build(
|
|
337
|
-
manifest_rootpath=manifest_rootpath,
|
|
338
|
-
modified_components=modified_components,
|
|
339
|
-
modified_files=modified_files,
|
|
340
|
-
check_app_dependencies=
|
|
341
|
-
manifest_rootpath=manifest_rootpath,
|
|
342
|
-
modified_components=modified_components,
|
|
343
|
-
modified_files=modified_files,
|
|
344
|
-
ignore_app_dependencies_components=ignore_app_dependencies_components,
|
|
345
|
-
ignore_app_dependencies_filepatterns=ignore_app_dependencies_filepatterns,
|
|
346
|
-
)
|
|
347
|
-
if check_app_dependencies is None
|
|
348
|
-
else check_app_dependencies,
|
|
185
|
+
manifest_rootpath=build_arguments.manifest_rootpath,
|
|
186
|
+
modified_components=build_arguments.modified_components,
|
|
187
|
+
modified_files=build_arguments.modified_files,
|
|
188
|
+
check_app_dependencies=build_arguments.dependency_driven_build_enabled,
|
|
349
189
|
)
|
|
350
190
|
test_suite.add_test_case(TestCase.from_app(app))
|
|
351
191
|
|
|
@@ -354,20 +194,20 @@ def build_apps(
|
|
|
354
194
|
else:
|
|
355
195
|
LOGGER.info('%s', app.build_status.value)
|
|
356
196
|
|
|
357
|
-
if
|
|
358
|
-
with open(
|
|
197
|
+
if build_arguments.collect_app_info:
|
|
198
|
+
with open(build_arguments.collect_app_info, 'a') as fw:
|
|
359
199
|
fw.write(app.to_json() + '\n')
|
|
360
|
-
LOGGER.debug('Recorded app info in %s',
|
|
200
|
+
LOGGER.debug('Recorded app info in %s', build_arguments.collect_app_info)
|
|
361
201
|
|
|
362
202
|
if app.build_status == BuildStatus.FAILED:
|
|
363
|
-
if not keep_going:
|
|
203
|
+
if not build_arguments.keep_going:
|
|
364
204
|
return 1
|
|
365
205
|
else:
|
|
366
206
|
exit_code = 1
|
|
367
207
|
elif app.build_status == BuildStatus.SUCCESS:
|
|
368
|
-
if
|
|
208
|
+
if build_arguments.collect_size_info and app.size_json_path:
|
|
369
209
|
if os.path.isfile(app.size_json_path):
|
|
370
|
-
with open(
|
|
210
|
+
with open(build_arguments.collect_size_info, 'a') as fw:
|
|
371
211
|
fw.write(
|
|
372
212
|
json.dumps(
|
|
373
213
|
{
|
|
@@ -379,13 +219,13 @@ def build_apps(
|
|
|
379
219
|
)
|
|
380
220
|
+ '\n'
|
|
381
221
|
)
|
|
382
|
-
LOGGER.debug('Recorded size info file path in %s',
|
|
222
|
+
LOGGER.debug('Recorded size info file path in %s', build_arguments.collect_size_info)
|
|
383
223
|
|
|
384
224
|
LOGGER.info('') # add one empty line for separating different builds
|
|
385
225
|
|
|
386
|
-
if
|
|
387
|
-
TestReport([test_suite],
|
|
388
|
-
LOGGER.info('Generated junit report for build apps: %s',
|
|
226
|
+
if build_arguments.junitxml:
|
|
227
|
+
TestReport([test_suite], build_arguments.junitxml).create_test_report()
|
|
228
|
+
LOGGER.info('Generated junit report for build apps: %s', build_arguments.junitxml)
|
|
389
229
|
|
|
390
230
|
return exit_code
|
|
391
231
|
|
|
@@ -438,7 +278,7 @@ class IdfBuildAppsCliFormatter(argparse.HelpFormatter):
|
|
|
438
278
|
|
|
439
279
|
def get_parser() -> argparse.ArgumentParser:
|
|
440
280
|
parser = argparse.ArgumentParser(
|
|
441
|
-
description='Tools for building ESP-IDF related apps.'
|
|
281
|
+
description='Tools for building ESP-IDF related apps. '
|
|
442
282
|
'Some CLI options can be expanded by the following placeholders, like "--work-dir", "--build-dir", etc.:\n'
|
|
443
283
|
'- @t: would be replaced by the target chip type\n'
|
|
444
284
|
'- @w: would be replaced by the wildcard, usually the sdkconfig\n'
|
|
@@ -449,176 +289,14 @@ def get_parser() -> argparse.ArgumentParser:
|
|
|
449
289
|
'- @p: would be replaced by the parallel index (only available in `build` command)',
|
|
450
290
|
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
451
291
|
)
|
|
452
|
-
actions = parser.add_subparsers(dest='action')
|
|
292
|
+
actions = parser.add_subparsers(dest='action', required=True)
|
|
453
293
|
|
|
454
294
|
common_args = argparse.ArgumentParser(add_help=False)
|
|
455
|
-
common_args.add_argument(
|
|
456
|
-
'-c',
|
|
457
|
-
'--config-file',
|
|
458
|
-
help='Path to the default configuration file, toml file',
|
|
459
|
-
)
|
|
460
|
-
|
|
461
|
-
common_args.add_argument('-p', '--paths', nargs='+', help='One or more paths to look for apps')
|
|
462
|
-
common_args.add_argument('-t', '--target', help='filter apps by given target')
|
|
463
|
-
common_args.add_argument(
|
|
464
|
-
'--build-system', default='cmake', choices=['cmake', 'make'], help='filter apps by given build system'
|
|
465
|
-
)
|
|
466
|
-
common_args.add_argument(
|
|
467
|
-
'--recursive',
|
|
468
|
-
action='store_true',
|
|
469
|
-
help='Look for apps in the specified paths recursively',
|
|
470
|
-
)
|
|
471
|
-
common_args.add_argument('--exclude', nargs='+', help='Ignore specified path (if --recursive is given)')
|
|
472
|
-
common_args.add_argument(
|
|
473
|
-
'--work-dir',
|
|
474
|
-
help='If set, the app is first copied into the specified directory, and then built. '
|
|
475
|
-
'If not set, the work directory is the directory of the app. Can expand placeholders',
|
|
476
|
-
)
|
|
477
|
-
common_args.add_argument(
|
|
478
|
-
'--build-dir',
|
|
479
|
-
default='build',
|
|
480
|
-
help='If set, specifies the build directory name. Can be either a name relative to the work directory, '
|
|
481
|
-
'or an absolute path. Can expand placeholders',
|
|
482
|
-
)
|
|
483
|
-
common_args.add_argument(
|
|
484
|
-
'--build-log',
|
|
485
|
-
help='Relative to build dir. The build log will be written to this file instead of sys.stdout if specified. '
|
|
486
|
-
'Can expand placeholders',
|
|
487
|
-
)
|
|
488
|
-
common_args.add_argument(
|
|
489
|
-
'--size-file',
|
|
490
|
-
help='Relative to build dir. The size json will be written to this file if specified. Can expand placeholders',
|
|
491
|
-
)
|
|
492
|
-
common_args.add_argument(
|
|
493
|
-
'--config',
|
|
494
|
-
nargs='+',
|
|
495
|
-
help='Adds configurations (sdkconfig file names) to build. '
|
|
496
|
-
'This can either be FILENAME[=NAME] or FILEPATTERN. FILENAME is the name of the sdkconfig file, '
|
|
497
|
-
'relative to the project directory, to be used. Optional NAME can be specified, '
|
|
498
|
-
'which can be used as a name of this configuration. FILEPATTERN is the name of '
|
|
499
|
-
'the sdkconfig file, relative to the project directory, with at most one wildcard. '
|
|
500
|
-
'The part captured by the wildcard is used as the name of the configuration',
|
|
501
|
-
)
|
|
502
|
-
|
|
503
|
-
common_args.add_argument(
|
|
504
|
-
'--override-sdkconfig-items',
|
|
505
|
-
nargs='?',
|
|
506
|
-
type=str,
|
|
507
|
-
help='The --override-sdkconfig-items option is a comma-separated list '
|
|
508
|
-
'that permits the overriding of specific configuration items defined '
|
|
509
|
-
"in the SDK's sdkconfig file and Kconfig using a command-line argument. "
|
|
510
|
-
'The sdkconfig items specified here override the same sdkconfig '
|
|
511
|
-
'item defined in the --override-sdkconfig-files, if exists.',
|
|
512
|
-
)
|
|
513
|
-
common_args.add_argument(
|
|
514
|
-
'--override-sdkconfig-files',
|
|
515
|
-
nargs='?',
|
|
516
|
-
type=str,
|
|
517
|
-
help='"The --override-sdkconfig-files option is a comma-separated list, '
|
|
518
|
-
'which provides an alternative (alt: --override-sdkconfig-items) '
|
|
519
|
-
'approach for overriding SDK configuration items. '
|
|
520
|
-
'The filepath may be global or relative to the root.',
|
|
521
|
-
)
|
|
522
|
-
common_args.add_argument(
|
|
523
|
-
'--sdkconfig-defaults',
|
|
524
|
-
help='semicolon-separated string, pass to idf.py -DSDKCONFIG_DEFAULTS if specified, also could be set via '
|
|
525
|
-
'environment variables "SDKCONFIG_DEFAULTS"',
|
|
526
|
-
)
|
|
527
|
-
common_args.add_argument(
|
|
528
|
-
'-v',
|
|
529
|
-
'--verbose',
|
|
530
|
-
default=0,
|
|
531
|
-
action='count',
|
|
532
|
-
help='Increase the logging level of the whole process. Can be specified multiple times. '
|
|
533
|
-
'By default set to WARNING level. '
|
|
534
|
-
'Specify once to set to INFO level. '
|
|
535
|
-
'Specify twice or more to set to DEBUG level',
|
|
536
|
-
)
|
|
537
|
-
common_args.add_argument(
|
|
538
|
-
'--log-file',
|
|
539
|
-
help='Write the log to the specified file, instead of stderr',
|
|
540
|
-
)
|
|
541
|
-
common_args.add_argument(
|
|
542
|
-
'--check-warnings', action='store_true', help='If set, fail the build if warnings are found'
|
|
543
|
-
)
|
|
544
|
-
|
|
545
|
-
common_args.add_argument(
|
|
546
|
-
'--manifest-file',
|
|
547
|
-
nargs='+',
|
|
548
|
-
help='Manifest files which specify the build test rules of the apps',
|
|
549
|
-
)
|
|
550
|
-
common_args.add_argument(
|
|
551
|
-
'--manifest-rootpath',
|
|
552
|
-
help='Root directory for calculating the realpath of the relative path defined in the manifest files. '
|
|
553
|
-
'Would use the current directory if not set',
|
|
554
|
-
)
|
|
555
|
-
common_args.add_argument(
|
|
556
|
-
'--check-manifest-rules',
|
|
557
|
-
action='store_true',
|
|
558
|
-
help='Exit with error if any of the manifest rules does not exist on your filesystem',
|
|
559
|
-
)
|
|
560
|
-
common_args.add_argument(
|
|
561
|
-
'--enable-preview-targets',
|
|
562
|
-
action='store_true',
|
|
563
|
-
help='Build the apps with all targets in the current ESP-IDF branch, '
|
|
564
|
-
'including preview targets, when the app supports the target.',
|
|
565
|
-
)
|
|
566
|
-
common_args.add_argument(
|
|
567
|
-
'--default-build-targets',
|
|
568
|
-
nargs='+',
|
|
569
|
-
help='space-separated list of string which specifies the targets for building the apps. '
|
|
570
|
-
'If provided, the apps will be built only with the specified targets '
|
|
571
|
-
'when the app supports the target.',
|
|
572
|
-
)
|
|
573
|
-
common_args.add_argument(
|
|
574
|
-
'--modified-components',
|
|
575
|
-
type=semicolon_separated_str_to_list,
|
|
576
|
-
help='semicolon-separated string which specifies the modified components. '
|
|
577
|
-
'app with `depends_components` set in the corresponding manifest files would only be built '
|
|
578
|
-
'if depends on any of the specified components. '
|
|
579
|
-
'If set to "", the value would be considered as None. '
|
|
580
|
-
'If set to ";", the value would be considered as an empty list',
|
|
581
|
-
)
|
|
582
|
-
common_args.add_argument(
|
|
583
|
-
'--modified-files',
|
|
584
|
-
type=semicolon_separated_str_to_list,
|
|
585
|
-
help='semicolon-separated string which specifies the modified files. '
|
|
586
|
-
'app with `depends_filepatterns` set in the corresponding manifest files would only be built '
|
|
587
|
-
'if any of the specified file pattern matches any of the specified modified files. '
|
|
588
|
-
'If set to "", the value would be considered as None. '
|
|
589
|
-
'If set to ";", the value would be considered as an empty list',
|
|
590
|
-
)
|
|
591
|
-
common_args.add_argument(
|
|
592
|
-
'-ic',
|
|
593
|
-
'--ignore-app-dependencies-components',
|
|
594
|
-
type=semicolon_separated_str_to_list,
|
|
595
|
-
help='semicolon-separated string which specifies the modified components used for '
|
|
596
|
-
'ignoring checking the app dependencies. '
|
|
597
|
-
'The `depends_components` and `depends_filepatterns` set in the manifest files will be ignored when any of the '
|
|
598
|
-
'specified components matches any of the modified components. '
|
|
599
|
-
'Must be used together with --modified-components. '
|
|
600
|
-
'If set to "", the value would be considered as None. '
|
|
601
|
-
'If set to ";", the value would be considered as an empty list',
|
|
602
|
-
)
|
|
603
|
-
common_args.add_argument(
|
|
604
|
-
'-if',
|
|
605
|
-
'--ignore-app-dependencies-filepatterns',
|
|
606
|
-
type=semicolon_separated_str_to_list,
|
|
607
|
-
help='semicolon-separated string which specifies the file patterns used for '
|
|
608
|
-
'ignoring checking the app dependencies. '
|
|
609
|
-
'The `depends_components` and `depends_filepatterns` set in the manifest files will be ignored when any of the '
|
|
610
|
-
'specified file patterns matches any of the modified files. '
|
|
611
|
-
'Must be used together with --modified-files. '
|
|
612
|
-
'If set to "", the value would be considered as None. '
|
|
613
|
-
'If set to ";", the value would be considered as an empty list',
|
|
614
|
-
)
|
|
615
|
-
|
|
616
|
-
common_args.add_argument(
|
|
617
|
-
'--no-color',
|
|
618
|
-
action='store_true',
|
|
619
|
-
help='enable colored output by default on UNIX-like systems. enable this flag to make the logs uncolored.',
|
|
620
|
-
)
|
|
295
|
+
common_args.add_argument('--config-file', help='Path to the config file')
|
|
621
296
|
|
|
297
|
+
########
|
|
298
|
+
# Find #
|
|
299
|
+
########
|
|
622
300
|
find_parser = actions.add_parser(
|
|
623
301
|
'find',
|
|
624
302
|
help='Find the buildable applications. Run `idf-build-apps find --help` for more information on a command.',
|
|
@@ -626,95 +304,27 @@ def get_parser() -> argparse.ArgumentParser:
|
|
|
626
304
|
'`--path` and `--target` options must be provided. '
|
|
627
305
|
'By default, print the found apps in stdout. '
|
|
628
306
|
'To find apps for all chips use the `--target` option with the `all` argument.',
|
|
629
|
-
parents=[common_args],
|
|
630
307
|
formatter_class=IdfBuildAppsCliFormatter,
|
|
308
|
+
parents=[common_args],
|
|
631
309
|
)
|
|
632
|
-
|
|
633
|
-
find_parser.add_argument(
|
|
634
|
-
'--output-format',
|
|
635
|
-
choices=['raw', 'json'],
|
|
636
|
-
default='raw',
|
|
637
|
-
help='Output format. In "raw" format, each line is a valid json that represents the app. '
|
|
638
|
-
'In "json" format, the whole file is a JSON file of a list of apps.',
|
|
639
|
-
)
|
|
640
|
-
find_parser.add_argument(
|
|
641
|
-
'--include-all-apps',
|
|
642
|
-
action='store_true',
|
|
643
|
-
help='Include skipped and disabled apps. By default only apps that should be built.',
|
|
644
|
-
)
|
|
310
|
+
add_args_to_parser(FindArguments, find_parser)
|
|
645
311
|
|
|
312
|
+
#########
|
|
313
|
+
# Build #
|
|
314
|
+
#########
|
|
646
315
|
build_parser = actions.add_parser(
|
|
647
316
|
'build',
|
|
648
317
|
help='Build the found applications. Run `idf-build-apps build --help` for more information on a command.',
|
|
649
318
|
description='Build the application in the given path or paths for specified chips. '
|
|
650
319
|
'`--path` and `--target` options must be provided.',
|
|
651
|
-
parents=[common_args],
|
|
652
320
|
formatter_class=IdfBuildAppsCliFormatter,
|
|
321
|
+
parents=[common_args],
|
|
653
322
|
)
|
|
654
|
-
build_parser
|
|
655
|
-
'--build-verbose',
|
|
656
|
-
action='store_true',
|
|
657
|
-
help='Enable verbose output of the build system',
|
|
658
|
-
)
|
|
659
|
-
build_parser.add_argument(
|
|
660
|
-
'--parallel-count',
|
|
661
|
-
default=1,
|
|
662
|
-
type=int,
|
|
663
|
-
help="Number of parallel build jobs. Note that this script doesn't start all jobs simultaneously. "
|
|
664
|
-
'It needs to be executed multiple times with same value of --parallel-count and '
|
|
665
|
-
'different values of --parallel-index',
|
|
666
|
-
)
|
|
667
|
-
build_parser.add_argument(
|
|
668
|
-
'--parallel-index',
|
|
669
|
-
default=1,
|
|
670
|
-
type=int,
|
|
671
|
-
help='Index (1-based) of the job, out of the number specified by --parallel-count',
|
|
672
|
-
)
|
|
673
|
-
build_parser.add_argument(
|
|
674
|
-
'--dry-run',
|
|
675
|
-
action='store_true',
|
|
676
|
-
help="Don't actually build, only print the build commands",
|
|
677
|
-
)
|
|
678
|
-
build_parser.add_argument(
|
|
679
|
-
'--keep-going',
|
|
680
|
-
action='store_true',
|
|
681
|
-
help="Don't exit immediately when a build fails",
|
|
682
|
-
)
|
|
683
|
-
build_parser.add_argument(
|
|
684
|
-
'--no-preserve',
|
|
685
|
-
action='store_true',
|
|
686
|
-
help="Don't preserve the build directory after a successful build",
|
|
687
|
-
)
|
|
688
|
-
build_parser.add_argument(
|
|
689
|
-
'--collect-size-info',
|
|
690
|
-
help='write size info json file while building into the specified file. each line is a json object. '
|
|
691
|
-
'Can expand placeholder @p',
|
|
692
|
-
)
|
|
693
|
-
build_parser.add_argument(
|
|
694
|
-
'--collect-app-info',
|
|
695
|
-
help='write app info json file while building into the specified file. each line is a json object. '
|
|
696
|
-
'Can expand placeholder @p',
|
|
697
|
-
)
|
|
698
|
-
build_parser.add_argument(
|
|
699
|
-
'--ignore-warning-str',
|
|
700
|
-
nargs='+',
|
|
701
|
-
help='Ignore the warning string that match the specified regex in the build output',
|
|
702
|
-
)
|
|
703
|
-
build_parser.add_argument(
|
|
704
|
-
'--ignore-warning-file',
|
|
705
|
-
type=argparse.FileType('r'),
|
|
706
|
-
help='Ignore the warning strings in the specified file. Each line should be a regex string',
|
|
707
|
-
)
|
|
708
|
-
build_parser.add_argument(
|
|
709
|
-
'--copy-sdkconfig',
|
|
710
|
-
action='store_true',
|
|
711
|
-
help='Copy the sdkconfig file to the build directory',
|
|
712
|
-
)
|
|
713
|
-
build_parser.add_argument(
|
|
714
|
-
'--junitxml',
|
|
715
|
-
help='Path to the junitxml file. If specified, the junitxml file will be generated. Can expand placeholder @p',
|
|
716
|
-
)
|
|
323
|
+
add_args_to_parser(BuildArguments, build_parser)
|
|
717
324
|
|
|
325
|
+
###############
|
|
326
|
+
# Completions #
|
|
327
|
+
###############
|
|
718
328
|
completions_parser = actions.add_parser(
|
|
719
329
|
'completions',
|
|
720
330
|
help='Add the autocompletion activation script to the shell rc file. '
|
|
@@ -735,8 +345,19 @@ def get_parser() -> argparse.ArgumentParser:
|
|
|
735
345
|
'-s',
|
|
736
346
|
'--shell',
|
|
737
347
|
choices=['bash', 'zsh', 'fish'],
|
|
738
|
-
help='Specify the shell type for the
|
|
348
|
+
help='Specify the shell type for the autocomplete activation script.',
|
|
349
|
+
)
|
|
350
|
+
|
|
351
|
+
############################
|
|
352
|
+
# Dump Manifest SHA Values #
|
|
353
|
+
############################
|
|
354
|
+
dump_manifest_parser = actions.add_parser(
|
|
355
|
+
'dump-manifest-sha',
|
|
356
|
+
help='Dump the manifest files SHA values. '
|
|
357
|
+
'This could be useful in CI to check if the manifest files are changed.',
|
|
358
|
+
parents=[common_args],
|
|
739
359
|
)
|
|
360
|
+
add_args_to_parser(DumpManifestShaArguments, dump_manifest_parser)
|
|
740
361
|
|
|
741
362
|
return parser
|
|
742
363
|
|
|
@@ -752,56 +373,6 @@ def handle_completions(args: argparse.Namespace) -> None:
|
|
|
752
373
|
print(completion_instructions)
|
|
753
374
|
|
|
754
375
|
|
|
755
|
-
def validate_args(parser: argparse.ArgumentParser, args: argparse.Namespace) -> None:
|
|
756
|
-
# validate cli subcommands
|
|
757
|
-
if args.action not in ['find', 'build', 'completions']:
|
|
758
|
-
parser.print_help()
|
|
759
|
-
raise InvalidCommand('subcommand is required. {find, build, completions}')
|
|
760
|
-
|
|
761
|
-
if not args.paths:
|
|
762
|
-
raise InvalidCommand(
|
|
763
|
-
'Must specify at least one path to search for the apps ' 'with CLI option "-p <path>" or "--path <path>"'
|
|
764
|
-
)
|
|
765
|
-
|
|
766
|
-
if not args.target:
|
|
767
|
-
raise InvalidCommand(
|
|
768
|
-
'Must specify current build target with CLI option "-t <target>" or "--target <target>". '
|
|
769
|
-
'(choices: [{}]'.format(','.join([*ALL_TARGETS, 'all']))
|
|
770
|
-
)
|
|
771
|
-
|
|
772
|
-
default_build_targets = []
|
|
773
|
-
if args.default_build_targets:
|
|
774
|
-
for target in args.default_build_targets:
|
|
775
|
-
if target not in ALL_TARGETS:
|
|
776
|
-
LOGGER.warning(
|
|
777
|
-
f'Ignoring... Unrecognizable target {target} specified with "--default-build-targets". '
|
|
778
|
-
f'Current ESP-IDF available targets: {ALL_TARGETS}'
|
|
779
|
-
)
|
|
780
|
-
elif target not in default_build_targets:
|
|
781
|
-
default_build_targets.append(target)
|
|
782
|
-
args.default_build_targets = default_build_targets
|
|
783
|
-
elif args.enable_preview_targets:
|
|
784
|
-
args.default_build_targets = deepcopy(ALL_TARGETS)
|
|
785
|
-
|
|
786
|
-
if args.ignore_app_dependencies_components is not None:
|
|
787
|
-
if args.modified_components is None:
|
|
788
|
-
raise InvalidCommand('Must specify "--ignore-app-dependencies-components" with "--modified-components", ')
|
|
789
|
-
|
|
790
|
-
if args.ignore_app_dependencies_filepatterns is not None:
|
|
791
|
-
if args.modified_files is None:
|
|
792
|
-
raise InvalidCommand('Must specify "--ignore-app-dependencies-filepatterns" with "--modified-files", ')
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
def apply_config_args(args: argparse.Namespace) -> None:
|
|
796
|
-
# support toml config file
|
|
797
|
-
config_dict = get_valid_config(custom_path=args.config_file)
|
|
798
|
-
if config_dict:
|
|
799
|
-
for k, v in config_dict.items():
|
|
800
|
-
setattr(args, k, v)
|
|
801
|
-
|
|
802
|
-
setup_logging(args.verbose, args.log_file, not args.no_color)
|
|
803
|
-
|
|
804
|
-
|
|
805
376
|
def main():
|
|
806
377
|
parser = get_parser()
|
|
807
378
|
argcomplete.autocomplete(parser)
|
|
@@ -811,86 +382,47 @@ def main():
|
|
|
811
382
|
handle_completions(args)
|
|
812
383
|
sys.exit(0)
|
|
813
384
|
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
SESSION_ARGS.set(args)
|
|
818
|
-
|
|
819
|
-
if args.action == 'build':
|
|
820
|
-
args.output = None # build action doesn't support output option
|
|
821
|
-
|
|
822
|
-
kwargs = {
|
|
823
|
-
'build_system': args.build_system,
|
|
824
|
-
'recursive': args.recursive,
|
|
825
|
-
'exclude_list': args.exclude or [],
|
|
826
|
-
'work_dir': args.work_dir,
|
|
827
|
-
'build_dir': args.build_dir or 'build',
|
|
828
|
-
'config_rules_str': args.config,
|
|
829
|
-
'build_log_filename': args.build_log,
|
|
830
|
-
'size_json_filename': args.size_file,
|
|
831
|
-
'check_warnings': args.check_warnings,
|
|
832
|
-
'manifest_rootpath': args.manifest_rootpath,
|
|
833
|
-
'manifest_files': args.manifest_file,
|
|
834
|
-
'check_manifest_rules': args.check_manifest_rules,
|
|
835
|
-
'default_build_targets': args.default_build_targets,
|
|
836
|
-
'modified_components': args.modified_components,
|
|
837
|
-
'modified_files': args.modified_files,
|
|
838
|
-
'ignore_app_dependencies_components': args.ignore_app_dependencies_components,
|
|
839
|
-
'ignore_app_dependencies_filepatterns': args.ignore_app_dependencies_filepatterns,
|
|
840
|
-
'sdkconfig_defaults': args.sdkconfig_defaults,
|
|
841
|
-
}
|
|
842
|
-
# only useful in find
|
|
843
|
-
if args.action == 'find' and args.include_all_apps:
|
|
844
|
-
kwargs['include_skipped_apps'] = True
|
|
845
|
-
kwargs['include_disabled_apps'] = True
|
|
385
|
+
kwargs = vars(args)
|
|
386
|
+
action = kwargs.pop('action')
|
|
387
|
+
config_file = kwargs.pop('config_file')
|
|
846
388
|
|
|
847
|
-
|
|
848
|
-
apps = find_apps(args.paths, args.target, **kwargs)
|
|
389
|
+
apply_config_file(config_file)
|
|
849
390
|
|
|
850
|
-
if
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
391
|
+
if action == 'dump-manifest-sha':
|
|
392
|
+
arguments = DumpManifestShaArguments(**drop_none_kwargs(kwargs))
|
|
393
|
+
Manifest.from_files(arguments.manifest_files).dump_sha_values(arguments.output)
|
|
394
|
+
sys.exit(0)
|
|
395
|
+
elif action == 'find':
|
|
396
|
+
arguments = FindArguments(**drop_none_kwargs(kwargs))
|
|
397
|
+
else:
|
|
398
|
+
arguments = BuildArguments(**drop_none_kwargs(kwargs))
|
|
856
399
|
|
|
857
|
-
|
|
858
|
-
|
|
400
|
+
# real call starts here
|
|
401
|
+
# build also needs to find first
|
|
402
|
+
apps = find_apps(args.paths, args.target, find_arguments=arguments)
|
|
403
|
+
if isinstance(arguments, FindArguments): # find only
|
|
404
|
+
if arguments.output:
|
|
405
|
+
os.makedirs(os.path.dirname(os.path.realpath(arguments.output)), exist_ok=True)
|
|
406
|
+
with open(arguments.output, 'w') as fw:
|
|
407
|
+
if arguments.output_format == 'raw':
|
|
859
408
|
for app in apps:
|
|
860
409
|
fw.write(app.to_json() + '\n')
|
|
861
|
-
elif
|
|
410
|
+
elif arguments.output_format == 'json':
|
|
862
411
|
fw.write(json.dumps([app.model_dump() for app in apps], indent=2))
|
|
863
412
|
else:
|
|
864
|
-
raise
|
|
413
|
+
raise InvalidCommand(f'Output format {arguments.output_format} is not supported.')
|
|
865
414
|
else:
|
|
866
415
|
for app in apps:
|
|
867
416
|
print(app)
|
|
868
417
|
|
|
869
418
|
sys.exit(0)
|
|
870
419
|
|
|
871
|
-
|
|
420
|
+
# build
|
|
421
|
+
if arguments.no_preserve:
|
|
872
422
|
for app in apps:
|
|
873
423
|
app.preserve = False
|
|
874
424
|
|
|
875
|
-
|
|
876
|
-
apps,
|
|
877
|
-
build_verbose=args.build_verbose,
|
|
878
|
-
parallel_count=args.parallel_count,
|
|
879
|
-
parallel_index=args.parallel_index,
|
|
880
|
-
dry_run=args.dry_run,
|
|
881
|
-
keep_going=args.keep_going,
|
|
882
|
-
collect_size_info=args.collect_size_info,
|
|
883
|
-
collect_app_info=args.collect_app_info,
|
|
884
|
-
ignore_warning_strs=args.ignore_warning_str,
|
|
885
|
-
ignore_warning_file=args.ignore_warning_file,
|
|
886
|
-
copy_sdkconfig=args.copy_sdkconfig,
|
|
887
|
-
manifest_rootpath=args.manifest_rootpath,
|
|
888
|
-
modified_components=args.modified_components,
|
|
889
|
-
modified_files=args.modified_files,
|
|
890
|
-
ignore_app_dependencies_components=args.ignore_app_dependencies_components,
|
|
891
|
-
ignore_app_dependencies_filepatterns=args.ignore_app_dependencies_filepatterns,
|
|
892
|
-
junitxml=args.junitxml,
|
|
893
|
-
)
|
|
425
|
+
ret_code = build_apps(apps, build_arguments=arguments)
|
|
894
426
|
|
|
895
427
|
built_apps = [app for app in apps if app.build_status == BuildStatus.SUCCESS]
|
|
896
428
|
if built_apps:
|
|
@@ -910,7 +442,8 @@ def main():
|
|
|
910
442
|
for app in failed_apps:
|
|
911
443
|
print(f' {app}')
|
|
912
444
|
|
|
913
|
-
|
|
445
|
+
if ret_code != 0:
|
|
446
|
+
sys.exit(ret_code)
|
|
914
447
|
|
|
915
448
|
|
|
916
449
|
def json_to_app(json_str: str, extra_classes: t.Optional[t.List[t.Type[App]]] = None) -> App:
|
|
@@ -922,13 +455,17 @@ def json_to_app(json_str: str, extra_classes: t.Optional[t.List[t.Type[App]]] =
|
|
|
922
455
|
You can pass extra_cls to support custom App class. A custom App class must be a subclass of App, and have a
|
|
923
456
|
different value of `build_system`. For example, a custom CMake app
|
|
924
457
|
|
|
925
|
-
|
|
926
|
-
|
|
458
|
+
.. code:: python
|
|
459
|
+
|
|
460
|
+
class CustomApp(CMakeApp):
|
|
461
|
+
build_system: Literal['custom_cmake'] = 'custom_cmake'
|
|
462
|
+
|
|
463
|
+
Then you can pass the :class:`CustomApp` class to the :attr:`extra_cls` argument
|
|
927
464
|
|
|
928
|
-
|
|
465
|
+
.. code:: python
|
|
929
466
|
|
|
930
|
-
|
|
931
|
-
|
|
467
|
+
json_str = CustomApp('.', 'esp32').to_json()
|
|
468
|
+
json_to_app(json_str, extra_classes=[CustomApp])
|
|
932
469
|
|
|
933
470
|
:param json_str: json string
|
|
934
471
|
:param extra_classes: extra App class
|