• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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