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>
diff --git a/scripts/west_commands/export.py b/scripts/west_commands/export.py
index f4f8367..f7f8dec 100644
--- a/scripts/west_commands/export.py
+++ b/scripts/west_commands/export.py
@@ -3,10 +3,13 @@
# 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 pathlib import PurePath
from zcmake import run_cmake
EXPORT_DESCRIPTION = '''\
@@ -39,38 +42,43 @@
return parser
def do_run(self, args, unknown_args):
- zephyr_config_package_path = PurePath(__file__).parents[2] \
- / 'share' / 'zephyr-package' / 'cmake'
+ # The 'share' subdirectory of the top level zephyr repository.
+ share = Path(__file__).parents[2] / 'share'
- cmake_args = ['-S', f'{zephyr_config_package_path}',
- '-B', f'{zephyr_config_package_path}']
- lines = run_cmake(cmake_args, capture_output=True)
+ run_cmake_and_clean_up(share / 'zephyr-package' / 'cmake')
+ run_cmake_and_clean_up(share / 'zephyrunittest-package' / 'cmake')
- # Let's clean up, as Zephyr has now been exported, and we no longer
- # need the generated files.
- cmake_args = ['--build', f'{zephyr_config_package_path}',
- '--target', 'pristine']
- run_cmake(cmake_args, capture_output=True)
+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.
- # Let's ignore the normal CMake printing and instead only print
- # 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('-- ')]
- print('\n'.join(msg))
+ log.inf('\n'.join(msg))
+ clean_up(path)
- zephyr_unittest_config_package_path = PurePath(__file__).parents[2] \
- / 'share' / 'zephyrunittest-package' / 'cmake'
+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)
- cmake_args = ['-S', f'{zephyr_unittest_config_package_path}',
- '-B', f'{zephyr_unittest_config_package_path}']
- lines = run_cmake(cmake_args, capture_output=True)
-
- # Let's clean up, as Zephyr has now been exported, and we no longer
- # need the generated files.
- cmake_args = ['--build', f'{zephyr_unittest_config_package_path}',
- '--target', 'pristine']
- run_cmake(cmake_args, capture_output=True)
-
- # Let's ignore the normal CMake printing and instead only print
- # the important information.
- msg = [line for line in lines if not line.startswith('-- ')]
- print('\n'.join(msg))
+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)