2
0

rustc_args.py 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. #!/usr/bin/env python3
  2. """Generate rustc arguments for meson rust builds.
  3. This program generates --cfg compile flags for the configuration headers passed
  4. as arguments.
  5. Copyright (c) 2024 Linaro Ltd.
  6. Authors:
  7. Manos Pitsidianakis <manos.pitsidianakis@linaro.org>
  8. This program is free software; you can redistribute it and/or modify
  9. it under the terms of the GNU General Public License as published by
  10. the Free Software Foundation; either version 2 of the License, or
  11. (at your option) any later version.
  12. This program is distributed in the hope that it will be useful,
  13. but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. GNU General Public License for more details.
  16. You should have received a copy of the GNU General Public License
  17. along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. """
  19. import argparse
  20. import logging
  21. from pathlib import Path
  22. from typing import Any, Iterable, Mapping, Optional, Set
  23. try:
  24. import tomllib
  25. except ImportError:
  26. import tomli as tomllib
  27. class CargoTOML:
  28. tomldata: Mapping[Any, Any]
  29. check_cfg: Set[str]
  30. def __init__(self, path: str):
  31. with open(path, 'rb') as f:
  32. self.tomldata = tomllib.load(f)
  33. self.check_cfg = set(self.find_check_cfg())
  34. def find_check_cfg(self) -> Iterable[str]:
  35. toml_lints = self.lints
  36. rust_lints = toml_lints.get("rust", {})
  37. cfg_lint = rust_lints.get("unexpected_cfgs", {})
  38. return cfg_lint.get("check-cfg", [])
  39. @property
  40. def lints(self) -> Mapping[Any, Any]:
  41. return self.get_table("lints")
  42. def get_table(self, key: str) -> Mapping[Any, Any]:
  43. table = self.tomldata.get(key, {})
  44. return table
  45. def generate_cfg_flags(header: str, cargo_toml: CargoTOML) -> Iterable[str]:
  46. """Converts defines from config[..].h headers to rustc --cfg flags."""
  47. with open(header, encoding="utf-8") as cfg:
  48. config = [l.split()[1:] for l in cfg if l.startswith("#define")]
  49. cfg_list = []
  50. for cfg in config:
  51. name = cfg[0]
  52. if f'cfg({name})' not in cargo_toml.check_cfg:
  53. continue
  54. if len(cfg) >= 2 and cfg[1] != "1":
  55. continue
  56. cfg_list.append("--cfg")
  57. cfg_list.append(name)
  58. return cfg_list
  59. def main() -> None:
  60. parser = argparse.ArgumentParser()
  61. parser.add_argument("-v", "--verbose", action="store_true")
  62. parser.add_argument(
  63. "--config-headers",
  64. metavar="CONFIG_HEADER",
  65. action="append",
  66. dest="config_headers",
  67. help="paths to any configuration C headers (*.h files), if any",
  68. required=False,
  69. default=[],
  70. )
  71. parser.add_argument(
  72. metavar="TOML_FILE",
  73. action="store",
  74. dest="cargo_toml",
  75. help="path to Cargo.toml file",
  76. )
  77. args = parser.parse_args()
  78. if args.verbose:
  79. logging.basicConfig(level=logging.DEBUG)
  80. logging.debug("args: %s", args)
  81. cargo_toml = CargoTOML(args.cargo_toml)
  82. for header in args.config_headers:
  83. for tok in generate_cfg_flags(header, cargo_toml):
  84. print(tok)
  85. if __name__ == "__main__":
  86. main()