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

Provide a way to explicitly specify a target architecture from the command line. #2576

Closed
tannergooding opened this issue Sep 18, 2020 · 11 comments · Fixed by #3100
Closed

Comments

@tannergooding
Copy link
Member

tannergooding commented Sep 18, 2020

Issue

#2571 updated the logic so that the bitness of the host is used by default in .NET Core. This means that if you run tests from a 32-bit SDK, you will run the tests in 32-bit mode. Likewise, if you run tests from a 64-bit SDK, you will run the tests in 64-bit mode.

This works well if you only have the 32-bit or 64-bit SDK installed, such as if you are using the dotnet-install script in order to validate your code in a CI environment.

However, there may be scenarios where you are running from a particular SDK and you want to run the tests under a different architecture. For example, you may have both the 32-bit and 64-bit SDK installed. In this case, having a command line switch to specify the architecture under which tests should run would be beneficial.

Proposal

Expose a command line switch such as dotnet test --architecture x86.

This provides an escape hatch if the default logic doesn't work as the consumer requires. I would imagine it should support x86, x64, arm, and arm64 as valid and be expanded as needed in the future. This should likely also be tested under Windows on Windows, where you might be running on x64 and have x86 as a valid target or where you might be running on ARM64 and have both ARM and x86 as valid targets.

Other Considerations

It would likely be worthwhile to also document the behavior of this flag when used with a solution. A solution might have a mix of projects, some could be AnyCPU and some could target an explicit architecture. I imagine the most seamless behavior would be to automatically run non-AnyCPU binaries against their target architecture (rather than the specified target architecture), however, one could also imagine skipping or allowing explicit skipping of certain projects as you might be running on x64 but have a single project that targets arm and not have an arm SDK installed.

@ViktorHofer
Copy link
Member

Isn't that already possible with the --runtime switch?

@tannergooding
Copy link
Member Author

@ViktorHofer, the --runtime switch requires you to have built the project for a specific runtime as well.

This would allow you to say run my existing binaries, which are not RID-specific and which are AnyCPU, under a specific host for the current OS.
That is you could just say x64, x86, or arm64; you don't need to have built the project for a specific RID, you don't need to be aware of what a project supports/requires, you don't need to care about windows-, linux-, ubuntu18.04-, etc.

@ViktorHofer
Copy link
Member

ViktorHofer commented Sep 30, 2020

@ViktorHofer, the --runtime switch requires you to have built the project for a specific runtime as well.

You are right, when I invoke dotnet test --runtime X on a test assembly it ignores the value:

PS C:\temp\dotnettestruntime\bin\Debug\net5.0\win-x86> dotnet test .\dotnettestruntime.dll --runtime win-x64
The following arguments have been ignored : "--runtime win-x64"
Microsoft (R) Test Execution Command Line Tool Version 16.8.0
Copyright (c) Microsoft Corporation.  All rights reserved.

Starting test execution, please wait...
A total of 1 test files matched the specified pattern.

Passed!  - Failed:     0, Passed:     1, Skipped:     0, Total:     1, Duration: 3 ms - dotnettestruntime.dll (net5.0)

@tannergooding
Copy link
Member Author

I'd like to call out that I think the following command is important to test: dotnet test -c "$configuration" --no-build --no-restore -v "$verbosity" /bl:"$logFile" /err "$properties" "$solution"

Namely, this is what I use in CI as I will have already run a discreet restore and build step and so I want to use the existing outputs.
I have discreet: restore, build, test, pack steps as I want CI to break these up into easy to diagnose stages that can be tracked and logged individually.
I specify the --no-build, --no-restore, and related options where possible as those stages are known to be complete and there is no point in even running those tasks (which will require up-to-date checks and other things that can add unnecessary time to the CI leg for large solutions).

@ViktorHofer
Copy link
Member

ViktorHofer commented Sep 30, 2020

@tannergooding FWIW, when you invoke a test assembly directly, the --platform switch works:

