Skip to content

Commit

Permalink
scripts: fix west zephyr-export error handling
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
mbolivar-nordic authored and nashif committed Apr 16, 2020
1 parent 94de3e9 commit d6f5f51
Showing 1 changed file with 43 additions and 35 deletions.
78 changes: 43 additions & 35 deletions scripts/west_commands/export.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 = '''\
Expand Down Expand Up @@ -39,38 +42,43 @@ def do_add_parser(self, parser_adder):
return parser

def do_run(self, args, unknown_args):
zephyr_config_package_path = PurePath(__file__).parents[2] \
/ 'share' / 'zephyr-package' / 'cmake'

cmake_args = ['-S', f'{zephyr_config_package_path}',
'-B', f'{zephyr_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_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))

zephyr_unittest_config_package_path = PurePath(__file__).parents[2] \
/ 'share' / 'zephyrunittest-package' / 'cmake'

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.
# 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('-- ')]
print('\n'.join(msg))
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)

0 comments on commit d6f5f51

Please sign in to comment.