• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1"""
2This file assembles a toolchain for Linux using the Clang Compiler and musl.
3
4It currently makes use of musl and not glibc because the pre-compiled libraries from the latter
5have absolute paths baked in and this makes linking difficult. The pre-compiled musl library
6does not have this restriction and is much easier to statically link in as a result.
7
8As inputs, it takes external URLs from which to download the clang binaries/libraries/includes
9as well as the musl headers and pre-compiled binaries. Those files are downloaded and put
10into one folder, with a little bit of re-arrangement so clang can find files (like the C runtime).
11"""
12
13def _download_and_extract_deb(ctx, deb, sha256, prefix, output = ""):
14    """Downloads a debian file and extracts the data into the provided output directory"""
15
16    # https://docs.bazel.build/versions/main/skylark/lib/repository_ctx.html#download
17    download_info = ctx.download(
18        url = deb,
19        output = "deb.ar",
20        sha256 = sha256,
21    )
22
23    # https://docs.bazel.build/versions/main/skylark/lib/repository_ctx.html#execute
24    # This uses the extracted llvm-ar that comes with clang.
25    ctx.execute(["bin/llvm-ar", "x", "deb.ar"])
26
27    # https://docs.bazel.build/versions/main/skylark/lib/repository_ctx.html#extract
28    extract_info = ctx.extract(
29        archive = "data.tar.xz",
30        output = output,
31        stripPrefix = prefix,
32    )
33
34    # Clean up
35    ctx.delete("deb.ar")
36    ctx.delete("data.tar.xz")
37    ctx.delete("control.tar.xz")
38
39def _build_cpp_toolchain_impl(ctx):
40    # Download the clang toolchain (the extraction can take a while)
41    # https://docs.bazel.build/versions/main/skylark/lib/repository_ctx.html#download
42    download_info = ctx.download_and_extract(
43        url = ctx.attr.clang_url,
44        output = "",
45        stripPrefix = ctx.attr.clang_prefix,
46        sha256 = ctx.attr.clang_sha256,
47    )
48
49    # This puts the musl include files in ${PWD}/usr/include/x86_64-linux-musl
50    # and the runtime files and lib.a files in ${PWD}/usr/lib/x86_64-linux-musl
51    _download_and_extract_deb(
52        ctx,
53        ctx.attr.musl_dev_url,
54        ctx.attr.musl_dev_sha256,
55        ".",
56    )
57
58    # kjlubick@ cannot figure out how to get clang to look in ${PWD}/usr/lib/x86_64-linux-musl
59    # for the crt1.o files, so we'll move them to ${PWD}/usr/lib/ where clang *is* looking.
60    for file in ["crt1.o", "crtn.o", "Scrt1.o", "crti.o", "rcrt1.o"]:
61        ctx.execute(["cp", "usr/lib/x86_64-linux-musl/" + file, "usr/lib/"])
62
63    # Create a BUILD.bazel file that makes all the files in this subfolder
64    # available for use in rules, i.e. in the toolchain declaration.
65    # https://docs.bazel.build/versions/main/skylark/lib/repository_ctx.html#file
66    ctx.file(
67        "BUILD.bazel",
68        content = """
69filegroup(
70    name = "all_files",
71    srcs = glob([
72        "**",
73    ]),
74    visibility = ["//visibility:public"]
75)
76""",
77        executable = False,
78    )
79
80build_cpp_toolchain = repository_rule(
81    implementation = _build_cpp_toolchain_impl,
82    attrs = {
83        "clang_url": attr.string(mandatory = True),
84        "clang_sha256": attr.string(mandatory = True),
85        "clang_prefix": attr.string(mandatory = True),
86        "musl_dev_url": attr.string(mandatory = True),
87        "musl_dev_sha256": attr.string(mandatory = True),
88    },
89    doc = "",
90)
91