PS C:\temp\dotnettestruntime\bin\Debug\net5.0\win-x86> dotnet test --platform x86 .\dotnettestruntime.dll
Microsoft (R) Test Execution Command Line Tool Version 16.8.0
Copyright (c) Microsoft Corporation.  All rights reserved.

Starting test execution, please wait...
A total of 1 test files matched the specified pattern.

Passed!  - Failed:     0, Passed:     1, Skipped:     0, Total:     1, Duration: 2 ms - dotnettestruntime.dll (net5.0)

@ViktorHofer
Copy link
Member

ViktorHofer commented Sep 30, 2020

@tannergooding one more thing, would dotnet test --runtime any-x64 satisfy your needs?

EDIT: please disregard. This still requires the application to be built rid specific...

@tannergooding
Copy link
Member Author

I don't want to have to track every output manually. This should work when passing in a solution file and therefore cover all test projects at once with a single invocation.

If I have a project that has 20-40 test projects, I want to be able to say dotnet test --no-build -configuration Debug -platform x86 Name.sln and have it run all test projects under a 32-bit host for the current OS, even if dotnet is the 64-bit SDK (this assumes for it to succeed the 32-bit SDK is also installed).

I should likewise be able to run arm32 or arm64 tests from the x86 SDK (as Windows on ARM currently has a arm32 and x86 emulation layer and will be getting a x64 emulation layer, as was announced today).

@ViktorHofer
Copy link
Member

ViktorHofer commented Sep 30, 2020

@tannergooding one more idea from my side. Can you try this out:

dotnet test --no-restore --no-build -c Debug name.sln -- RunConfiguration.TargetPlatform=x86

@ViktorHofer
Copy link
Member

ViktorHofer commented Sep 30, 2020

@nohwnd Tanner let me know that the above command doesn't work.

dotnet test or dotnet vstest already supports specifying the --platform when invoked on an assembly. I believe --platform should work when invoked on a project/solution when building for AnyCPU and using the emulation layer (as Tanner said above). Also I'm unsure why the RunConfiguration.TargetPlatform setting doesn't work.

@nohwnd
Copy link
Member

nohwnd commented Jan 7, 2021

( I am only talking about .NET Core here )

I've been looking into this for the past few days and the platform switch is mostly ignored. To be more precise it is used only on Windows x86 and x64. The ARM switch there has almost no significance and on Windows it won't result in ARM runtime being forced, instead it will result in x64. Unfortunately there is no history for this functionality because the code is there since the first commit.

The reason why this is so broken is because we only ship win-x86 and win-x64 executables in TestHost nuget package. Because those executables target specific runtime, they will try to resolve it on the system, and thus force the testhost to use the correct runtime.

But there is no win-arm executable (nor win-arm64). So specifying the arm option would have no effect (and nor would arm64). To make this work we would have to ship executables targetting the specific platform. And more so, we would have to ship executable for every combination on every platform.

This is probably not a good way forward.


Taking a step back: Having an executable for the specific runtime is a shortcut to just looking up the runtime yourself. That is the path we take for any other runtime than win-x86 and win-x64. We use the dotnet available in PATH (or take if from the current process if we are running in dotnet executable) and use that. That is also why running tests on arm64 works correctly, and runs as arm64. So the platform is determined by the runtime you use to run those tests. This is okay for a solution that targets a single platform, but not as much if we have multiple platforms.

So for us to make this work without shipping assemblies of all types we need a way to determine the path to the dotnet executable for the correct platform and use that to run the testhost.dll. E.g. on Windows ARM64, when running dotnet test UnitTests1.dll /platform:arm64, I would need to resolve dotnet from C:\Program Files\dotnet, because that is where the Arm64 dotnet is.

Anyone knows about some API that would help me resolve which dotnets I have on my system and getting path to them based on the specified platform?

@tannergooding
Copy link
Member Author

Anyone knows about some API that would help me resolve which dotnets I have on my system and getting path to them based on the specified platform?

CC. @KathleenDollard

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

Successfully merging a pull request may close this issue.

4 participants