Search code examples
buildbazel

Bazel select build file depending on toolchain


I want to change build file of a http_archive depending on the toolchain. The idea is to use a different library for a different architecture. But I could not figure out how. In my .bzl file I defined

load(
"@bazel_tools//tools/build_defs/repo:utils.bzl",
"maybe",)
load(
"@bazel_tools//tools/build_defs/repo:http.bzl",
"http_archive",
)

def silkit():
    maybe(
        http_archive,
        name = "silkit",
        build_file = <select-build-file>,
        url = "silkit-url-in artifactory",
    )

I defined silkit_aarch64.BUILD and silkit_x86_64.BUILD under the same folder. In my .bazelrc file, I defined

build:aarch64 --platforms=//toolchain/gcc_12.3.0_aarch64:aarch64

I need to get this info in .bzl file. How can I do it?


Solution

  • I think you can do this with select in a single BUILD file. I can't think of anything which actually requires separate repositories. For example, if you currently have this:

    cc_library(
        name = "silkit",
        hdrs = glob(["usr/include/aarch64-linux-gnu/*.h"]),
        includes = ["usr/include/aarch64-linux-gnu"],
        srcs = glob(["usr/lib/aarch64-linux-gnu/libnsilkit.so.0.*"]),
    )
    

    and this:

    cc_library(
        name = "silkit",
        hdrs = glob(["usr/include/x86_64-linux-gnu/*.h"]),
        includes = ["usr/include/x86_64-linux-gnu"],
        srcs = glob(["usr/lib/x86_64-linux-gnu/libnsilkit.so.0.*"]),
    )
    

    then you can combine them like this:

    cc_library(
        name = "silkit",
        hdrs = select({
            "@platforms//cpu:aarch64": glob(["usr/include/aarch64-linux-gnu/*.h"]),
            "@platforms//cpu:x86_64": glob(["usr/include/x86_64-linux-gnu/*.h"]),
        }),
        includes = select({
            "@platforms//cpu:aarch64": ["usr/include/aarch64-linux-gnu"],
            "@platforms//cpu:x86_64": ["usr/include/x86_64-linux-gnu"],
        }),
        srcs = select({
            "@platforms//cpu:aarch64": glob(["usr/lib/aarch64-linux-gnu/libnsilkit.so.0.*"]),
            "@platforms//cpu:x86_64": glob(["usr/lib/x86_64-linux-gnu/libnsilkit.so.0.*"]),
        }),
    )
    

    That's the approach I've taken when there's a single archive file for both platforms.

    If you really need separate repositories (if there are different archive files for each for example), then you need to create separate repositories and then use select to choose which one to use. Bazel won't download the deselected one for bazel build commands. Something like this:

    def silkit():
        maybe(
            http_archive,
            name = "silkit_aarch64",
            build_file = "silkit_aarch64.BUILD",
            url = "silkit-aarch64-url-in artifactory",
        )
        maybe(
            http_archive,
            name = "silkit_x86_64",
            build_file = "silkit_x86_64.BUILD",
            url = "silkit-x86_64-url-in artifactory",
        )
    

    and then put something like this to select the appropriate one to use:

    cc_library(
        name = "silkit",
        deps = select({
            "@platforms//cpu:aarch64": ["@silkit_aarch64//:silkit"],
            "@platforms//cpu:x86_64": ["@silkit_x86_64//:silkit"],
        }),
    )
    

    I've found cc_library works better for this than alias due to some complications with forwarding providers, but for simple cases like this either will work.