sandboxed-api/sandboxed_api/bazel/llvm_config.bzl
Christian Blichmann e98133c7b4 bazel: Use linkopts instead of srcs for consuming archives
This should fix the build on Debian 10 with LLVM 11.

- Keep order of files to look up in `ls` invocation
- Use `--start-group`/`--end-group` linker options
- Drive-by: use `splitlines()` instead of manual `split("\n")[:-1]`

PiperOrigin-RevId: 439248079
Change-Id: I919bb292ac8a5f514431aa004345f1c6478b1cc9
2022-04-04 01:00:54 -07:00

230 lines
7.5 KiB
Python

# Copyright 2022 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Repository rule that tries to find system provided LLVM packages."""
load("@bazel_tools//tools/build_defs/repo:utils.bzl", "maybe")
SYSTEM_LLVM_BAZEL_TEMPLATE = """package(default_visibility = ["//visibility:public"])
# Create one hidden library with all LLVM headers that depends on all its
# static library archives. This will be used to provide individual library
# targets named the same as the upstream Bazel files.
cc_library(
name = "llvm",
hdrs = glob([
"llvm-project-include/clang-c/**/*.h",
"llvm-project-include/clang/**/*.def",
"llvm-project-include/clang/**/*.h",
"llvm-project-include/clang/**/*.inc",
"llvm-project-include/llvm-c/**/*.h",
"llvm-project-include/llvm/**/*.def",
"llvm-project-include/llvm/**/*.h",
"llvm-project-include/llvm/**/*.inc",
]),
includes = ["llvm-project-include"],
linkopts = [
"-lncurses",
"-lz",
"-L%{llvm_lib_dir}",
"-Wl,--start-group",
%{llvm_libs}
"-Wl,--end-group",
],
visibility = ["@llvm-project//clang:__pkg__"],
)
# Fake support library
cc_library(name = "Support", deps = ["@llvm-project//llvm:llvm"])
"""
SYSTEM_CLANG_BAZEL = """package(default_visibility = ["//visibility:public"])
# Fake libraries that just depend on a big library with all files.
cc_library(name = "ast", deps = ["@llvm-project//llvm:llvm"])
cc_library(name = "basic", deps = ["@llvm-project//llvm:llvm"])
cc_library(name = "driver", deps = ["@llvm-project//llvm:llvm"])
cc_library(name = "format", deps = ["@llvm-project//llvm:llvm"])
cc_library(name = "frontend", deps = ["@llvm-project//llvm:llvm"])
cc_library(name = "lex", deps = ["@llvm-project//llvm:llvm"])
cc_library(name = "tooling", deps = ["@llvm-project//llvm:llvm"])
"""
def _use_system_llvm(ctx):
found = False
# Look for LLVM in known places
llvm_dirs = ctx.execute(
["ls", "-1f"] +
[
"/usr/lib/llvm-{}/include/llvm/Support/InitLLVM.h".format(ver)
for ver in [16, 15, 14, 13, 12, 11] # Debian
] + [
"/usr/include/llvm/Support/InitLLVM.h", # Fedora and others
],
).stdout.splitlines()
if llvm_dirs:
llvm_dir = llvm_dirs[0].split("/include/llvm/")[0]
for suffix in ["llvm", "llvm-c", "clang", "clang-c"]:
ctx.symlink(
llvm_dir + "/include/" + suffix,
"llvm/llvm-project-include/" + suffix,
)
# Try to find the lib directory
lib_dirs = ctx.execute(
["ls", "-d1f"] +
[llvm_dir + "/lib64", llvm_dir + "/lib"],
).stdout.splitlines()
if lib_dirs:
found = True
if found:
# Create stub targets in sub-packages
lib_dir = lib_dirs[0] # buildifier: disable=uninitialized
archives = ctx.execute(
["find", ".", "-maxdepth", "1"] +
["(", "-name", "libLLVM*.a", "-o", "-name", "libclang*.a", ")"],
working_directory = lib_dir,
).stdout.splitlines()
lib_strs = sorted(["\"-l{}\",".format(a[5:-2]) for a in archives])
ctx.file(
"llvm/BUILD.bazel",
SYSTEM_LLVM_BAZEL_TEMPLATE
.replace("%{llvm_lib_dir}", lib_dir)
.replace("%{llvm_libs}", "\n".join(lib_strs)),
)
ctx.file("clang/BUILD.bazel", SYSTEM_CLANG_BAZEL)
return found
def _overlay_directories(ctx, src_path, target_path):
bazel_path = src_path.get_child("utils").get_child("bazel")
overlay_path = bazel_path.get_child("llvm-project-overlay")
script_path = bazel_path.get_child("overlay_directories.py")
python_bin = ctx.which("python3")
if not python_bin:
python_bin = ctx.which("python")
if not python_bin:
fail("Failed to find python3 binary")
cmd = [
python_bin,
script_path,
"--src",
src_path,
"--overlay",
overlay_path,
"--target",
target_path,
]
exec_result = ctx.execute(cmd, timeout = 20)
if exec_result.return_code != 0:
fail(("Failed to execute overlay script: '{cmd}'\n" +
"Exited with code {return_code}\n" +
"stdout:\n{stdout}\n" +
"stderr:\n{stderr}\n").format(
cmd = " ".join([str(arg) for arg in cmd]),
return_code = exec_result.return_code,
stdout = exec_result.stdout,
stderr = exec_result.stderr,
))
DEFAULT_LLVM_COMMIT = "2c494f094123562275ae688bd9e946ae2a0b4f8b" # 2022-03-31
DEFAULT_LLVM_SHA256 = "59b9431ae22f0ea5f2ce880925c0242b32a9e4f1ae8147deb2bb0fc19b53fa0d"
def _llvm_configure_impl(ctx):
commit = ctx.attr.commit
sha256 = ctx.attr.sha256
if ctx.attr.system_libraries:
if _use_system_llvm(ctx):
return
if not commit:
fail((
"Failed to find LLVM and clang system libraries\n\n" +
"Note: You may have to install llvm-13-dev and libclang-13-dev\n" +
" packages (or later versions) first.\n"
))
if not commit:
commit = DEFAULT_LLVM_COMMIT
sha256 = DEFAULT_LLVM_SHA256
ctx.download_and_extract(
["https://github.com/llvm/llvm-project/archive/{commit}.tar.gz".format(commit = commit)],
"llvm-raw",
sha256,
"",
"llvm-project-" + commit,
)
target_path = ctx.path("llvm-raw").dirname
src_path = target_path.get_child("llvm-raw")
_overlay_directories(ctx, src_path, target_path)
# Create a starlark file with the requested LLVM targets
ctx.file(
"llvm/targets.bzl",
"llvm_targets = " + str(ctx.attr.targets),
executable = False,
)
# Set up C++ toolchain options. LLVM requires at least C++ 14.
ctx.file(
".bazelrc",
"build --cxxopt=-std=c++17 --host_cxxopt=-std=c++17",
executable = False,
)
DEFAULT_TARGETS = ["AArch64", "ARM", "PowerPC", "X86"]
llvm_configure = repository_rule(
implementation = _llvm_configure_impl,
local = True,
configure = True,
attrs = {
"system_libraries": attr.bool(default = True),
"commit": attr.string(),
"sha256": attr.string(),
"targets": attr.string_list(default = DEFAULT_TARGETS),
},
)
def _llvm_zlib_disable_impl(ctx):
ctx.file(
"BUILD.bazel",
"""cc_library(name = "zlib", visibility = ["//visibility:public"])""",
executable = False,
)
llvm_zlib_disable = repository_rule(
implementation = _llvm_zlib_disable_impl,
)
def _llvm_terminfo_disable(ctx):
ctx.file(
"BUILD.bazel",
"""cc_library(name = "terminfo", visibility = ["//visibility:public"])""",
executable = False,
)
llvm_terminfo_disable = repository_rule(
implementation = _llvm_terminfo_disable,
)
def llvm_disable_optional_support_deps():
maybe(llvm_zlib_disable, name = "llvm_zlib")
maybe(llvm_terminfo_disable, name = "llvm_terminfo")