How do i override a global variable when using a rule from another workspace?

786 views
Skip to first unread message

Yucong Sun

unread,
May 16, 2022, 10:58:45 PM5/16/22
to bazel-discuss
Hi,

say I have two projects they both use bazel, 

in Project A I have Project B as a git repository 

then in one BUILD files in Project A I use a custom rule defined in Project B

example/BUILD:
load("@repob//1.bzl", "rule1");

rule1(name="xxx", ...)

This works fine, however

in Project B, 
1.bzl uses 

load("//2.bzl", get_global_var)
def rule1():
    v = get_global_var() 

in 2.bzl, it is
PROJECT_NAME = "B"

def get_global_var():
   return PROJECT_NAME

Now, this is a problem for me, because  I actually wanted to set PROJECT_NAME to A , and still use the same rule definition, in project A . But since load() function automatically resolve first argument to Label, I can't even override "2.bzl" locally in Project A to return a different variable. 

What other options do I have? 

Thanks

Alex Humesky

unread,
May 17, 2022, 1:14:16 PM5/17/22
to Yucong Sun, bazel-discuss
It looks like you'll have to either fork or vendor project B to make the changes that you need, or submit code changes to make PROJECT_NAME configurable in project B, or ask the project maintainers to make it configurable. There aren't really any mechanisms in Bazel or Starlark to override variables directly. It's the same situation as having a 3rd party code dependency that has some hardcoded values -- you have to either change the source code to have a different value, or change the code to make it configurable in some way.

--
You received this message because you are subscribed to the Google Groups "bazel-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to bazel-discus...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/bazel-discuss/9d7d5524-88b0-46f9-a435-7288cc2368dan%40googlegroups.com.

Yucong Sun

unread,
May 17, 2022, 1:33:39 PM5/17/22
to Alex Humesky, bazel-discuss
What is the recommended way of making a variable configurable? 

I've found a workaround for project B to use   ctx.workspace_name , and a map to translate from workspace name to variable, but I would rather have a way to supply the variable from project A directly.

Thanks

Alex Humesky

unread,
May 17, 2022, 1:52:31 PM5/17/22
to Yucong Sun, bazel-discuss
That's a good question, but I think it would be up to the maintainers of that library. From the pseudo-code at least, it might be possible to pass in this value through a rule attribute. But there might be some rule-specific or domain-specific considerations on the best way to do it.

Yucong Sun

unread,
May 17, 2022, 2:42:54 PM5/17/22
to Alex Humesky, bazel-discuss
Actually it is not feasible to override this at a rule level,  because the problem is that there are many rules that reuse a common macro that provide this value. The only thing available to that common macro is CTX object,  so th I'm thinking we could basically add a dictionary (maybe workspace_attrs)  next to the workspace_name . before using Project B  , one would clearly see what workspace attribute they have and populate ahead of time instead of doing it through trial and errors.

Alex Humesky

unread,
May 17, 2022, 3:41:34 PM5/17/22
to Yucong Sun, bazel-discuss
You'd mentioned using a git_repository to depend on project B, so I assumed this was a 3rd party dependency, but to clarify, do you control both project A and project B? I'll assume 'yes' for the rest below --

I'm not sure why adding a rule attribute wouldn't work (from a technical perspective. there might be other reasons). You would have to refactor the code to not rely on the common macro and instead get the value from the attribute. The advantage of using a rule is that the value is associated with the target that your building, so that different targets in different projects can set the value, and there's no other configuration needed.

There are other options too. One is to use a Starlark defined flag: https://bazel.build/rules/config#user-defined-build-settings But that would require you to remember to set the flag, or to put it in the .bazelrc. That affects every target in the build though (e.g. you couldn't easily build two different targets that require two different values for that flag).

Another option would be to create a 3rd repository with those configuration values, project C, and have project B depend on project C for those values. E.g. project C might just contain one bzl file with the necessary values. Then in the top-level workspace you can replace project C with a different repo (maybe even a local repo that points into a directory in project A) with a bzl file that redfines those values. The advantage here is that you can set the values on a repo / project level, and don't have to do any command line things or other configuration. The downside is that it's a little circuitous, and you're basically implicitly defining an interface from project C to B that you're overriding.

Reply all
Reply to author
Forward
0 new messages