1#!/usr/bin/env python 2# Copyright 2020 The Pigweed Authors 3# 4# Licensed under the Apache License, Version 2.0 (the "License"); you may not 5# use this file except in compliance with the License. You may obtain a copy of 6# the License at 7# 8# https://www.apache.org/licenses/LICENSE-2.0 9# 10# Unless required by applicable law or agreed to in writing, software 11# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13# License for the specific language governing permissions and limitations under 14# the License. 15"""Generates a BUILD.gn for a Python package. 16 17Pass the script a list of paths to the root directory of a Python package (where 18setup.py is). 19 20Don't forget to add the pw_python_package to a top-level group, or it will not 21be included in the build. 22""" 23 24from datetime import datetime 25from pathlib import Path 26import sys 27from typing import Iterable, NamedTuple 28 29from pw_presubmit import git_repo 30 31_HEADER = f"""\ 32# Copyright {datetime.now().year} The Pigweed Authors 33# 34# Licensed under the Apache License, Version 2.0 (the "License"); you may not 35# use this file except in compliance with the License. You may obtain a copy of 36# the License at 37# 38# https://www.apache.org/licenses/LICENSE-2.0 39# 40# Unless required by applicable law or agreed to in writing, software 41# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 42# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 43# License for the specific language governing permissions and limitations under 44# the License. 45 46import("//build_overrides/pigweed.gni") 47 48import("$dir_pw_build/python.gni") 49""" 50 51 52class PackageFiles(NamedTuple): 53 setup: list[Path] 54 sources: list[Path] 55 tests: list[Path] 56 other: list[Path] 57 58 59def _find_package_files(root_dir: Path) -> PackageFiles: 60 files = git_repo.list_files( 61 pathspecs=('*.py', '*.toml', '*.cfg'), repo_path=root_dir 62 ) 63 64 package_files = PackageFiles([], [], [], []) 65 66 for file in files: 67 if file.parent == root_dir: 68 if file.name == 'setup.py' or file.suffix != '.py': 69 package_files.setup.append(file) 70 elif file.stem.startswith('test_') or file.stem.endswith('_test'): 71 package_files.tests.append(file) 72 else: 73 package_files.other.append(file) 74 else: 75 package_files.sources.append(file) 76 77 return package_files 78 79 80def _gn_list(name: str, files: Iterable[Path], base: Path) -> Iterable[str]: 81 if files: 82 yield f' {name} = [' 83 for file in files: 84 yield f' "{file.relative_to(base).as_posix()}",' 85 yield ' ]' 86 87 88def generate_build_gn(root_dir: Path): 89 files = _find_package_files(root_dir) 90 91 yield _HEADER 92 93 yield 'pw_python_package("py") {' 94 95 yield from _gn_list('setup', files.setup, root_dir) 96 yield from _gn_list('sources', files.sources, root_dir) 97 yield from _gn_list('tests', files.tests, root_dir) 98 99 # Don't include the "other" files for now. 100 # yield from _gn_list('other', files.other, root_dir) 101 102 yield '}' 103 104 105def main(paths: Iterable[Path]): 106 for path in paths: 107 path.joinpath('BUILD.gn').write_text( 108 '\n'.join(generate_build_gn(path)) + '\n' 109 ) 110 111 112if __name__ == '__main__': 113 if len(sys.argv) > 1: 114 main(Path(p).resolve() for p in sys.argv[1:]) 115 else: 116 print(__file__, '', __doc__.strip(), sep='\n', file=sys.stderr) 117 sys.exit(1) 118