question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

bazel query can lie about external dependency version

See original GitHub issue

Description of the problem / feature request:

bazel query --output build //external:something may print wrong version of something

Bugs: what’s the simplest, easiest way to reproduce this bug? Please provide a minimal example if possible.

WORKSPACE

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

add_skylib()
http_archive(
    name = "bazel_skylib",
    urls = [
        "https://github.com/bazelbuild/bazel-skylib/releases/download/1.0.3/bazel-skylib-1.0.3.tar.gz",
        "https://mirror.bazel.build/github.com/bazelbuild/bazel-skylib/releases/download/1.0.3/bazel-skylib-1.0.3.tar.gz",
    ],
    sha256 = "1c531376ac7e5a180e0237938a2536de0c54d93f5c278634818e0efc952dd56c",
)

a.bzl

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

def add_skylib():
    http_archive(
        name = "bazel_skylib",
        urls = [
            "https://mirror.bazel.build/github.com/bazelbuild/bazel-skylib/releases/download/1.0.2/bazel-skylib-1.0.2.tar.gz",
            "https://github.com/bazelbuild/bazel-skylib/releases/download/1.0.2/bazel-skylib-1.0.2.tar.gz",
        ],
        sha256 = "97e70364e9249702246c0e9444bccdc4b847bed1eb03c5a3ece4f83dfe6abc44",
    )

BUILD: empty file

$ bazel query --output build //external:bazel_skylib
http_archive(
  name = "bazel_skylib",
  urls = ["https://github.com/bazelbuild/bazel-skylib/releases/download/1.0.3/bazel-skylib-1.0.3.tar.gz", "https://mirror.bazel.build/github.com/bazelbuild/bazel-skylib/releases/download/1.0.3/bazel-skylib-1.0.3.tar.gz"],
  sha256 = "1c531376ac7e5a180e0237938a2536de0c54d93f5c278634818e0efc952dd56c",
)

$ cat "`bazel info output_base`/external/bazel_skylib/version.bzl"
...
version = "1.0.2"

Interestingly adding

load("@bazel_skylib//:version.bzl", "version")

to WORKSPACE makes bazel use 1.0.3. Though there also are cases when having

http_archive(name = "foo" ...)
load("@foo//:something.bzl", "something')

fail because some other dependency manages to override/pre-load foo and bazel fails on not finding something.bzl in non-workspace version (can try to create a bigger repro where bazel_skylib is used in WORKSPACE but version is still mismatching between bazel query and actual external dependency)

What operating system are you running Bazel on?

NixOS

What’s the output of bazel info release?

Tried on 3.3.1 and 4.0.0

Issue Analytics

  • State:open
  • Created 3 years ago
  • Comments:12 (11 by maintainers)

github_iconTop GitHub Comments

1reaction
robfigcommented, Nov 3, 2021

We run into this issue a lot in our Bazel usage at my company. It is very frustrating for developers because it seems like an impossible situation is happening – Bazel says a dependency is one version, but the actual code on disk doesn’t match that. In my opinion, this is a major usability problem for larger repos.

1reaction
brandjoncommented, Feb 19, 2021

For what it’s worth, I was digging through this portion of the codebase the other week and it’s implemented roughly as follows:

  1. Break the WORKSPACE file into chunks based on where the load() statements appear.
  2. Evaluate each chunk as its own entity, first populating it with definitions from the previous chunk, and then adding new ones introduced by this chunk. Any time a repo is defined, it replaces any existing repo of the same name in the current chunk, so that the last definition wins within each chunk.
  3. To find the definition for repo foo, scan through all the chunks in order, and take the definition from the first chunk to define foo. This is how you get the “last definition within the first chunk wins” semantics.

Based on that, my guess for the cause of this bug would be that query is using the final state from the last chunk, and not reproducing the behavior of step 3.

These semantics are of course terrible, and I’m not thrilled about the idea of fixing query to match, vs just replacing the whole machinery with something cleaner. (I also had no idea you could do a query over //external, and am unclear on how it’s even able to resolve repos using a separate code path from the normal one.)

Read more comments on GitHub >

github_iconTop Results From Across the Web

Working with External Dependencies - Bazel
Working with External Dependencies ... Bazel can depend on targets from other projects. Dependencies from these other projects are called external dependencies.
Read more >
Query guide - Bazel
This page covers how to get started using Bazel's query language to trace dependencies in your code. For a language details and --output...
Read more >
The Bazel Query Reference
Cycles in the dependency graph; Implicit dependencies; Soundness ... The following are examples of what the Java query string will be:.
Read more >
Query quickstart - Bazel
This tutorial covers how to work with Bazel to trace dependencies in ... This guide runs you through a set of basic queries...
Read more >
Manage external dependencies with Bzlmod - Bazel
The old WORKSPACE -based external dependency system is centered around repositories (or repos), created via repository rules (or repo rules).
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found