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

Support running tests on the target platform #12719

Closed
wants to merge 1 commit into from

Conversation

ulfjack
Copy link
Contributor

@ulfjack ulfjack commented Dec 17, 2020

This change includes another change by @juliexxia that was previously
merged and rolled back:
c266ac9

This adds an --use_target_platform_for_tests option that changes tests
to use the execution properties from the target platform rather than
the host platform. I believe that the code is currently incorrect -
if the host and target platforms differ, then tests are cross-compiled
for the target platform, but use the execution properties for the host
platform.

This matters for remote execution, where host and target platform may
be different CPU architectures and operating systems (e.g., compiling
on x64 Linux and running on ARM64 Mac). Currently, such tests will
typically fail to run if they contain architecture or OS-specific code.

Progress on #10799.

Change-Id: I774bd4442044d6725e78f496b9991368e73ffa00

This change *includes* another change by @juliexxia that was previously
merged and rolled back:
bazelbuild@c266ac9

This adds an --use_target_platform_for_tests option that changes tests
to use the execution properties from the target platform rather than
the host platform. I believe that the code is currently incorrect -
if the host and target platforms differ, then tests are cross-compiled
for the target platform, but use the execution properties for the host
platform.

This matters for remote execution, where host and target platform may
be different CPU architectures and operating systems (e.g., compiling
on x64 Linux and running on ARM64 Mac). Currently, such tests will
typically fail to run if they contain architecture or OS-specific code.

Progress on bazelbuild#10799.

Change-Id: I774bd4442044d6725e78f496b9991368e73ffa00
@google-cla google-cla bot added the cla: yes label Dec 17, 2020
@ulfjack
Copy link
Contributor Author

ulfjack commented Dec 17, 2020

@juliexxia Would you mind taking a look at this?

@ulfjack
Copy link
Contributor Author

ulfjack commented Dec 17, 2020

Also, does this need a flag? This looks like a bugfix to me, but it may break users that rely on the legacy behavior.

@pcjanzen
Copy link
Contributor

Here's an example use case where the legacy behavior is useful and desired:

Consider an embedded OS target which could never support running a remote worker on its own, but for which we have an emulator. Then, the "test" could be performed by executing the pure target binary in the emulator. The emulator could be described by a toolchain and have different variants for different execution platforms.

In this case we want the execution properties of the host, not the target.

@ulfjack
Copy link
Contributor Author

ulfjack commented Dec 18, 2020

@pcjanzen, I think your use case works even better with the proposed change. IMO, what you're doing is lying to Bazel and then hoping that everything will work out. To me, that doesn't seem like a promising long-term strategy.

