blob: 363e4c7cc7ce8ab1c7158900cfc22423061c7e0c [file] [log] [blame]
Torsten Rasmussenbd7569f2019-03-19 10:38:18 +01001#!/usr/bin/env python3
2#
3# Copyright (c) 2019, Nordic Semiconductor ASA
4#
5# SPDX-License-Identifier: Apache-2.0
6
7'''Tool for parsing a list of projects to determine if they are Zephyr
8projects. If no projects are given then the output from `west list` will be
9used as project list.
10
11Include file is generated for Kconfig using --kconfig-out.
12A <name>:<path> text file is generated for use with CMake using --cmake-out.
Anas Nashif286a9ed2019-12-11 10:13:23 -050013
Anas Nashif54713982020-12-07 14:52:10 -050014Using --twister-out <filename> an argument file for twister script will
Anas Nashif286a9ed2019-12-11 10:13:23 -050015be generated which would point to test and sample roots available in modules
Anas Nashif54713982020-12-07 14:52:10 -050016that can be included during a twister run. This allows testing code
Anas Nashif286a9ed2019-12-11 10:13:23 -050017maintained in modules in addition to what is available in the main Zephyr tree.
Torsten Rasmussenbd7569f2019-03-19 10:38:18 +010018'''
19
20import argparse
21import os
Torsten Rasmussen3d880832021-01-19 12:01:38 +010022import re
Torsten Rasmussenfffaf052021-10-12 23:08:36 +020023import subprocess
Torsten Rasmussenbd7569f2019-03-19 10:38:18 +010024import sys
25import yaml
26import pykwalify.core
Torsten Rasmussenb3da9ef2019-12-13 09:42:13 +010027from pathlib import Path, PurePath
Torsten Rasmussen3917ee52020-05-18 22:34:49 +020028from collections import namedtuple
Torsten Rasmussenbd7569f2019-03-19 10:38:18 +010029
30METADATA_SCHEMA = '''
31## A pykwalify schema for basic validation of the structure of a
32## metadata YAML file.
33##
34# The zephyr/module.yml file is a simple list of key value pairs to be used by
35# the build system.
36type: map
37mapping:
Torsten Rasmussenf24f8832021-01-07 15:27:53 +010038 name:
39 required: false
40 type: str
Torsten Rasmussenbd7569f2019-03-19 10:38:18 +010041 build:
Anas Nashif286a9ed2019-12-11 10:13:23 -050042 required: false
Torsten Rasmussenbd7569f2019-03-19 10:38:18 +010043 type: map
44 mapping:
45 cmake:
46 required: false
47 type: str
48 kconfig:
49 required: false
50 type: str
Torsten Rasmussen3673e282020-12-17 11:27:42 +010051 cmake-ext:
52 required: false
53 type: bool
54 default: false
55 kconfig-ext:
56 required: false
57 type: bool
58 default: false
Torsten Rasmussen3917ee52020-05-18 22:34:49 +020059 depends:
60 required: false
61 type: seq
62 sequence:
63 - type: str
Torsten Rasmussen25d57ba2020-07-07 17:29:56 +020064 settings:
65 required: false
66 type: map
67 mapping:
68 board_root:
69 required: false
70 type: str
71 dts_root:
72 required: false
73 type: str
74 soc_root:
75 required: false
76 type: str
77 arch_root:
78 required: false
79 type: str
Torsten Rasmussen3673e282020-12-17 11:27:42 +010080 module_ext_root:
81 required: false
82 type: str
Anas Nashif286a9ed2019-12-11 10:13:23 -050083 tests:
84 required: false
85 type: seq
86 sequence:
87 - type: str
88 samples:
89 required: false
90 type: seq
91 sequence:
92 - type: str
93 boards:
94 required: false
95 type: seq
96 sequence:
97 - type: str
Torsten Rasmussenbd7569f2019-03-19 10:38:18 +010098'''
99
100schema = yaml.safe_load(METADATA_SCHEMA)
101
102
103def validate_setting(setting, module_path, filename=None):
104 if setting is not None:
105 if filename is not None:
106 checkfile = os.path.join(module_path, setting, filename)
107 else:
108 checkfile = os.path.join(module_path, setting)
109 if not os.path.isfile(checkfile):
110 return False
111 return True
112
113
Anas Nashif286a9ed2019-12-11 10:13:23 -0500114def process_module(module):
Torsten Rasmussenb3da9ef2019-12-13 09:42:13 +0100115 module_path = PurePath(module)
Anas Nashif286a9ed2019-12-11 10:13:23 -0500116
Sebastian Bøebb95dce2019-12-19 15:49:22 +0100117 # The input is a module if zephyr/module.yml is a valid yaml file
118 # or if both zephyr/CMakeLists.txt and zephyr/Kconfig are present.
119
Alexander Mihajlovic099c1262022-03-31 08:04:45 +0200120 for module_yml in [module_path.joinpath('zephyr/module.yml'),
121 module_path.joinpath('zephyr/module.yaml')]:
122 if Path(module_yml).is_file():
123 with Path(module_yml).open('r') as f:
124 meta = yaml.safe_load(f.read())
Torsten Rasmussenbd7569f2019-03-19 10:38:18 +0100125
Alexander Mihajlovic099c1262022-03-31 08:04:45 +0200126 try:
127 pykwalify.core.Core(source_data=meta, schema_data=schema)\
128 .validate()
129 except pykwalify.errors.SchemaError as e:
130 sys.exit('ERROR: Malformed "build" section in file: {}\n{}'
131 .format(module_yml.as_posix(), e))
Torsten Rasmussenbd7569f2019-03-19 10:38:18 +0100132
Alexander Mihajlovic099c1262022-03-31 08:04:45 +0200133 meta['name'] = meta.get('name', module_path.name)
134 meta['name-sanitized'] = re.sub('[^a-zA-Z0-9]', '_', meta['name'])
135 return meta
Torsten Rasmussenbd7569f2019-03-19 10:38:18 +0100136
Sebastian Bøebb95dce2019-12-19 15:49:22 +0100137 if Path(module_path.joinpath('zephyr/CMakeLists.txt')).is_file() and \
138 Path(module_path.joinpath('zephyr/Kconfig')).is_file():
Torsten Rasmussenf24f8832021-01-07 15:27:53 +0100139 return {'name': module_path.name,
Torsten Rasmussen3d880832021-01-19 12:01:38 +0100140 'name-sanitized': re.sub('[^a-zA-Z0-9]', '_', module_path.name),
Torsten Rasmussenf24f8832021-01-07 15:27:53 +0100141 'build': {'cmake': 'zephyr', 'kconfig': 'zephyr/Kconfig'}}
Sebastian Bøebb95dce2019-12-19 15:49:22 +0100142
Anas Nashif286a9ed2019-12-11 10:13:23 -0500143 return None
Torsten Rasmussenbd7569f2019-03-19 10:38:18 +0100144
Torsten Rasmussenbd7569f2019-03-19 10:38:18 +0100145
Anas Nashif286a9ed2019-12-11 10:13:23 -0500146def process_cmake(module, meta):
147 section = meta.get('build', dict())
148 module_path = PurePath(module)
149 module_yml = module_path.joinpath('zephyr/module.yml')
Torsten Rasmussen3673e282020-12-17 11:27:42 +0100150
151 cmake_extern = section.get('cmake-ext', False)
152 if cmake_extern:
153 return('\"{}\":\"{}\":\"{}\"\n'
Andrzej Głąbek02819482021-01-19 07:39:47 +0100154 .format(meta['name'],
Torsten Rasmussen3673e282020-12-17 11:27:42 +0100155 module_path.as_posix(),
Torsten Rasmussen3d880832021-01-19 12:01:38 +0100156 "${ZEPHYR_" + meta['name-sanitized'].upper() + "_CMAKE_DIR}"))
Torsten Rasmussen3673e282020-12-17 11:27:42 +0100157
Anas Nashif286a9ed2019-12-11 10:13:23 -0500158 cmake_setting = section.get('cmake', None)
159 if not validate_setting(cmake_setting, module, 'CMakeLists.txt'):
160 sys.exit('ERROR: "cmake" key in {} has folder value "{}" which '
Torsten Rasmussen25c3f8e2020-08-25 14:02:04 +0200161 'does not contain a CMakeLists.txt file.'
162 .format(module_yml.as_posix(), cmake_setting))
Anas Nashif286a9ed2019-12-11 10:13:23 -0500163
164 cmake_path = os.path.join(module, cmake_setting or 'zephyr')
165 cmake_file = os.path.join(cmake_path, 'CMakeLists.txt')
166 if os.path.isfile(cmake_file):
Torsten Rasmussenab7ec172020-08-25 13:32:33 +0200167 return('\"{}\":\"{}\":\"{}\"\n'
Torsten Rasmussenf24f8832021-01-07 15:27:53 +0100168 .format(meta['name'],
Torsten Rasmussenab7ec172020-08-25 13:32:33 +0200169 module_path.as_posix(),
Torsten Rasmussen25c3f8e2020-08-25 14:02:04 +0200170 Path(cmake_path).resolve().as_posix()))
Anas Nashif286a9ed2019-12-11 10:13:23 -0500171 else:
Torsten Rasmussenab7ec172020-08-25 13:32:33 +0200172 return('\"{}\":\"{}\":\"\"\n'
Torsten Rasmussenf24f8832021-01-07 15:27:53 +0100173 .format(meta['name'],
Torsten Rasmussenab7ec172020-08-25 13:32:33 +0200174 module_path.as_posix()))
Torsten Rasmussen25c3f8e2020-08-25 14:02:04 +0200175
Torsten Rasmussen3673e282020-12-17 11:27:42 +0100176
Torsten Rasmussen25d57ba2020-07-07 17:29:56 +0200177def process_settings(module, meta):
178 section = meta.get('build', dict())
179 build_settings = section.get('settings', None)
180 out_text = ""
181
182 if build_settings is not None:
Torsten Rasmussen3673e282020-12-17 11:27:42 +0100183 for root in ['board', 'dts', 'soc', 'arch', 'module_ext']:
Torsten Rasmussen25d57ba2020-07-07 17:29:56 +0200184 setting = build_settings.get(root+'_root', None)
185 if setting is not None:
186 root_path = PurePath(module) / setting
Torsten Rasmussen3673e282020-12-17 11:27:42 +0100187 out_text += f'"{root.upper()}_ROOT":'
188 out_text += f'"{root_path.as_posix()}"\n'
Torsten Rasmussen25d57ba2020-07-07 17:29:56 +0200189
190 return out_text
191
Torsten Rasmussen25c3f8e2020-08-25 14:02:04 +0200192
Torsten Rasmussen3d880832021-01-19 12:01:38 +0100193def kconfig_snippet(meta, path, kconfig_file=None):
194 name = meta['name']
195 name_sanitized = meta['name-sanitized']
196
Trond Einar Snekvik6a8326f2021-12-02 15:44:36 +0100197 snippet = (f'menu "{name} ({path.as_posix()})"',
Torsten Rasmussen3673e282020-12-17 11:27:42 +0100198 f'osource "{kconfig_file.resolve().as_posix()}"' if kconfig_file
Torsten Rasmussen3d880832021-01-19 12:01:38 +0100199 else f'osource "$(ZEPHYR_{name_sanitized.upper()}_KCONFIG)"',
200 f'config ZEPHYR_{name_sanitized.upper()}_MODULE',
Torsten Rasmussen3673e282020-12-17 11:27:42 +0100201 ' bool',
202 ' default y',
203 'endmenu\n')
204 return '\n'.join(snippet)
205
206
Anas Nashif286a9ed2019-12-11 10:13:23 -0500207def process_kconfig(module, meta):
208 section = meta.get('build', dict())
209 module_path = PurePath(module)
210 module_yml = module_path.joinpath('zephyr/module.yml')
Torsten Rasmussen3673e282020-12-17 11:27:42 +0100211 kconfig_extern = section.get('kconfig-ext', False)
212 if kconfig_extern:
Torsten Rasmussen3d880832021-01-19 12:01:38 +0100213 return kconfig_snippet(meta, module_path)
Anas Nashif286a9ed2019-12-11 10:13:23 -0500214
215 kconfig_setting = section.get('kconfig', None)
216 if not validate_setting(kconfig_setting, module):
217 sys.exit('ERROR: "kconfig" key in {} has value "{}" which does '
Torsten Rasmussen25c3f8e2020-08-25 14:02:04 +0200218 'not point to a valid Kconfig file.'
219 .format(module_yml, kconfig_setting))
Anas Nashif286a9ed2019-12-11 10:13:23 -0500220
221 kconfig_file = os.path.join(module, kconfig_setting or 'zephyr/Kconfig')
222 if os.path.isfile(kconfig_file):
Torsten Rasmussen3d880832021-01-19 12:01:38 +0100223 return kconfig_snippet(meta, module_path, Path(kconfig_file))
Anas Nashif286a9ed2019-12-11 10:13:23 -0500224 else:
225 return ""
226
Torsten Rasmussen3673e282020-12-17 11:27:42 +0100227
Anas Nashif54713982020-12-07 14:52:10 -0500228def process_twister(module, meta):
Anas Nashif286a9ed2019-12-11 10:13:23 -0500229
230 out = ""
231 tests = meta.get('tests', [])
232 samples = meta.get('samples', [])
233 boards = meta.get('boards', [])
234
235 for pth in tests + samples:
236 if pth:
237 dir = os.path.join(module, pth)
Torsten Rasmussen25c3f8e2020-08-25 14:02:04 +0200238 out += '-T\n{}\n'.format(PurePath(os.path.abspath(dir))
239 .as_posix())
Anas Nashif286a9ed2019-12-11 10:13:23 -0500240
241 for pth in boards:
242 if pth:
243 dir = os.path.join(module, pth)
Torsten Rasmussen25c3f8e2020-08-25 14:02:04 +0200244 out += '--board-root\n{}\n'.format(PurePath(os.path.abspath(dir))
245 .as_posix())
Anas Nashif286a9ed2019-12-11 10:13:23 -0500246
247 return out
Torsten Rasmussenbd7569f2019-03-19 10:38:18 +0100248
249
Torsten Rasmussen1a519932021-11-04 18:35:50 +0100250def process_meta(zephyr_base, west_projects, modules, extra_modules=None,
251 propagate_state=False):
Torsten Rasmussenfffaf052021-10-12 23:08:36 +0200252 # Process zephyr_base, projects, and modules and create a dictionary
253 # with meta information for each input.
254 #
255 # The dictionary will contain meta info in the following lists:
256 # - zephyr: path and revision
257 # - modules: name, path, and revision
258 # - west-projects: path and revision
259 #
260 # returns the dictionary with said lists
261
Torsten Rasmussen64ec6ee2021-11-04 14:28:21 +0100262 meta = {'zephyr': None, 'modules': None, 'workspace': None}
263
264 workspace_dirty = False
265 workspace_extra = extra_modules is not None
266 workspace_off = False
Torsten Rasmussenfffaf052021-10-12 23:08:36 +0200267
268 def git_revision(path):
269 rc = subprocess.Popen(['git', 'rev-parse', '--is-inside-work-tree'],
270 stdout=subprocess.PIPE,
271 stderr=subprocess.PIPE,
272 cwd=path).wait()
273 if rc == 0:
274 # A git repo.
275 popen = subprocess.Popen(['git', 'rev-parse', 'HEAD'],
276 stdout=subprocess.PIPE,
277 stderr=subprocess.PIPE,
278 cwd=path)
279 stdout, stderr = popen.communicate()
280 stdout = stdout.decode('utf-8')
281
282 if not (popen.returncode or stderr):
283 revision = stdout.rstrip()
284
285 rc = subprocess.Popen(['git', 'diff-index', '--quiet', 'HEAD',
286 '--'],
287 stdout=None,
288 stderr=None,
289 cwd=path).wait()
290 if rc:
Torsten Rasmussen64ec6ee2021-11-04 14:28:21 +0100291 return revision + '-dirty', True
292 return revision, False
293 return None, False
Torsten Rasmussenfffaf052021-10-12 23:08:36 +0200294
Torsten Rasmussen64ec6ee2021-11-04 14:28:21 +0100295 zephyr_revision, zephyr_dirty = git_revision(zephyr_base)
296 zephyr_project = {'path': zephyr_base,
297 'revision': zephyr_revision}
298 meta['zephyr'] = zephyr_project
299 meta['workspace'] = {}
300 workspace_dirty |= zephyr_dirty
Torsten Rasmussenfffaf052021-10-12 23:08:36 +0200301
302 if west_projects is not None:
Torsten Rasmussen64ec6ee2021-11-04 14:28:21 +0100303 from west.manifest import MANIFEST_REV_BRANCH
304 projects = west_projects['projects']
Torsten Rasmussenfffaf052021-10-12 23:08:36 +0200305 meta_projects = []
Torsten Rasmussen64ec6ee2021-11-04 14:28:21 +0100306
307 # Special treatment of manifest project.
308 manifest_path = PurePath(projects[0].posixpath).as_posix()
309 manifest_revision, manifest_dirty = git_revision(manifest_path)
310 workspace_dirty |= manifest_dirty
311 manifest_project = {'path': manifest_path,
312 'revision': manifest_revision}
313 meta_projects.append(manifest_project)
314
315 for project in projects[1:]:
316 project_path = PurePath(project.posixpath).as_posix()
317 revision, dirty = git_revision(project_path)
318 workspace_dirty |= dirty
319 if project.sha(MANIFEST_REV_BRANCH) != revision:
320 revision += '-off'
321 workspace_off = True
Torsten Rasmussenfffaf052021-10-12 23:08:36 +0200322 meta_project = {'path': project_path,
Torsten Rasmussen64ec6ee2021-11-04 14:28:21 +0100323 'revision': revision}
Torsten Rasmussenfffaf052021-10-12 23:08:36 +0200324 meta_projects.append(meta_project)
Torsten Rasmussen64ec6ee2021-11-04 14:28:21 +0100325
326 meta.update({'west': {'manifest': west_projects['manifest'],
327 'projects': meta_projects}})
328 meta['workspace'].update({'off': workspace_off})
Torsten Rasmussenfffaf052021-10-12 23:08:36 +0200329
330 meta_projects = []
331 for module in modules:
332 module_path = PurePath(module.project).as_posix()
Torsten Rasmussen64ec6ee2021-11-04 14:28:21 +0100333 revision, dirty = git_revision(module_path)
334 workspace_dirty |= dirty
Torsten Rasmussenfffaf052021-10-12 23:08:36 +0200335 meta_project = {'name': module.meta['name'],
336 'path': module_path,
Torsten Rasmussen64ec6ee2021-11-04 14:28:21 +0100337 'revision': revision}
Torsten Rasmussenfffaf052021-10-12 23:08:36 +0200338 meta_projects.append(meta_project)
339 meta['modules'] = meta_projects
340
Torsten Rasmussen64ec6ee2021-11-04 14:28:21 +0100341 meta['workspace'].update({'dirty': workspace_dirty,
342 'extra': workspace_extra})
343
Torsten Rasmussen1a519932021-11-04 18:35:50 +0100344 if propagate_state:
345 if workspace_dirty and not zephyr_dirty:
346 zephyr_revision += '-dirty'
347 if workspace_extra:
348 zephyr_revision += '-extra'
349 if workspace_off:
350 zephyr_revision += '-off'
351 zephyr_project.update({'revision': zephyr_revision})
352
353 if west_projects is not None:
354 if workspace_dirty and not manifest_dirty:
355 manifest_revision += '-dirty'
356 if workspace_extra:
357 manifest_revision += '-extra'
358 if workspace_off:
359 manifest_revision += '-off'
360 manifest_project.update({'revision': manifest_revision})
361
Torsten Rasmussenfffaf052021-10-12 23:08:36 +0200362 return meta
363
364
365def west_projects():
366 manifest_file = None
367 projects = []
368 # West is imported here, as it is optional
369 # (and thus maybe not installed)
370 # if user is providing a specific modules list.
371 from west.manifest import Manifest
372 from west.util import WestNotFound
373 from west.version import __version__ as WestVersion
374 from packaging import version
375 try:
376 manifest = Manifest.from_file()
377 if version.parse(WestVersion) >= version.parse('0.9.0'):
Torsten Rasmussen64ec6ee2021-11-04 14:28:21 +0100378 projects = [p for p in manifest.get_projects([])
Torsten Rasmussenfffaf052021-10-12 23:08:36 +0200379 if manifest.is_active(p)]
380 else:
Torsten Rasmussen64ec6ee2021-11-04 14:28:21 +0100381 projects = manifest.get_projects([])
Torsten Rasmussenfffaf052021-10-12 23:08:36 +0200382 manifest_file = manifest.path
383 return {'manifest': manifest_file, 'projects': projects}
384 except WestNotFound:
385 # Only accept WestNotFound, meaning we are not in a west
386 # workspace. Such setup is allowed, as west may be installed
387 # but the project is not required to use west.
388 pass
389 return None
390
391
Marcin Niestroj248d25d2021-05-08 16:56:34 +0200392def parse_modules(zephyr_base, modules=None, extra_modules=None):
393 if modules is None:
Torsten Rasmussenfffaf052021-10-12 23:08:36 +0200394 modules = []
Torsten Rasmussenbd7569f2019-03-19 10:38:18 +0100395
Marcin Niestroj248d25d2021-05-08 16:56:34 +0200396 if extra_modules is None:
397 extra_modules = []
Anas Nashif286a9ed2019-12-11 10:13:23 -0500398
Torsten Rasmussen3917ee52020-05-18 22:34:49 +0200399 Module = namedtuple('Module', ['project', 'meta', 'depends'])
Damian Krolika5051482022-03-01 18:36:16 +0100400
401 all_modules_by_name = {}
Torsten Rasmussen3917ee52020-05-18 22:34:49 +0200402 # dep_modules is a list of all modules that has an unresolved dependency
403 dep_modules = []
404 # start_modules is a list modules with no depends left (no incoming edge)
405 start_modules = []
406 # sorted_modules is a topological sorted list of the modules
407 sorted_modules = []
408
Torsten Rasmussenfffaf052021-10-12 23:08:36 +0200409 for project in modules + extra_modules:
Anas Nashif286a9ed2019-12-11 10:13:23 -0500410 # Avoid including Zephyr base project as module.
Marcin Niestroj248d25d2021-05-08 16:56:34 +0200411 if project == zephyr_base:
Anas Nashif286a9ed2019-12-11 10:13:23 -0500412 continue
413
414 meta = process_module(project)
415 if meta:
Damian Krolika5051482022-03-01 18:36:16 +0100416 depends = meta.get('build', {}).get('depends', [])
417 all_modules_by_name[meta['name']] = Module(project, meta, depends)
418
Martí Bolívar34346c42020-01-29 12:38:58 -0800419 elif project in extra_modules:
420 sys.exit(f'{project}, given in ZEPHYR_EXTRA_MODULES, '
421 'is not a valid zephyr module')
Anas Nashif286a9ed2019-12-11 10:13:23 -0500422
Damian Krolika5051482022-03-01 18:36:16 +0100423 for module in all_modules_by_name.values():
424 if not module.depends:
425 start_modules.append(module)
426 else:
427 dep_modules.append(module)
428
Torsten Rasmussen3917ee52020-05-18 22:34:49 +0200429 # This will do a topological sort to ensure the modules are ordered
430 # according to dependency settings.
431 while start_modules:
432 node = start_modules.pop(0)
433 sorted_modules.append(node)
Torsten Rasmussenf24f8832021-01-07 15:27:53 +0100434 node_name = node.meta['name']
Torsten Rasmussen3917ee52020-05-18 22:34:49 +0200435 to_remove = []
436 for module in dep_modules:
437 if node_name in module.depends:
438 module.depends.remove(node_name)
439 if not module.depends:
440 start_modules.append(module)
441 to_remove.append(module)
442 for module in to_remove:
443 dep_modules.remove(module)
444
445 if dep_modules:
446 # If there are any modules with unresolved dependencies, then the
447 # modules contains unmet or cyclic dependencies. Error out.
448 error = 'Unmet or cyclic dependencies in modules:\n'
449 for module in dep_modules:
450 error += f'{module.project} depends on: {module.depends}\n'
451 sys.exit(error)
452
Marcin Niestroj248d25d2021-05-08 16:56:34 +0200453 return sorted_modules
454
455
456def main():
457 parser = argparse.ArgumentParser(description='''
458 Process a list of projects and create Kconfig / CMake include files for
459 projects which are also a Zephyr module''')
460
461 parser.add_argument('--kconfig-out',
462 help="""File to write with resulting KConfig import
463 statements.""")
464 parser.add_argument('--twister-out',
465 help="""File to write with resulting twister
466 parameters.""")
467 parser.add_argument('--cmake-out',
468 help="""File to write with resulting <name>:<path>
469 values to use for including in CMake""")
Torsten Rasmussenfffaf052021-10-12 23:08:36 +0200470 parser.add_argument('--meta-out',
471 help="""Write a build meta YaML file containing a list
472 of Zephyr modules and west projects.
473 If a module or project is also a git repository
474 the current SHA revision will also be written.""")
Torsten Rasmussen1a519932021-11-04 18:35:50 +0100475 parser.add_argument('--meta-state-propagate', action='store_true',
476 help="""Propagate state of modules and west projects
477 to the suffix of the Zephyr SHA and if west is
478 used, to the suffix of the manifest SHA""")
Marcin Niestroj248d25d2021-05-08 16:56:34 +0200479 parser.add_argument('--settings-out',
480 help="""File to write with resulting <name>:<value>
481 values to use for including in CMake""")
482 parser.add_argument('-m', '--modules', nargs='+',
483 help="""List of modules to parse instead of using `west
484 list`""")
485 parser.add_argument('-x', '--extra-modules', nargs='+',
486 help='List of extra modules to parse')
487 parser.add_argument('-z', '--zephyr-base',
488 help='Path to zephyr repository')
489 args = parser.parse_args()
490
491 kconfig = ""
492 cmake = ""
493 settings = ""
494 twister = ""
495
Torsten Rasmussenfffaf052021-10-12 23:08:36 +0200496 west_proj = None
497 if args.modules is None:
498 west_proj = west_projects()
499 modules = parse_modules(args.zephyr_base,
Torsten Rasmussen64ec6ee2021-11-04 14:28:21 +0100500 [p.posixpath for p in west_proj['projects']]
501 if west_proj else None,
Torsten Rasmussenfffaf052021-10-12 23:08:36 +0200502 args.extra_modules)
503 else:
504 modules = parse_modules(args.zephyr_base, args.modules,
505 args.extra_modules)
Marcin Niestroj248d25d2021-05-08 16:56:34 +0200506
507 for module in modules:
Torsten Rasmussen3917ee52020-05-18 22:34:49 +0200508 kconfig += process_kconfig(module.project, module.meta)
509 cmake += process_cmake(module.project, module.meta)
Torsten Rasmussen25d57ba2020-07-07 17:29:56 +0200510 settings += process_settings(module.project, module.meta)
Anas Nashif54713982020-12-07 14:52:10 -0500511 twister += process_twister(module.project, module.meta)
Torsten Rasmussen3917ee52020-05-18 22:34:49 +0200512
Torsten Rasmussenbd7569f2019-03-19 10:38:18 +0100513 if args.kconfig_out:
Anas Nashif286a9ed2019-12-11 10:13:23 -0500514 with open(args.kconfig_out, 'w', encoding="utf-8") as fp:
515 fp.write(kconfig)
Torsten Rasmussenbd7569f2019-03-19 10:38:18 +0100516
517 if args.cmake_out:
Anas Nashif286a9ed2019-12-11 10:13:23 -0500518 with open(args.cmake_out, 'w', encoding="utf-8") as fp:
519 fp.write(cmake)
Torsten Rasmussenbd7569f2019-03-19 10:38:18 +0100520
Torsten Rasmussen25d57ba2020-07-07 17:29:56 +0200521 if args.settings_out:
522 with open(args.settings_out, 'w', encoding="utf-8") as fp:
Martí Bolívar361956b2021-08-09 10:46:17 -0700523 fp.write('''\
524# WARNING. THIS FILE IS AUTO-GENERATED. DO NOT MODIFY!
525#
526# This file contains build system settings derived from your modules.
527#
528# Modules may be set via ZEPHYR_MODULES, ZEPHYR_EXTRA_MODULES,
529# and/or the west manifest file.
530#
531# See the Modules guide for more information.
532''')
Torsten Rasmussen25d57ba2020-07-07 17:29:56 +0200533 fp.write(settings)
534
Anas Nashif54713982020-12-07 14:52:10 -0500535 if args.twister_out:
536 with open(args.twister_out, 'w', encoding="utf-8") as fp:
537 fp.write(twister)
Torsten Rasmussenbd7569f2019-03-19 10:38:18 +0100538
Torsten Rasmussenfffaf052021-10-12 23:08:36 +0200539 if args.meta_out:
Torsten Rasmussen64ec6ee2021-11-04 14:28:21 +0100540 meta = process_meta(args.zephyr_base, west_proj, modules,
Torsten Rasmussen1a519932021-11-04 18:35:50 +0100541 args.extra_modules, args.meta_state_propagate)
Torsten Rasmussen64ec6ee2021-11-04 14:28:21 +0100542
Torsten Rasmussenfffaf052021-10-12 23:08:36 +0200543 with open(args.meta_out, 'w', encoding="utf-8") as fp:
544 fp.write(yaml.dump(meta))
545
Torsten Rasmussen25c3f8e2020-08-25 14:02:04 +0200546
Torsten Rasmussenbd7569f2019-03-19 10:38:18 +0100547if __name__ == "__main__":
548 main()