#!/usr/bin/env python3 """Check that non-test C++ rules only depend on Carbon and LLVM. Carbon works to ensure its user-visible libraries and binaries only depend on their code and LLVM. Among other benefits, this provides a single, simple license used for the whole project. However, we frequently use third-party projects and libraries where useful in our test code. Here, we verify that the dependencies of non-test C++ rules only include Carbon and LLVM code. """ __copyright__ = """ Part of the Carbon Language project, under the Apache License v2.0 with LLVM Exceptions. See /LICENSE for license information. SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception """ import os import sys from pathlib import Path runfiles = Path(os.environ["TEST_SRCDIR"]) deps_path = runfiles / "_main" / "bazel" / "check_deps" / "non_test_cc_deps.txt" try: with deps_path.open() as deps_file: deps = deps_file.read().splitlines() except FileNotFoundError: sys.exit("ERROR: unable to find deps file: %s" % deps_path) # This errors out on dependencies that aren't recognized, and continues on # allowed dependencies. for dep in deps: print("Checking dependency: " + dep) repo, _, rule = dep.partition("//") if repo == "@@+llvm_project+llvm-project": package, _, rule = rule.partition(":") # Other packages in the LLVM project shouldn't be accidentally used # in Carbon. We can expand the above list if use cases emerge. if package not in ( "clang", "clang-tools-extra/clangd", "libc", "libcxx", "libcxxabi", "libunwind", "lld", "llvm", # While this is in a `third_party` directory, its code is documented # as part of LLVM and for use in compiler-rt. "third-party/siphash", ) and ( package == "third-party" and rule not in ( # LLVM wrappers for zlib-ng and zstd, which are fine as linked. "zlib", "zstd", ) ): sys.exit( "ERROR: unexpected dependency into the LLVM project: %s" % dep ) # Check for accidentally using the copy of GoogleTest in LLVM. if rule in ("gmock", "gtest", "gtest_main"): sys.exit( "ERROR: dependency on LLVM's GoogleTest from non-test code: %s" % dep ) # The rest of LLVM, LLD, and Clang themselves are safe to depend on. continue # Carbon code is always allowed. if repo == "" and not rule.startswith("third_party"): continue # LLVM code managed in the Carbon repository is still LLVM code and OK. if repo == "" and rule.startswith("third_party/llvm:"): continue # Utility libraries provided by Bazel that are under a compatible license. if repo in ("@@rules_cc+", "@@bazel_tools"): continue # These libraries have compatible licenses and are linked in without copying # source, so fine for our binaries. if repo in ( "@@zlib-ng+", "@@zstd+", ): continue # This should never be reached from non-test code, but these targets do # exist. Specially diagnose them to try to provide a more helpful # message. if repo in ( "@google_benchmark", "@abseil-cpp", "@googletest", ): sys.exit("ERROR: dependency only allowed in test code: %s" % dep) # Conservatively fail if a dependency isn't explicitly allowed above. sys.exit(f"ERROR: unknown dependency on {repo}: {dep}")