For local execution, Bazel could automatically recognize that a given binary requires emulation to run. For example, go run automatically looks for an executable named go_$GOOS_$GOARCH_exec and then runs the underlying binary with that (see https://golang.org/pkg/cmd/go/internal/run/).

If you are using remote execution, the remote execution service could be similarly configured, i.e., it could provide x64 machines with arm64 emulators and route arm64 actions to those and start them under an emulator. You could even provide both emulated and actual hardware and use additional per-rule attributes to select which should be used for what, e.g., run unit tests in an emulator but integration tests on actual hardware.

@pcjanzen
Copy link
Contributor

In our case, our remote execution environment knows nothing of the emulator (or even the target architecture), and we do not want it to; the emulator is provisioned by the client and provided as part of the test action.

I'm not sure that I agree that we are lying to Bazel. We use the documented toolchain resolution mechanism to choose a platform to execute the action, and we expect its execution properties to be the ones associated with that platform. If we wanted the RE service to route the test action to a host that could execute it "natively", we would structure the list of execution platforms differently.

In other words, we're assuming that Bazel treats test actions exactly the same as build actions. You're saying that test actions are fundamentally different, which is certainly a reasonable argument, but it doesn't mean that we are lying to Bazel; there are lots of places where Bazel treats test actions and build actions similarly.

If I understand your proposed change correctly, we would lose the ability to use platform/toolchain resolution to control the execution properties of test actions. This would be unfortunate, because the toolchain mechanism is basically perfectly designed for our use case -- we need to ensure that the emulator binary and the RE properties are aligned.

I am not opposed to this change in general, however, please keep it behind a flag, because we rely on the current behavior.

@ulfjack
Copy link
Contributor Author

ulfjack commented Dec 19, 2020

Ok, let me briefly explain what this change does. Right now, Bazel has a host and target platform; I see these as a model of reality. It uses them to select appropriate toolchains using constraints. In addition, the platforms provide execution properties to be sent to the remote execution system. Note that these properties are completely independent of the constraints. Currently, it always uses the host platform execution properties for all actions (including tests) and ignores any execution properties on the target platform. This means that it is not possible to cross-compile tests and (automatically) run them on appropriate hardware.

With this change, Bazel now uses the target platform execution properties for test actions. Note that this has no effect on toolchain resolution, and toolchain resolution has no effect on execution properties.

That means you should be able to set the target platform execution properties to the same value as the host platform execution properties, and then this should be a no-op for you.

Philosophically, I think that's not a good approach because it introduces inconsistent platform views between Bazel and the remote execution system. I believe that this inconsistency is likely to bite you in the future, maybe not soon, but eventually. For example, if you ever want to run tests on actual hardware rather than on an emulator, your current approach won't work - by design.

If you're using --run_under to provide the emulator, I agree that the current host / target platform model isn't quite able to express that the --run_under binary is actually different from the target platform. Note that Bazel compiles labels for --run_under for the target platform, not the host platform (i.e., building the --run_under tool from source rather than using an existing binary), so if you're using a cross compiler, this option already doesn't work for you. I think the way to handle this would be a separate 'run_under platform'.

@pcjanzen
Copy link
Contributor

Ok, let me briefly explain what this change does. Right now, Bazel has a host and target platform; I see these as a model of reality. It uses them to select appropriate toolchains using constraints. In addition, the platforms provide execution properties to be sent to the remote execution system. Note that these properties are completely independent of the constraints. Currently, it always uses the host platform execution properties for all actions (including tests) and ignores any execution properties on the target platform. This means that it is not possible to cross-compile tests and (automatically) run them on appropriate hardware.

That's a bit of an oversimplification, isn't it? Bazel has one target platform, and then a list of N execution platforms. The host platform is always appended to the end of the list of execution platforms, so it's the one that happens to get used if you don't use "register_execution_platforms" or "--extra_execution_platforms". For each target, Bazel uses the target's exec_compatible_with attribute and its toolchains to select an execution platform. It's the execution properties of the selected execution platform that get sent to RE, for both build and test actions.

This behavior is useful even in the non-cross-compiling case. In any given build, we might have half a dozen different execution platforms: one might have extra memory, another might have GPU hardware, etc. Some of these constraints might be irrelevant for build actions, but necessary to execute some subset of the build's tests.

We cannot just set the target platform properties to the execution platform properties, because there's only one target platform, and many (possibly conflicting) execution platforms.

@ulfjack
Copy link
Contributor Author

ulfjack commented Dec 19, 2020

My understanding is that Bazel selects one platform for each configured target, and within the scope of that target, that becomes the 'target platform'. Hopefully, @juliexxia can clear this up if that's not correct. Yes, different targets may have different platforms, and - in fact - you can also add or override execution properties for each target and (with this change) also for subsets of actions within the target (action groups).

+@gregestren

@pcjanzen
Copy link
Contributor

Maybe we're using different terminology? My understanding is that the 'target platform' is part of the configuration. It starts off with the argument to '--platforms' and thereafter, the only way to change it is to take an explicit configuration transition.

Then, for each configured target, Bazel selects one platform to be the 'execution platform.' The execution platform is therefore much finer-grained than the target platform. With the addition of exec groups, it can become finer still - there can be different execution platforms for different actions created by the target.

But in any case, the execution platform is selected from the list of registered execution platforms, using the toolchain/exec_compatible_with/registered_execution_platforms dance.

@aiuto aiuto requested a review from juliexxia January 6, 2021 04:21
@aiuto aiuto added the team-Configurability platforms, toolchains, cquery, select(), config transitions label Jan 6, 2021
@juliexxia
Copy link
Contributor

Hi Ulf, handing this PR of to @katre since I'm leaving Bazel this week and he has more than enough background on platforms and exec groups.

@katre thanks for taking this, I'd love to see this PR get in which should allow us to close #10799 by way of a better solution.

@juliexxia juliexxia requested review from katre and removed request for juliexxia February 4, 2021 18:14
@juliexxia juliexxia assigned katre and unassigned juliexxia Feb 4, 2021
@ulfjack
Copy link
Contributor Author

ulfjack commented Feb 4, 2021

Hi @katre, it would be great if we could move this forward. There's been a long discussion about exec platforms above, maybe you can clear up our confusion here.

@katre
Copy link
Member

katre commented Feb 4, 2021

Reading the history of both changes and the discussion to get current on this.

@katre
Copy link
Member

katre commented Feb 4, 2021

Okay, first some general background statements to clear up this thread:

  1. Every configured target has a single target platform and one execution platform for every action group. Most targets have only a single action group, and so have only a single execution platform.
  2. The set of available execution platforms is (in order) platforms listed in --extra_execution_platforms, platforms registered in WORKSPACE via register_execution_platforms, and then lastly the host platform (determined from --host_platform, which defaults to @local_config_platform:host).
    a. @local_config_platform:host is slightly magic, in that it tries to determine the host platform's OS and CPU and set the appropriate constraints.
  3. Toolchain resolution is increasingly misnamed, since it actually manages:
    a. Determining and loading the target platform
    b. Determining and loading the execution platform for each action group
    c. Determining the concrete toolchain implementations for each required toolchain type in each action group
    i. The toolchains and execution platform for each action group are selected in concert to ensure the toolchain's execution constraints match.
  4. For remote execution, the execution properties from the execution platform are sent with the RE request, in order for the remote service to correctly configure the worker.
  5. For any legacy rules that do not use toolchains, the host platform will frequently be selected as the execution platform, since it has the fewest constraints.
    a. This means that the execution properties on the host platform will be sent with the RE request.
    b. This leads to many builds needing to "lie" to Bazel about the host platform to send the expected execution properties with each RE request.

Also, we have a currently proposal to unify execution strategy selection with toolchain resolution. When this is implemented, the execution platform will be easier to keep in sync with the execution strategy, especially for remote execution. Unfortunately, we are short on engineer time to make this happen.

@katre
Copy link
Member

katre commented Feb 4, 2021

To get to this actual proposal, using the target platform to execute tests seems incorrect to me, but becomes tricky due to how tests work.

As an example, let's consider an android_test target: the target platform represents an android device. The execution platform is something that has an Android SDK available, and could be executed either on the host platform or a remote platform. The tests, however, need to be run in an emulator (which itself runs on either the host platform or a remote platform).

The easiest way to consider this is that the build phase (which corresponds to the default action group) takes one execution platform, and then test execution (which uses the test action group) takes an execution platform which could be the same as the build, or different, but which is not the target platform. The actual generated test action is something like emulator --image artifact.apk --output log.xml, and this could run on the execution platform.

@katre
Copy link
Member

katre commented Feb 4, 2021

Bazel itself never executes anything on the target platform (bazel run being nominally the exception, except that bazel still doesn't handle execution, that's done by the client shim). Part of the proposal to unify execution strategy with platforms would be to actually remove the exec_properties attribute from the platform rule in favor of a new execution_platform rule that handles this distinction.

@katre
Copy link
Member

katre commented Feb 4, 2021

Final comment (thanks for everyone's patience): there is a clear need to set the execution properties of the platform that tests are executed on. With @juliexxia's change, that is the execution platform of the test action group of the configured target (that's very indirect). I think that we can come up with a way to influence that platform that is similar to this change, but without combining the target and execution platforms (as this PR does). Also, I think it would be beneficial to make this an attribute in the actual BUILD file, instead of a single flag that affects every test target.

My understanding is that, once @juliexxia's change is in place, it will be possible to add new execution properties to a test target like so:

cc_test(
    name = "my_test",
    srcs = [...],
    deps = [...],
    exec_properties = {
        test: {
            "mem": "16G",
        },
    }
)

We could also fairly simply extend the current support for exec_compatible_with on a target to allow adding extra constraints to an execution group (strawman syntax proposal):

cc_test(
    name = "my_test",
    srcs = [...],
    deps = [...],
    exec_compatible_with = {
        test: ["//extra:remote/constraint:enable_networking"],
    }
)

This would allow users to add an attribute to tests in the BUILD file and influence which execution platforms are available for the test execution group, similarly to how the exec_compatible_with attribute currently allows influencing the execution platform for the target as a whole.

(Also, I just noticed that I have been saying "action groups" when I mean to say "execution groups". I appear to have been using outdated terminology).

Final doc links:
Execution groups: https://docs.bazel.build/versions/4.0.0/exec-groups.html
exec_compatible_with: https://docs.bazel.build/versions/4.0.0/toolchains.html#toolchain-resolution (step 2, specifically).

@quval
Copy link
Contributor

quval commented Feb 4, 2021

@katre, thanks for the very detailed explanation! This sounds like what I've been trying to achieve in quval@af02b71 (we've actually been using a version that has this patch for a few weeks now - it looks pretty much like what you outlined). Could you please take a look at that change as well?

Edit: just to be precise - it doesn't allow setting constraints per execution group on a target, and exec_compatible_with stays a label_list. Rather, it allows defining platform properties for execution groups, so the appropriate execution platform can be selected for the test action (i.e., the platform with the constraint can add a test. property, which would be picked up for test actions - after @juliexxia's original change, test actions have this execution group).

@pcjanzen
Copy link
Contributor

pcjanzen commented Feb 4, 2021

I am 100% in support of the proposed extension to exec_compatible_with to allow it to express constraints on a per-execution group basis.

The thing that is tricky is that all execution groups created by cc_test currently use the cc toolchain_type. But the exec_compatible_with constraints for the compile and link actions generated by the cc_toolchain are completely unrelated to the exec_compatible_with constraints for a test action.

If I'm writing my own rule suite in starlark, I can do something like

toolchain(
    name = "my_test_toolchain",
    exec_compatible_with = [
        "@platforms//os:target_os",
        "@platforms//cpu:target_cpu",
    ],
    target_compatible_with = [
        "@platforms//os:target_os",
        "@platforms//cpu:target_cpu",
    ],
    toolchain_type = "//my:test_toolchain_type",
)

my_test = rule(
    _impl,
    exec_groups = {
        "compile”: exec_group(
            toolchains = ["//my:toolchain_type"],
        ),
        “test”: exec_group(
            toolchains = ["//my:test_toolchain_type"],
        ),
    },
)

