Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

config.string with allow_multiple=True should use list for build_setting_default #13817

Closed
Yannic opened this issue Aug 8, 2021 · 6 comments
Closed
Assignees
Labels
P2 We'll consider working on this in future. (Assignee optional) team-Configurability platforms, toolchains, cquery, select(), config transitions type: support / not a bug (process)

Comments

@Yannic
Copy link
Contributor

Yannic commented Aug 8, 2021

I'm trying to migrate a native flag (--protocopt) to a Starlark flag. For this, we need a flag that a) can be supplied multiple times (like with allow_multiple=True - config.string_list doesn't allow this) and b) has an empty default.

Today, it's impossible to get an empty list or a list with multiple elements as ctx.build_setting_value when using config.string with allow_multiple=True.

# foo.bzl

def _impl(ctx):
    pass

foo = rule(
    implementation = _impl,
    build_setting = config.string(flag = True, allow_multiple = True),
)

# BUILD
load(":foo.bzl", "foo")

foo(name="foo", build_setting_default="")  # <-- `ctx.build_setting_value` becomes `[""]`.

There are ways to work around this (i.e. setting build_setting_default to a nonsensical value and checking for ctx.build_setting_value with one element that is the specified default value), but that seems unnecessarily complex.

From a technical perspective, changing the allowed type for build_setting_default when allow_multiple=True looks pretty straight forward to me.

allow_multiple was added in https://cs.opensource.google/bazel/bazel/+/a13f590b69bcbcaa10b1a49bfd9a4607dfbd8f47 after cutting Bazel 4.0.0, so its usage in the wild should be low.

@oquenchil oquenchil added team-Configurability platforms, toolchains, cquery, select(), config transitions type: support / not a bug (process) untriaged labels Aug 20, 2021
@gregestren
Copy link
Contributor

Interesting. Are you comfortable if it still uses the same syntax build_setting_default=""? And that semantically means an empty list?

I get your point, and agree this is worth addressing. I'd want to be cautious to make sure whatever solution doesn't create some unknown other consistency in some other API piece with different expectations.

@fmeum
Copy link
Collaborator

fmeum commented Feb 24, 2022

@gregestren What would you think of allowing both list of <type> and <type> as default values, with the latter continuing to be converted to a singleton list for backwards compatibility? Since there is already a string_list type, having the BuildSetting return a type that dynamically depends on the value of its allowMultiple member may actually not be that much work.

Edit: I now see that the problem is not that BuildSetting can't return a different type, it's that build_setting_default has to go through the usual attr, which does not allow for this kind of fallback behavior.

@fmeum
Copy link
Collaborator

fmeum commented Feb 25, 2022

I ultimately came to the conclusion that the source of issues is that repeatable string flags should be represented as string_list flags with a different CLI argument passing style rather than string flags that conditionally provide a list value. I created #14911 to create a replacement for the current allow_multiple flag that requires significantly less special casing internally and should also be more transparent to users.

@gregestren
Copy link
Contributor

Thanks. I'll take a look. Also cc @aranguyen FYI who's been looking recently at flag parsing logic in general.

@aranguyen
Copy link
Contributor

@fmeum thanks for sending out the proposal. I don't know how to make comments on the proposal you linked so I'm dropping them here instead.

  1. Have you considered what the overriding/accumulating behavior would look like if users do the following bazel build --flag=["a", "b"] --flag=["c", "d"]? Would the final evaluation be --flag=["c", "d"] or would it be --flag=["a", "b", "c", "d"]?
  2. If the answer to the previous question is --flag=["c", "d"]. Would it break for the case of inheritance (test inheriting from build for example)? Some users might want to pass in additional flags for testing.

@fmeum
Copy link
Collaborator

fmeum commented May 3, 2022

