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

Inherit exec_group setting from build actions when selecting executable #21641

Open
spektrof opened this issue Mar 12, 2024 · 2 comments
Open

Comments

@spektrof
Copy link

Description of the feature request:

Hi,

In our team we are using tools to generate intermediate artifacts, which are used by C++ build and link actions afterwards. These tools have different binaries on different platforms, they are compatible with the platform where they were built and usually with the next major release platform, and generate the same outputs. When it comes to the cross-compilation, we need to make sure that we select the proper binary which is compatible with the execution platform, otherwise it might result an error. We encountered an issue during cross-compilation on rhel8 from a rhel7 host, when a local build action, defined by using the no-remote-exec tag, selected the rhel8 compatible binary and tried to run it on the rhel7 host, but failed. Remote actions run fine.

We'd like to have a feature which allows the executable tools to inherit the execution group setting from their related build actions.

Which category does this issue belong to?

Configurability, Local Execution, Remote Execution

What underlying problem are you trying to solve with this feature?

The executable rule attribute when using cfg="exec" doesn't inherit the execution group from the related build action, e.g. ctx.actions.run().

  attrs = {"tool" : attr.label(mandatory=True, executable=True, cfg="exec")},
  exec_groups = {
    "host" :  exec_group(exec_compatible_with=["@crossbuild//constraint:host"]),
    "rhel7" : exec_group(exec_compatible_with=["@crossbuild//constraint:rhel7"]),
    "rhel8" : exec_group(exec_compatible_with=["@crossbuild//constraint:rhel8"]),
  },
  exec_group = "host" if _has_no_remote_tag(ctx) else _target_platform_to_exec_group(ctx)

  ctx.actions.run(
    inputs = [],
    outputs = [intermediate_executable],
    executable = ctx.executable.tool,
    arguments = [intermediate_executable.path],
    mnemonic = "InterAction",
    progress_message = "Run intermediate action for {}".format(ctx.attr.name),
    execution_requirements = {tag : '1' for tag in ctx.attr.tags},
    exec_group = exec_group,
  )

, when the rhel8 exec_group is set, then I would expect that the tool selects the rhel8 compatible binary.

The executable rule attribute when using cfg="target" doesn't consider the tags when selecting the tool binary.

  attrs = {"tool" : attr.label(mandatory=True, executable=True, cfg="target")},
  exec_groups = {
    "host" :  exec_group(exec_compatible_with=["@crossbuild//constraint:host"]),
    "rhel7" : exec_group(exec_compatible_with=["@crossbuild//constraint:rhel7"]),
    "rhel8" : exec_group(exec_compatible_with=["@crossbuild//constraint:rhel8"]),
  },

when the exec_group is set to host at the build action or having any no-remote execution_requirement, the tool binary will be compatible with the target platform. This might be fine due to the definition of target platform.

Specifying exec_compatible_with at the rule helps when using cfg="exec", however it doesn't support the multi-platform build well because the attribute is non-configurable.

  intermediate_action(
    name = "remote_action",
    tool = select({
      "@crossbuild//config:rhel7" : ["tool_rhel7_bin"],
      "@crossbuild//config:rhel8" : ["tool_rhel8_bin"],
    }),
    exec_compatible_with = select({
      "@crossbuild//config:rhel7" : ["@crossbuild//constraint:rhel7"],
      "@crossbuild//config:rhel8" : ["@crossbuild//constraint:rhel8"],
    }),
  )
ERROR: package contains error: : //:remote_action: attribute "exec_compatible"with" is not configurable

Which operating system are you running Bazel on?

RHEL7

What is the output of bazel info release?

release 6.0.0 (@06deebfb5b73f848de5a0ea0e00fcfaa26788d1f)

If bazel info release returns development version or (@non-git), tell us how you built Bazel.

We build Bazel from source by using an older release, we patch the source code when we really need to.
https://bazel.build/install/compile-source#build-bazel-using-bazel

What's the output of git remote get-url origin; git rev-parse HEAD ?

No response

Have you found anything relevant by searching the web?

https://bazel.build/extending/platforms
https://bazel.build/extending/exec-groups#platform-execution-properties

I didn't find similar use-case with cross-compilation including local only actions yet.

Any other information, logs, or outputs that you want to share?

I have a personal repository which might help to reproduce the problem and check the platform, constraint and rule implementation. Please set the .rc file accordingly.
https://github.com/spektrof/bazel_crossbuild/tree/main

How did I detect the problem?

We were setting both --platforms and --host_platform to the target platform, didn't use any exec_group or exec_compatible_with attribute, this case we didn't even set cfg for the attribute. When I started the cross-compilation on rhel8 from rhel7 host, the tool path has been resolved to the rhel8 compatible binary what it tried to run on rhel7 and failed.

bazel test :test_group1 --config rhel8_host --config rhel8 --config remote

What else did I try?

I tried to set exec_groups for rule with config.exec("target") but I couldn't make it work since it should be non-configurable and don't know how to consider tags there.

I tried to check the implementation of FilesToRunProvider but as far as I saw the executable path selection is separated from execution group, defined by the build action.

I was wondering whether there is a problem in the platform, constraint or rule implementation.

Do you expect these actions to run only locally?
Do you recommend to implement a toolchain for the tool instead?

Thank you very much in advance!

@github-actions github-actions bot added team-Configurability Issues for Configurability team team-Local-Exec Issues and PRs for the Execution (Local) team team-Remote-Exec Issues and PRs for the Execution (Remote) team labels Mar 12, 2024
@sgowroji sgowroji removed team-Local-Exec Issues and PRs for the Execution (Local) team team-Remote-Exec Issues and PRs for the Execution (Remote) team labels Mar 12, 2024
@pcjanzen
Copy link
Contributor

related: #11432 and #19904

@katre
Copy link
Member

katre commented Apr 4, 2024

The executable rule attribute when using cfg="exec" doesn't inherit the execution group from the related build action, e.g. ctx.actions.run().

I don't fully understand what you expect to happen here: execution platforms are chosen before actions are defined, and so cannot inherit from the action. The correct flow is to first define execution groups, then use those execution groups when defining actions.

  attrs = {"tool" : attr.label(mandatory=True, executable=True, cfg="exec")},
  exec_groups = {
    "host" :  exec_group(exec_compatible_with=["@crossbuild//constraint:host"]),
    "rhel7" : exec_group(exec_compatible_with=["@crossbuild//constraint:rhel7"]),
    "rhel8" : exec_group(exec_compatible_with=["@crossbuild//constraint:rhel8"]),
  },

Note that you have four execution groups defined here, host, rhel7, rhel8, and the default execution group (used for the tool attribute, because of cfg = "exec").

I expect that you actually want the tool attribute to use one of the three defined groups. You would do this with a slightly different syntax, using config.exec:

  attrs = {"tool" : attr.label(mandatory=True, executable=True, cfg = config.exec("host"))},

(Or using rhel7, etc, instead of host, depending on what you want.

You may also be interested in automatic execution groups, which lets you avoid manually defining the groups and just lets bazel pick the right execution group for each toolchain you require.

Let me know if this helps you out, or please let me know what part of your problem I have misunderstood.

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

No branches or pull requests

6 participants