check_non_test_cc_deps.py 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  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. # This errors out on dependencies that aren't recognized, and continues on
  26. # allowed dependencies.
  27. for dep in deps:
  28. print("Checking dependency: " + dep)
  29. repo, _, rule = dep.partition("//")
  30. if repo == "@@+llvm_project+llvm-project":
  31. package, _, rule = rule.partition(":")
  32. # Other packages in the LLVM project shouldn't be accidentally used
  33. # in Carbon. We can expand the above list if use cases emerge.
  34. if package not in (
  35. "clang",
  36. "clang-tools-extra/clangd",
  37. "libc",
  38. "libcxx",
  39. "libcxxabi",
  40. "libunwind",
  41. "lld",
  42. "llvm",
  43. # While this is in a `third_party` directory, its code is documented
  44. # as part of LLVM and for use in compiler-rt.
  45. "third-party/siphash",
  46. ) and (
  47. package == "third-party"
  48. and rule
  49. not in (
  50. # LLVM wrappers for zlib-ng and zstd, which are fine as linked.
  51. "zlib",
  52. "zstd",
  53. )
  54. ):
  55. sys.exit(
  56. "ERROR: unexpected dependency into the LLVM project: %s" % dep
  57. )
  58. # Check for accidentally using the copy of GoogleTest in LLVM.
  59. if rule in ("gmock", "gtest", "gtest_main"):
  60. sys.exit(
  61. "ERROR: dependency on LLVM's GoogleTest from non-test code: %s"
  62. % dep
  63. )
  64. # The rest of LLVM, LLD, and Clang themselves are safe to depend on.
  65. continue
  66. # Carbon code is always allowed.
  67. if repo == "" and not rule.startswith("third_party"):
  68. continue
  69. # LLVM code managed in the Carbon repository is still LLVM code and OK.
  70. if repo == "" and rule.startswith("third_party/llvm:"):
  71. continue
  72. # Utility libraries provided by Bazel that are under a compatible license.
  73. if repo in ("@@rules_cc+", "@@bazel_tools"):
  74. continue
  75. # These libraries have compatible licenses and are linked in without copying
  76. # source, so fine for our binaries.
  77. if repo in (
  78. "@@zlib-ng+",
  79. "@@zstd+",
  80. ):
  81. continue
  82. # This should never be reached from non-test code, but these targets do
  83. # exist. Specially diagnose them to try to provide a more helpful
  84. # message.
  85. if repo in (
  86. "@google_benchmark",
  87. "@abseil-cpp",
  88. "@googletest",
  89. ):
  90. sys.exit("ERROR: dependency only allowed in test code: %s" % dep)
  91. # Conservatively fail if a dependency isn't explicitly allowed above.
  92. sys.exit(f"ERROR: unknown dependency on {repo}: {dep}")