Skip to content

[Bazel] Migrate to Bzlmod#88927

Open
aaronmondal wants to merge 2 commits into
llvm:mainfrom
aaronmondal:add-bzlmod-support
Open

[Bazel] Migrate to Bzlmod#88927
aaronmondal wants to merge 2 commits into
llvm:mainfrom
aaronmondal:add-bzlmod-support

Conversation

@aaronmondal

@aaronmondal aaronmondal commented Apr 16, 2024

Copy link
Copy Markdown
Member

The workspace build is now gated behind --config=deprecated_workspace.

See utils/bazel/examples for the new setup instructions.

While not necessarily the most intuitive implementation, this seems to
be the only way retain the flexibility of all potential usecases as of
Bazel 8. The module build supports:

  • The in-tree build from within the utils/bazel directory.
  • The llvm-project cloned into an arbitrary directory (e.g. for local
    development, submodule setups and and Nix users).
  • The llvm-project fetched from github via an archive.

Since module overrides are invisible to third-party dependents, every
project that has the llvm project "somewhere" in its dependency tree
needs to create an explicit override in their root module. It's possible
to avoid this inconvenience by creating custom bazel registries, but
only makes sense to do for the next stable tag that contains this commit.

If you need to link against a nonhermetic system variant of an external
dependency you can override the repositories from the
llvm_project_overlay extension like this:

'''MODULE.bazel'''
new_local_repository = use_repo_rule(
    "@bazel_tools//tools/build_defs/repo:local.bzl",
    "new_local_repository",
)

new_local_repository(
    name = "zlib-ng",
    path = "xxxx",
    build_file_content = "xxxx",
)

override_repo(llvm_project_overlay, "zlib-ng")

@aaronmondal

Copy link
Copy Markdown
Member Author

cc @keith

Still under construction, but at least this works with bazelisk build @llvm-project//clang

Comment thread utils/bazel/extensions.bzl Outdated
Comment thread utils/bazel/extensions.bzl Outdated
@keith

keith commented Jun 26, 2024

Copy link
Copy Markdown
Member

think you'll get back to this sometime?

@aaronmondal

Copy link
Copy Markdown
Member Author

I believe this is still blocked by these:

I just tried building with 8.0.0-pre.20240607.2 and bazelisk test --config=ci @llvm-project//... and it still failed because of that.

@maxbartel

Copy link
Copy Markdown
Contributor

Seems like the two issues are resolved now. Any chance you want to try the transition again?

@aaronmondal

Copy link
Copy Markdown
Member Author

Seems like the two issues are resolved now. Any chance you want to try the transition again?

Will retry this weekend 👍

I'll need to figure out a more elegant solution for the patching and I think I figured out a better way for the external dependencies via label-flags so that we no longer need to maintain the custom nonhermeticity logic.

@aaronmondal aaronmondal force-pushed the add-bzlmod-support branch 5 times, most recently from ebec54f to c16968e Compare February 2, 2025 21:00
@aaronmondal aaronmondal changed the title [Bazel] Add support for Bzlmod [Bazel] Migrate to Bzlmod Feb 2, 2025
@aaronmondal aaronmondal marked this pull request as ready for review February 2, 2025 21:08
@llvmbot llvmbot added the bazel "Peripheral" support tier build system: utils/bazel label Feb 2, 2025
@aaronmondal aaronmondal requested a review from keith February 2, 2025 21:11
@maxbartel

Copy link
Copy Markdown
Contributor

@keith @rupprecht Do you think you could maybe review the PR soonish? It is quite the nice QoL improvement

@aaronmondal

aaronmondal commented Feb 11, 2025

Copy link
Copy Markdown
Member Author

FYI I've pulled out the zlib/zstd changes in a cleaner way in #126729

@rupprecht rupprecht left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not yet very familiar w/ bzlmod, so I'm not a great reviewer. But if it works, it works. Thanks for taking care of this!

Comment thread utils/bazel/.bazelversion Outdated
Comment on lines -321 to -329
# We unconditionally depend on the custom LLVM zlib wrapper. This will
# be an empty library unless zlib is enabled, in which case it will
# both provide the necessary dependencies and configuration defines.
"@llvm_zlib//:zlib",
# We unconditionally depend on the custom LLVM zstd wrapper. This will
# be an empty library unless zstd is enabled, in which case it will
# both provide the necessary dependencies and configuration defines.
"@llvm_zstd//:zstd",
],

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I kinda like having this pattern, as it makes the build files less cluttered (fewer selects). Could we re-introduce a wrapper around it, similar to the maybe_pfm target in this file? i.e. something like:

cc_library(
    name = "maybe_zlib",
    defines = select({
        ":zlib_enabled": ["LLVM_ENABLE_ZLIB=1"],
        "//conditions:default": [],
    }),
    deps = select({
        ":zlib_enabled": ["@zlib-ng"],
        "//conditions:default": [],
    }),
)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved to #126729

I did a lot of back-and-forth with the "maybe pattern". The cleaner looking callsites ("depsites" I guess 😅) are appealing but I ultimately came to the conclusion that it seems like a bad idea because it abuses implementation details that "just happen" to work in the cc_library case. That is, this isn't a generally applicable pattern that could be used for arbitrary rules because deps might not always be implemented transitively.