@aranguyen My proposal doesn't allow for this syntax, so it (luckily) doesn't have to specify this interaction. My proposal only affects how repeated flags are represented in Starlark, not how they are specified on the command-line: You still either specify a string_list as --flag=first,second (where later occurrences of --flag override all previous occurrences) or as --flag=first --first=second, depending on the flag style. The starlark value would be ["first", "second"] in both cases.

aranguyen pushed a commit to aranguyen/bazel that referenced this issue Jul 20, 2022
For all parts of Bazel other than option parsing, string build setting
flags with `allow_multiple = True` should behave just like `string_list`
settings, even though they are fundamentally of a different type. This
requires a lot of special casing all over the code base and also causes
confusing user-facing behavior when transitioning on such settings.

This commit deprecates the `allow_multiple` named parameter of
`config.string` and as a replacement introduces a new named parameter
`repeatable` on `config.string_list`. Settings with the latter set to True
behave exactly like `string` settings with `allow_multiple = True` with
respect to command-line option parsing and exactly like ordinary
`string_list` flags in all other situations.

Fixes bazelbuild#13817

Closes bazelbuild#14911.

PiperOrigin-RevId: 462146752
Change-Id: I91ddc4328a1b2244f4303fcda7b4228b182a5d56
aranguyen pushed a commit to aranguyen/bazel that referenced this issue Jul 20, 2022
For all parts of Bazel other than option parsing, string build setting
flags with `allow_multiple = True` should behave just like `string_list`
settings, even though they are fundamentally of a different type. This
requires a lot of special casing all over the code base and also causes
confusing user-facing behavior when transitioning on such settings.

This commit deprecates the `allow_multiple` named parameter of
`config.string` and as a replacement introduces a new named parameter
`repeatable` on `config.string_list`. Settings with the latter set to True
behave exactly like `string` settings with `allow_multiple = True` with
respect to command-line option parsing and exactly like ordinary
`string_list` flags in all other situations.

Fixes bazelbuild#13817

Closes bazelbuild#14911.

PiperOrigin-RevId: 462146752
Change-Id: I91ddc4328a1b2244f4303fcda7b4228b182a5d56
ckolli5 pushed a commit to ckolli5/bazel that referenced this issue Jul 21, 2022
For all parts of Bazel other than option parsing, string build setting
flags with `allow_multiple = True` should behave just like `string_list`
settings, even though they are fundamentally of a different type. This
requires a lot of special casing all over the code base and also causes
confusing user-facing behavior when transitioning on such settings.

This commit deprecates the `allow_multiple` named parameter of
`config.string` and as a replacement introduces a new named parameter
`repeatable` on `config.string_list`. Settings with the latter set to True
behave exactly like `string` settings with `allow_multiple = True` with
respect to command-line option parsing and exactly like ordinary
`string_list` flags in all other situations.

Fixes bazelbuild#13817

Closes bazelbuild#14911.

PiperOrigin-RevId: 462146752
Change-Id: I91ddc4328a1b2244f4303fcda7b4228b182a5d56
sgowroji pushed a commit that referenced this issue Jul 22, 2022
For all parts of Bazel other than option parsing, string build setting
flags with `allow_multiple = True` should behave just like `string_list`
settings, even though they are fundamentally of a different type. This
requires a lot of special casing all over the code base and also causes
confusing user-facing behavior when transitioning on such settings.

This commit deprecates the `allow_multiple` named parameter of
`config.string` and as a replacement introduces a new named parameter
`repeatable` on `config.string_list`. Settings with the latter set to True
behave exactly like `string` settings with `allow_multiple = True` with
respect to command-line option parsing and exactly like ordinary
`string_list` flags in all other situations.

Fixes #13817

Closes #14911.

PiperOrigin-RevId: 462146752
Change-Id: I91ddc4328a1b2244f4303fcda7b4228b182a5d56

Co-authored-by: Fabian Meumertzheim <fabian@meumertzhe.im>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
P2 We'll consider working on this in future. (Assignee optional) team-Configurability platforms, toolchains, cquery, select(), config transitions type: support / not a bug (process)
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants