check_non_test_cc_deps.py 3.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. #!/usr/bin/env python3
  2. """Check that non-test C++ rules only depend on Carbon and LLVM.
  3. Carbon works to ensure its user-visible libraries and binaries only depend on
  4. their code and LLVM. Among other benefits, this provides a single, simple
  5. license used for the whole project.
  6. However, we frequently use third-party projects and libraries where useful in
  7. our test code. Here, we verify that the dependencies of non-test C++ rules only
  8. include Carbon and LLVM code.
  9. """
  10. __copyright__ = """
  11. Part of the Carbon Language project, under the Apache License v2.0 with LLVM
  12. Exceptions. See /LICENSE for license information.
  13. SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  14. """
  15. import os
  16. import sys
  17. from pathlib import Path
  18. runfiles = Path(os.environ["TEST_SRCDIR"])
  19. deps_path = runfiles / "_main" / "bazel" / "check_deps" / "non_test_cc_deps.txt"
  20. try:
  21. with deps_path.open() as deps_file:
  22. deps = deps_file.read().splitlines()
  23. except FileNotFoundError:
  24. sys.exit("ERROR: unable to find deps file: %s" % deps_path)
  25. # bazel_dep repos can have a `name~version` format, whereas use_repo and
  26. # use_repo_rule have a `@@_main~rule_name~repo_name` format. We process the
  27. # latter case first because we only have a couple; once done, we can assume
  28. # anything after the ~ is a version.
  29. for dep in deps:
  30. print("Checking dependency: " + dep)
  31. repo, _, rule = dep.partition("//")
  32. if repo == "@@_main~llvm_project~llvm-project":
  33. package, _, rule = rule.partition(":")
  34. # Other packages in the LLVM project shouldn't be accidentally used
  35. # in Carbon. We can expand the above list if use cases emerge.
  36. if package not in ("llvm", "lld", "clang", "clang-tools-extra/clangd"):
  37. sys.exit(
  38. "ERROR: unexpected dependency into the LLVM project: %s" % dep
  39. )
  40. # Check for accidentally using the copy of GoogleTest in LLVM.
  41. if rule in ("gmock", "gtest", "gtest_main"):
  42. sys.exit(
  43. "ERROR: dependency on LLVM's GoogleTest from non-test code: %s"
  44. % dep
  45. )
  46. # The rest of LLVM, LLD, and Clang themselves are safe to depend on.
  47. continue
  48. # Ignore the version, just use the repo name.
  49. repo_base = repo.split("~")[0]
  50. # Carbon code is always allowed.
  51. if repo_base == "" and not rule.startswith("third_party"):
  52. continue
  53. # An empty stub library added by rules_cc:
  54. # https://github.com/bazelbuild/rules_cc/blob/main/BUILD
  55. if repo_base == "@@rules_cc" and rule == ":link_extra_lib":
  56. continue
  57. # These are stubs wrapping system libraries for LLVM. They aren't
  58. # distributed and so should be fine.
  59. if repo_base in (
  60. "@@zlib",
  61. "@@zstd",
  62. ):
  63. continue
  64. # This should never be reached from non-test code, but these targets do
  65. # exist. Specially diagnose them to try to provide a more helpful
  66. # message.
  67. if repo_base in (
  68. "@google_benchmark",
  69. "@protobuf",
  70. "@abseil-cpp",
  71. "@googletest",
  72. ):
  73. sys.exit("ERROR: dependency only allowed in test code: %s" % dep)
  74. # Conservatively fail if a dependency isn't explicitly allowed above.
  75. sys.exit("ERROR: unknown dependency: %s" % dep)