or at least I could, if bazel magically assigned every test action to the exec group named "test", if it was defined by the corresponding rule. This would allow me to do my compilation actions on the execution platform for the compiler, and the test actions on the target platform.

Extending this concept to native rules is trickier. Is there one global test_toolchain_type, or does every rule-suite need to define its own? Would bazel somehow synthesize default test toolchains?

@katre
Copy link
Member

katre commented Feb 4, 2021

The intent is for both native and Starlark tests to be updated to assign test actions to the test action group. This is hard to automate but should be possible to update manually (if rather extensive).

Instead of using a test toolchain, it's possible to directly specify exec_compatible_with on an execution group when defining a rule:

exec_groups = {
        “test”: exec_group(
            exec_compatible_with = [ "@platforms//os:linux" ]
            toolchains = ["//foo_tools:toolchain_type"],
        ),

Adding a way to do this on a per-target basis is possible but we need to work out the best syntax.

@pcjanzen
Copy link
Contributor

pcjanzen commented Feb 4, 2021

In this case:

exec_groups = {
        “test”: exec_group(
            exec_compatible_with = [ "@platforms//os:linux" ]
            toolchains = ["//foo_tools:toolchain_type"],
        ),

then wouldn't I have to register a toolchain of //foo_tools:toolchain_type (e.g., compiler, linker) for the target platform, even if the target platform is an embedded one that cannot self-host a compiler?

Requiring exec_compatible_with as an attr at rule-definition time might be OK for some use cases, but it makes it really hard to write a rule that might be used in multiple target configurations. As a rule author, I don't want to have to write "foo_linux_test" and "foo_macos_test" and "foo_windows_test".

Having a separate toolchain type for test actions is one idea that would solve both of these problems, but there are probably others.

@katre
Copy link
Member

katre commented Feb 8, 2021

@pcjanzen: Yes, if the exec_group requires a toolchain_type, then one has to exist. However, toolchain_type is not mandatory in the exec_group, so there's no need to add one if it doesn't make sense.

It only rarely makes sense to have OS-type execution constraints on a rule, unless that rule for some reason is only compatible with a given OS. Some of the macOS tooling might fit that, and might not. Many of these are probably better expressed using toolchains (and then only defining toolchains for platforms where they actually exist).

@quval
Copy link
Contributor

quval commented Feb 24, 2021

Hey @katre (and @ulfjack), I'd be happy for any thoughts on what I proposed above. If you'd like, I'd be happy to send this as a separate PR. Thanks!

@katre
Copy link
Member

katre commented Feb 25, 2021

@quval: Sorry I hadn't noticed and replied to that earlier.

Could you please send that as a separate PR, with an example of how it would be used (ie, what a platform with exec groups would look like, and how that would translate into remote exec requests)? Just looking at the commit it's hard for me to see how this actually works, the examples will help clarify it for me.

@quval
Copy link
Contributor

quval commented Feb 25, 2021

@katre: Done (#13110). Hope the description is clear enough. Thanks!

bazel-io pushed a commit that referenced this pull request Mar 5, 2021
When computing exec properties from the execution platform for an action, take into account only the properties that are relevant to the action's exec groups. In particular, allow setting exec properties for arbitrary exec groups on platforms. Previously, any such properties were rejected.

With this change, the following becomes possible:
```
cc_test(
    name = "my_test",
    ...,
    exec_properties = {
        "test.key": "value",
    },
)
```
This will apply `{"key": "value"}` for the test-runner action only (i.e., compilation and linkage won't be affected). The following also becomes possible:
```
platform(
    name = "test_platform",
    constraint_values = [":test_constraint"],
    exec_properties = {
        "test.key": "value",
    },
)

cc_test(
    name = "my_test",
    ...,
    exec_compatible_with = [":test_constraint"],
)
```
This achieves the same in a more succinct way.

For related discussion, see PR #12719 by @ulfjack.

Closes #13110.

PiperOrigin-RevId: 361167318
@ulfjack
Copy link
Contributor Author

ulfjack commented Mar 5, 2021

The use case I'm looking at is where a cc_test is cross-compiled for the target platform. In that case, it should clearly use the target platform for the RE properties. Note that this generally cannot work with local execution. Clearly, this is different from tests that use emulators to execute tests, like android_test.

Annotating tests individually is not an option; even ignoring the amount of manual labor required, it seems like that would require duplicating all cc_test targets for every possible cross-compilation target platform.

It may be that we need a mechanism to annotate in the rule whether it's using an emulator or not? If not, Bazel could automatically use the target platform for the exec platform of the test exec group?

@ulfjack
Copy link
Contributor Author

ulfjack commented Mar 5, 2021

I had a look at #13110 and that seems only tangentially related to my use case. It may provide a workaround for running tests on another platform by explicitly setting "test.key" settings on the general exec platform.

However, this still breaks if a build has both cross-compiled and emulated tests in the same invocation. I understand that this generally won't work on a single machine, but it is a concern for general remote execution. It seems to me that cross-compiled tests should use the target platform as their exec platform, for rules that don't use emulators (like cc_test, but not android_test).

@katre
Copy link
Member

katre commented Mar 8, 2021

The solution isn't to special case tests to use the target platform as the execution platform, but for tests to use multiple exec groups, to have the correct execution platform for building and executing the test.

@ulfjack
Copy link
Contributor Author

ulfjack commented Mar 9, 2021

I don't care all that much about how you want to call these things. What I do care about is this:
How can I get Bazel to pick one exec platform for android_test's test actions and another for cc_test's test actions?

philwo pushed a commit that referenced this pull request Mar 15, 2021
When computing exec properties from the execution platform for an action, take into account only the properties that are relevant to the action's exec groups. In particular, allow setting exec properties for arbitrary exec groups on platforms. Previously, any such properties were rejected.

With this change, the following becomes possible:
```
cc_test(
    name = "my_test",
    ...,
    exec_properties = {
        "test.key": "value",
    },
)
```
This will apply `{"key": "value"}` for the test-runner action only (i.e., compilation and linkage won't be affected). The following also becomes possible:
```
platform(
    name = "test_platform",
    constraint_values = [":test_constraint"],
    exec_properties = {
        "test.key": "value",
    },
)

cc_test(
    name = "my_test",
    ...,
    exec_compatible_with = [":test_constraint"],
)
```
This achieves the same in a more succinct way.

For related discussion, see PR #12719 by @ulfjack.

Closes #13110.

PiperOrigin-RevId: 361167318
philwo pushed a commit that referenced this pull request Mar 15, 2021
When computing exec properties from the execution platform for an action, take into account only the properties that are relevant to the action's exec groups. In particular, allow setting exec properties for arbitrary exec groups on platforms. Previously, any such properties were rejected.

With this change, the following becomes possible:
```
cc_test(
    name = "my_test",
    ...,
    exec_properties = {
        "test.key": "value",
    },
)
```
This will apply `{"key": "value"}` for the test-runner action only (i.e., compilation and linkage won't be affected). The following also becomes possible:
```
platform(
    name = "test_platform",
    constraint_values = [":test_constraint"],
    exec_properties = {
        "test.key": "value",
    },
)

cc_test(
    name = "my_test",
    ...,
    exec_compatible_with = [":test_constraint"],
)
```
This achieves the same in a more succinct way.

For related discussion, see PR #12719 by @ulfjack.

Closes #13110.

PiperOrigin-RevId: 361167318
@AustinSchuhBRT
Copy link

We cherry-picked this into our Bazel and were able to run aarch64 tests from an amd64 machine very nicely using remote execution. Thanks @ulfjack ! I've been wanting to do this for years, very exciting to see it actually work.

katre pushed a commit that referenced this pull request Jul 12, 2021
When computing exec properties from the execution platform for an action, take into account only the properties that are relevant to the action's exec groups. In particular, allow setting exec properties for arbitrary exec groups on platforms. Previously, any such properties were rejected.

With this change, the following becomes possible:
```
cc_test(
    name = "my_test",
    ...,
    exec_properties = {
        "test.key": "value",
    },
)
```
This will apply `{"key": "value"}` for the test-runner action only (i.e., compilation and linkage won't be affected). The following also becomes possible:
```
platform(
    name = "test_platform",
    constraint_values = [":test_constraint"],
    exec_properties = {
        "test.key": "value",
    },
)

cc_test(
    name = "my_test",
    ...,
    exec_compatible_with = [":test_constraint"],
)
```
This achieves the same in a more succinct way.

For related discussion, see PR #12719 by @ulfjack.

Closes #13110.

PiperOrigin-RevId: 361167318
katre pushed a commit to katre/bazel that referenced this pull request Jul 13, 2021
When computing exec properties from the execution platform for an action, take into account only the properties that are relevant to the action's exec groups. In particular, allow setting exec properties for arbitrary exec groups on platforms. Previously, any such properties were rejected.

With this change, the following becomes possible:
```
cc_test(
    name = "my_test",
    ...,
    exec_properties = {
        "test.key": "value",
    },
)
```
This will apply `{"key": "value"}` for the test-runner action only (i.e., compilation and linkage won't be affected). The following also becomes possible:
```
platform(
    name = "test_platform",
    constraint_values = [":test_constraint"],
    exec_properties = {
        "test.key": "value",
    },
)

cc_test(
    name = "my_test",
    ...,
    exec_compatible_with = [":test_constraint"],
)
```
This achieves the same in a more succinct way.

For related discussion, see PR bazelbuild#12719 by @ulfjack.

Closes bazelbuild#13110.

PiperOrigin-RevId: 361167318
defaultValue = "false",
documentationCategory = OptionDocumentationCategory.EXECUTION_STRATEGY,
effectTags = {OptionEffectTag.EXECUTION},
help = "If true, then Bazel will run coverage postprocessing for test in a new spawn.")
Copy link
Contributor

Choose a reason for hiding this comment

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

Is it possible that this help is a copy-paste artifact? It looks to me in need of updating.

@katre
Copy link
Member

katre commented Sep 29, 2021

What's the current status of this PR? It is very out of date and needs to be synced with the main branch. Specifically, most of the test exec group changes are now submitted (and several bugs fixed).

Also, I'm not sure that my earlier feedback has been incorporated. Specifically, I am not convinced that the target platform is appropriate for executing the test. In simple cases this is fine, but as an example, when running an Android test the target platform is an Android device, but the actual test is executed either on a real device or an emulator. In either of these cases, the actual test action can't just execute the APK: either an adb command is executed to send the APK to the real device, or the emulator is started and the APK is sent to that.

I feel that the test exec group needs to be used to execute test actions (that is the point of exec groups in general), and what we really need is better control over what the execution platform for the test exec group is.

@vmrob
Copy link

vmrob commented Oct 12, 2021

I'm also looking at this patch with interest. My use case is similar to the author's: cross compiling on an x86 host architecture for an aarch64 target architecture with both x86 and aarch64 execution platforms available for remote execution. I would like to specifically avoid adding target-level exec_properties to every test as that implies that ever test must have knowledge of all toolchains and platforms it's compatible with.

@katre I think your example is a good one, but conceptually it seems like --platforms=@platforms//os:android isn't the right user control for defining the test platform. I'm not sure how the user transitions api works, exactly, but it seems like you could obviate the need to pass in the platforms flag with a hypothetical android_apk_test rule. It seems like using the host execution platform for tests really only works for test scenarios that leverage sideloading (real or emulated) and that this could be largely addressed by the flagless multi-config stuff on the roadmap.

In the absence of a flag such as --use_target_platform_for_tests, what alternatives are there? It doesn't seem like it's possible to have execution environments that differ significantly from the host without defining target-level exec_properties. Target-level exec properties are probably ok in simple cases such as GPU selection for tests in Tensorflow, but I think it falls short when we look at cross-compilation use cases. Encoding compatible execution platforms at the target level seems like the wrong abstraction when working with portable code/languages.

@keertk
Copy link
Member

keertk commented Dec 7, 2022

Hi there! Thank you for contributing to the Bazel repository. We appreciate your time and effort. We're doing a clean up of old PRs and will be closing this one since it seems to have stalled. Please feel free to reopen/let us know if you’re still interested in pursuing this or if you'd like to discuss anything further. We’ll respond as soon as we have the bandwidth/resources to do so.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
awaiting-user-response Awaiting a response from the author cla: yes team-Configurability platforms, toolchains, cquery, select(), config transitions
Projects
None yet
Development

Successfully merging this pull request may close these issues.