It also introduces additonal complexity that makes the build graph less efficient (an edge to maybe_zlib even if it's unused) and harder to reason about (can no longer easily see which config option influences the dep - need to go to the maybe target to check).

However, we can still make this less verbose. #126729 moves the LLVM_ENABLE_ZLIB define to the config rather than a defines attribute. This not only saves a lot off command-line length but also reduces the overall number of selects. Now the 4 occurances of the zlib dep in the overlay add just 3 additional selects over the maybe approach (as opposed to the previous 6) and just 1 additional select in the zstd case (as opposed to the previous 2).

Comment thread utils/bazel/extensions.bzl Outdated
Comment on lines +100 to +101
# TODO: Make `NB_BUILD=1` and `NB_SHARED=1` configurable in the BCR variant
# and import this via `MODULE.bazel`.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure what this comment means, would you mind clarifying?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Technically we should treat the http_archive calls as "migration helpers" with the goal of removing all of them and instead importing them via bazel_dep in the MODULE.bazel file. For the deps that are already in the Bazel Central Registry (BCR) I did that. The http_archives are ones that currently don't have a corresponding BCR module.

The nanobind was an exception where a module exists in the BCR, but that variant doesn't work for our usecase at the moment.

I've clarified the comment.

@aaronmondal aaronmondal force-pushed the add-bzlmod-support branch 3 times, most recently from fb44deb to 8bdeb5f Compare February 14, 2025 12:35
This change implements the following flags and provides the
infrastructure for future additions:

    bazel query 'kind(".*_flag", @llvm-project//config:all)'
    @llvm-project//config:LLVM_ENABLE_BACKTRACES
    @llvm-project//config:LLVM_ENABLE_CRASH_DUMPS
    @llvm-project//config:LLVM_ENABLE_CRASH_OVERRIDES
    @llvm-project//config:LLVM_ENABLE_DEBUGLOC_COVERAGE_TRACKING
    @llvm-project//config:LLVM_ENABLE_PLUGINS
    @llvm-project//config:LLVM_ENABLE_ZLIB
    @llvm-project//config:LLVM_ENABLE_ZSTD
    @llvm-project//config:LLVM_HAS_LOGF128
    @llvm-project//config:LLVM_WINDOWS_PREFER_FORWARD_SLASH

For instance:

    bazel build ... \
        --@llvm-project//config:LLVM_ENABLE_BACKTRACES=false

The following flags have been moved to mirror CMake and simplify
migration to bzlmod:

    @llvm_zlib//:llvm_enable_zlib
    -> @llvm-project//config:LLVM_ENABLE_ZLIB

    @llvm_zstd//:llvm_enable_zstd
    -> @llvm-project//config:LLVM_ENABLE_ZSTD

The overlay now has platform definitions at `@llvm-project//platform`.
You can use these to cross compile the config headers to see how they'd
look like on other systems. For instance:

    bazel build @llvm-project//llvm:config_h \
        --platforms=@llvm-project//platform:aarch64-unknown-linux-gnu

    bazel build @llvm-project//llvm:llvm-config_h \
        --platforms=@llvm-project//platform:x86_64-pc-win32

The new implementation uses the original CMake templates as source of
truth. This makes it easier to detect and prevent drift as unhandled
substitutions tend to turn into compiler errors.

Saves 16 defines on windows and ~35 defines on other platforms which
previously leaked into the command lines of all targets that depended
transitively on the llvm configuration. For a full build of the overlay
this amounts to ~380k fewer defines.
The workspace build is now gated behind `--config=deprecated_workspace`.

See `utils/bazel/examples` for the new setup instructions.

While not necessarily the most intuitive implementation, this seems to
be the only way retain the flexibility of all potential usecases as of
Bazel 8. The module build supports:

- The in-tree build from within the `utils/bazel` directory.
- The llvm-project cloned into an arbitrary directory (e.g. for local
  development, submodule setups and and Nix users).
- The llvm-project fetched from github via an archive.

Since module overrides are invisible to third-party dependents, every
project that has the llvm project "somewhere" in its dependency tree
needs to create an explicit override in their root module. It's possible
to avoid this inconvenience by creating custom bazel registries, but
only makes sense to do for the next stable tag that contains this commit.

If you need to link against a nonhermetic system variant of an external
dependency you can override the repositories from the
`llvm_project_overlay` extension like this:

```python
'''MODULE.bazel'''
new_local_repository = use_repo_rule(
    "@bazel_tools//tools/build_defs/repo:local.bzl",
    "new_local_repository",
)

new_local_repository(
    name = "zlib-ng",
    path = "xxxx",
    build_file_content = "xxxx",
)

override_repo(llvm_project_overlay, "zlib-ng")
```
@aaronmondal

Copy link
Copy Markdown
Member Author

Note: This is now rebased onto (and dependent on) #126729 to separate flag config changes from the bzlmod changes.

@samkellett

Copy link
Copy Markdown

Any chance that some progress could be made on this? It seems to have stalled for quite a while

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bazel "Peripheral" support tier build system: utils/bazel

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants