1# Copyright 2019 The Pigweed Authors 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); you may not 4# use this file except in compliance with the License. You may obtain a copy of 5# the License at 6# 7# https://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12# License for the specific language governing permissions and limitations under 13# the License. 14"""Copies built host tools into Pigweed's host_tools directory.""" 15 16import argparse 17import logging 18from pathlib import Path 19import shutil 20import sys 21from typing import Optional 22 23import pw_cli.log 24 25_LOG = logging.getLogger(__name__) 26 27 28def argument_parser( 29 parser: Optional[argparse.ArgumentParser] = None, 30) -> argparse.ArgumentParser: 31 """Registers the script's arguments on an argument parser.""" 32 33 if parser is None: 34 parser = argparse.ArgumentParser(description=__doc__) 35 36 parser.add_argument( 37 '--dst', type=Path, required=True, help='Path to host tools directory' 38 ) 39 parser.add_argument('--name', help='Name for the installed tool') 40 parser.add_argument( 41 '--out-root', 42 type=Path, 43 required=True, 44 help='Root of Ninja out directory', 45 ) 46 parser.add_argument( 47 '--src', type=Path, required=True, help='Path to host tool executable' 48 ) 49 50 return parser 51 52 53def main() -> int: 54 """Copies a host tool into a destination directory.""" 55 args = argument_parser().parse_args() 56 57 if not args.src.is_file(): 58 _LOG.error('%s is not a file', args.src) 59 return 1 60 61 args.dst.mkdir(parents=True, exist_ok=True) 62 63 if args.name is not None: 64 if '/' in args.name: 65 _LOG.error('Host tool name cannot contain "/"') 66 return 1 67 name = args.name 68 else: 69 name = args.src.name 70 71 try: 72 shutil.copy2(args.src, args.dst.joinpath(name)) 73 except OSError as err: 74 _LOG.error('%s', err) 75 76 # Errno 26 (text file busy) indicates that a host tool binary is 77 # currently running. 78 # TODO(frolv): Check if this works on Windows. 79 if err.errno == 26: 80 _LOG.error('') 81 _LOG.error(' %s has been rebuilt but cannot be', name) 82 _LOG.error(' copied into the host tools directory:') 83 _LOG.error('') 84 _LOG.error( 85 ' %s', args.dst.relative_to(args.out_root).joinpath(name) 86 ) 87 _LOG.error('') 88 _LOG.error(' This can occur if the program is already running.') 89 _LOG.error( 90 ' If it is running, exit it and try re-running the build.' 91 ) 92 _LOG.error('') 93 94 return 1 95 96 return 0 97 98 99if __name__ == '__main__': 100 pw_cli.log.install() 101 sys.exit(main()) 102