Why dependent workspace doesn't automatically include/execute the WORKSPACE file it has a dependency on in Bazel

736 views Asked by At

I have two repositories with Bazel builds. The one uses the Bazel imports for building protobuf types. When I make this repo/workspace a dependency of my other repo/workspace I have to re-add all of the protobuf imports for rules_proto and rules_cc to this new dependent workspace. Is there a way to not have to do this, or is this expected behavior with Bazel builds?

Example:
WORKSPACE A:

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

http_archive(
    name = "bazel_skylib",
    strip_prefix = "bazel-skylib-67bfa0ce4de5d4b512178d5f63abad1696f6c05b",
    urls = ["https://github.com/bazelbuild/bazel-skylib/archive/67bfa0ce4de5d4b512178d5f63abad1696f6c05b.tar.gz"],
)

http_archive(
    name = "rules_cc",
    sha256 = "d1886f0ea5b6cfe7519b87030811f52620db31bcca7ef9964aa17af2d14f23c4",
    strip_prefix = "rules_cc-cb6d32e4d1ae29e20dd3328109d8cb7f8eccc9be",
    urls = [
        "https://mirror.bazel.build/github.com/bazelbuild/rules_cc/archive/cb6d32e4d1ae29e20dd3328109d8cb7f8eccc9be.tar.gz",
        "https://github.com/bazelbuild/rules_cc/archive/cb6d32e4d1ae29e20dd3328109d8cb7f8eccc9be.tar.gz",
    ],
)

http_archive(
    name = "rules_proto",
    sha256 = "fb7f1959d2d2bf4d7a1f4f29d650845a9a2303b7879c6792320ba8244910ab01",
    strip_prefix = "rules_proto-3212323502e21b819ac4fbdd455cb227ad0f6394",
    urls = [
        "https://mirror.bazel.build/github.com/bazelbuild/rules_proto/archive/3212323502e21b819ac4fbdd455cb227ad0f6394.tar.gz",
        "https://github.com/bazelbuild/rules_proto/archive/3212323502e21b819ac4fbdd455cb227ad0f6394.tar.gz",
    ],
)

load("@rules_cc//cc:repositories.bzl", "rules_cc_dependencies")

rules_cc_dependencies()

load("@rules_proto//proto:repositories.bzl", "rules_proto_dependencies", "rules_proto_toolchains")

rules_proto_dependencies()

rules_proto_toolchains()

WORKSPACE B (has dependency on WORKSPACE A):

load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository")

git_repository(
    name = "workspace-a",
    branch = "bazel",
    remote = "url/to/my/git/repo",
)

# WHY DO I HAVE TO DO THE FOLLOWING WHEN IT'S DONE IN WORKSPACE A ALREADY?
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")

http_archive(
    name = "bazel_skylib",
    strip_prefix = "bazel-skylib-67bfa0ce4de5d4b512178d5f63abad1696f6c05b",
    urls = ["https://github.com/bazelbuild/bazel-skylib/archive/67bfa0ce4de5d4b512178d5f63abad1696f6c05b.tar.gz"],
)

http_archive(
    name = "rules_cc",
    sha256 = "d1886f0ea5b6cfe7519b87030811f52620db31bcca7ef9964aa17af2d14f23c4",
    strip_prefix = "rules_cc-cb6d32e4d1ae29e20dd3328109d8cb7f8eccc9be",
    urls = [
        "https://mirror.bazel.build/github.com/bazelbuild/rules_cc/archive/cb6d32e4d1ae29e20dd3328109d8cb7f8eccc9be.tar.gz",
        "https://github.com/bazelbuild/rules_cc/archive/cb6d32e4d1ae29e20dd3328109d8cb7f8eccc9be.tar.gz",
    ],
)

http_archive(
    name = "rules_proto",
    sha256 = "fb7f1959d2d2bf4d7a1f4f29d650845a9a2303b7879c6792320ba8244910ab01",
    strip_prefix = "rules_proto-3212323502e21b819ac4fbdd455cb227ad0f6394",
    urls = [
        "https://mirror.bazel.build/github.com/bazelbuild/rules_proto/archive/3212323502e21b819ac4fbdd455cb227ad0f6394.tar.gz",
        "https://github.com/bazelbuild/rules_proto/archive/3212323502e21b819ac4fbdd455cb227ad0f6394.tar.gz",
    ],
)

load("@rules_cc//cc:repositories.bzl", "rules_cc_dependencies")

rules_cc_dependencies()

load("@rules_proto//proto:repositories.bzl", "rules_proto_dependencies", "rules_proto_toolchains")

rules_proto_dependencies()

rules_proto_toolchains()
1

There are 1 answers

0
ahumesky On BEST ANSWER

It's mostly because Bazel wasn't really originally designed to be a package manager. Bazel comes from a monorepo design where everything (your applications, libraries, third-party dependencies, data, tools, toolchains, compilers, Bazel itself, etc) is checked into a single repository with a single version of everything. So there's no question of where things come from and how to integrate them beyond the domain-specific rulesets (Java, C++, Python, etc). It's all just there in BUILD files. The WORKSPACE design and external dependencies are for bridging the monorepo approach and non-monorepo approach.

Some mitigations of the inconveniences are the macros like rules_proto_dependencies() and rules_proto_toolchains(), but you still have to load many things at the top-level, and resolve diamond-dependency problems manually.

There's a new system call "bzlmod" that's being developed to replace all of this. It was recently experimentally released in Bazel 5.0: https://bazel.build/docs/bzlmod