zephyr/scripts/west_commands/export.py
Martí Bolívar d6f5f51f37 scripts: fix west zephyr-export error handling
Fix two issues:

1. The script assumes the default CMake generator build tool
   platform is installed. On Linux at least, that's Make instead
   of Ninja, but Make might not be installed since Zephyr recommends
   Ninja. On Windows, that might be VS Code or nmake.

   Calling `cmake -P pristine` instead of `cmake --build <path>
   --target pristine` has the benefit of removing the dependency on a
   build command, and hence the default generator is not relevant.

2. It also assumes run_cmake() returns control, and therefore pristine
   can be run.

   However, if the cmake command fails hard (say, due to issue #1
   before this patch), run_cmake() throws an exception instead.

   Fix that by trying to run the pristine target in a finally block
   instead, and adding some manual cleanup steps in case the build
   system is in a bad state and pristine fails too.

Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
Signed-off-by: Torsten Rasmussen <torsten.rasmussen@nordicsemi.no>
2020-04-16 07:46:18 -04:00

85 lines
2.7 KiB
Python

# Copyright (c) 2020 Nordic Semiconductor ASA
#
# SPDX-License-Identifier: Apache-2.0
import argparse
from pathlib import Path
from shutil import rmtree
from subprocess import CalledProcessError
from west.commands import WestCommand
from west import log
from zcmake import run_cmake
EXPORT_DESCRIPTION = '''\
This command registers the current Zephyr installation as a CMake
config package in the CMake user package registry.
In Windows, the CMake user package registry is found in:
HKEY_CURRENT_USER\\Software\\Kitware\\CMake\\Packages\\
In Linux and MacOS, the CMake user package registry is found in:
~/.cmake/packages/'''
class ZephyrExport(WestCommand):
def __init__(self):
super().__init__(
'zephyr-export',
# Keep this in sync with the string in west-commands.yml.
'export Zephyr installation as a CMake config package',
EXPORT_DESCRIPTION,
accepts_unknown_args=False)
def do_add_parser(self, parser_adder):
parser = parser_adder.add_parser(
self.name,
help=self.help,
formatter_class=argparse.RawDescriptionHelpFormatter,
description=self.description)
return parser
def do_run(self, args, unknown_args):
# The 'share' subdirectory of the top level zephyr repository.
share = Path(__file__).parents[2] / 'share'
run_cmake_and_clean_up(share / 'zephyr-package' / 'cmake')
run_cmake_and_clean_up(share / 'zephyrunittest-package' / 'cmake')
def run_cmake_and_clean_up(path):
# Run a package installation script, cleaning up afterwards.
#
# Filtering out lines that start with -- ignores the normal
# CMake status messages and instead only prints the important
# information.
try:
lines = run_cmake(['-S', str(path), '-B', str(path)],
capture_output=True)
finally:
msg = [line for line in lines if not line.startswith('-- ')]
log.inf('\n'.join(msg))
clean_up(path)
def clean_up(path):
try:
run_cmake(['-P', str(path / 'pristine.cmake')],
capture_output=True)
except CalledProcessError:
# Do our best to clean up even though CMake failed.
log.wrn(f'Failed to make {path} pristine; '
'removing known generated files...')
for subpath in ['CMakeCache.txt', 'CMakeFiles', 'build.ninja',
'cmake_install.cmake', 'rules.ninja']:
remove_if_exists(Path(path) / subpath)
def remove_if_exists(pathobj):
if pathobj.is_file():
log.inf(f'- removing: {pathobj}')
pathobj.unlink()
elif pathobj.is_dir():
log.inf(f'- removing: {pathobj}')
rmtree(pathobj)