Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
# Initialize build_dir and created_build_dir attributes.
# If we created the build directory, we must run CMake.
log.dbg('setting up build directory', level=log.VERBOSE_EXTREME)
# The CMake Cache has not been loaded yet, so this is safe
board, _ = self._find_board()
source_dir = self._find_source_dir()
app = os.path.split(source_dir)[1]
build_dir = find_build_dir(self.args.build_dir, board=board,
source_dir=source_dir, app=app)
if not build_dir:
log.die('Unable to determine a default build folder. Check '
'your build.dir-fmt configuration option')
if os.path.exists(build_dir):
if not os.path.isdir(build_dir):
log.die('build directory {} exists and is not a directory'.
format(build_dir))
else:
os.makedirs(build_dir, exist_ok=False)
self.created_build_dir = True
self.run_cmake = True
self.build_dir = build_dir
def _ensure_min_version(cmake, dry_run):
cmd = [cmake, '--version']
if dry_run:
log.inf('Dry run:', quote_sh_list(cmd))
return
try:
version_out = subprocess.check_output(cmd, stderr=subprocess.DEVNULL)
except subprocess.CalledProcessError as cpe:
log.die('cannot get cmake version:', str(cpe))
decoded = version_out.decode('utf-8')
lines = decoded.splitlines()
if not lines:
log.die('can\'t get cmake version: ' +
'unexpected "cmake --version" output:\n{}\n'.
format(decoded) +
'Please install CMake ' + _MIN_CMAKE_VERSION_STR +
' or higher (https://cmake.org/download/).')
version = lines[0].split()[2]
if packaging.version.parse(version) < _MIN_CMAKE_VERSION:
log.die('cmake version', version,
'is less than minimum version {};'.
format(_MIN_CMAKE_VERSION_STR),
'please update your CMake (https://cmake.org/download/).')
else:
log.dbg('cmake version', version, 'is OK; minimum version is',
args.handler(args, unknown)
except WestUpdated:
# West has been automatically updated. Restart ourselves to run the
# latest version, with the same arguments that we were given.
os.execv(sys.executable, [sys.executable] + argv)
except KeyboardInterrupt:
sys.exit(0)
except CalledProcessError as cpe:
log.err('command exited with status {}: {}'.format(
cpe.args[0], quote_sh_list(cpe.args[1])))
if args.verbose:
raise
else:
log.inf(for_stack_trace)
except CommandContextError as cce:
log.die('command', args.command, 'cannot be run in this context:',
*cce.args)
# what west.manifest needs to happen before we can
# resolve the missing import.
rev = p.revision
ctxt += f' from revision "{rev}"\n'
ctxt += ' Hint: for this to work:\n'
ctxt += f' - {p.name} must be cloned\n'
ctxt += (f' - its {MANIFEST_REV_BRANCH} ref '
'must point to a commit with the missing file\n')
ctxt += ' To fix, run:\n'
ctxt += ' west update'
log.die(f'failed manifest import in {p.name_and_path}\n' +
ctxt)
else:
log.die('internal error:',
f'unhandled manifest load exception: {self.mle}')
def _run_pristine(self):
_banner('making build dir {} pristine'.format(self.build_dir))
zb = os.environ.get('ZEPHYR_BASE')
if not zb:
log.die('Internal error: ZEPHYR_BASE not set in the environment, '
'and should have been by the main script')
if not is_zephyr_build(self.build_dir):
log.die('Refusing to run pristine on a folder that is not a '
'Zephyr build system')
cmake_args = ['-P', '{}/cmake/pristine.cmake'.format(zb)]
run_cmake(cmake_args, cwd=self.build_dir, dry_run=self.args.dry_run)
except KeyError:
log.die('CMake cache has no CACHED_DTS_ROOT_BINDINGS.'
'\n Try again after re-building your application.')
# Ensure the build directory has a compiled DTS file
# where we expect it to be.
dts = b / 'zephyr' / (cache['CACHED_BOARD'] + '.dts.pre.tmp')
if not dts.is_file():
log.die("can't find DTS; expected:", dts)
log.dbg('DTS file:', dts, level=log.VERBOSE_VERY)
# Parse the devicetree using bindings from cache.
try:
edt = edtlib.EDT(dts, bindings)
except edtlib.EDTError as e:
log.die("can't parse devicetree:", e)
# By convention, the zephyr,flash chosen node contains the
# partition information about the zephyr image to sign.
flash = edt.chosen_node('zephyr,flash')
if not flash:
log.die('devicetree has no chosen zephyr,flash node;',
"can't infer flash write block or image-0 slot sizes")
return flash
def do_run(self, args, unknown_args):
zb = os.environ.get('ZEPHYR_BASE')
if not zb:
log.die('Internal error: ZEPHYR_BASE not set in the environment, '
'and should have been by the main script')
cmake_args = ['-DBOARD_ROOT_SPACE_SEPARATED={}'.format(zb),
'-P', '{}/cmake/boards.cmake'.format(zb)]
lines = run_cmake(cmake_args, capture_output=True)
arch_re = re.compile(r'\s*([\w-]+)\:')
board_re = re.compile(r'\s*([\w-]+)\s*')
arch = None
boards = collections.OrderedDict()
for line in lines:
match = arch_re.match(line)
if match:
arch = match.group(1)
boards[arch] = []
continue
match = board_re.match(line)
log.die("DT zephyr,flash chosen node has no image-0 partition,",
"can't determine its size")
# The partitions node, and its subnode, must provide
# the size of the image-0 partition via the regs property.
if not image_0.regs:
log.die('image-0 flash partition has no regs property;',
"can't determine size of image slot 0")
# Die on missing or zero alignment or slot_size.
if "write-block-size" not in flash.props:
log.die('DT zephyr,flash node has no write-block-size;',
"can't determine imgtool write alignment")
align = flash.props['write-block-size'].val
if align == 0:
log.die('expected nonzero flash alignment, but got '
'DT flash device write-block-size {}'.format(align))
reg = image_0.regs[0]
if reg.size == 0:
log.die('expected nonzero slot size, but got '
'DT image-0 partition size {}'.format(reg.size))
return (align, reg.addr, reg.size)
This raises `west.commands.CommandContextError` if the command
cannot be run due to a context mismatch. Other exceptions may
be raised as well.
:param args: known arguments parsed via `WestCommand.add_parser`
:param unknown: unknown arguments present on the command line;
must be empty unless ``accepts_unknown_args`` is true
:param topdir: west workspace topdir, accessible as a str via
``self.topdir`` from `WestCommand.do_run`
:param manifest: `west.manifest.Manifest` or ``None``,
accessible as ``self.manifest`` from `WestCommand.do_run`
'''
if unknown and not self.accepts_unknown_args:
self.parser.error(f'unexpected arguments: {unknown}')
if not topdir and self.requires_workspace:
log.die(_no_topdir_msg(os.getcwd(), self.name))
self.topdir = os.fspath(topdir) if topdir else None
self.manifest = manifest
self.do_run(args, unknown)
def _sanity_check(self):
# Sanity check the build configuration.
# Side effect: may update cmake_cache attribute.
log.dbg('sanity checking the build', level=log.VERBOSE_EXTREME)
if self.source_dir == self.build_dir:
# There's no forcing this.
log.die('source and build directory {} cannot be the same; '
'use --build-dir {} to specify a build directory'.
format(self.source_dir, self.build_dir))
srcrel = os.path.relpath(self.source_dir)
if is_zephyr_build(self.source_dir):
self._check_force('it looks like {srcrel} is a build directory: '
'did you mean -build-dir {srcrel} instead?'.
format(srcrel=srcrel))
elif 'CMakeLists.txt' not in os.listdir(self.source_dir):
self._check_force('source directory "{srcrel}" does not contain '
'a CMakeLists.txt; is that really what you '
'want to build? (Use -s SOURCE_DIR to specify '
'the application source directory)'.
format(srcrel=srcrel))
if not is_zephyr_build(self.build_dir) and not self.args.board: