How is PlatformTarget assigned?
2024年1月24日In MSBuild, there are two similar properties, PlatformTarget
and Platform
.
Differences between PlatformTarget
and Platform
PlatformTarget
is basically an enum with possible values, AnyCPU, x86, x64, ARM, etc.
Platform
on the other hand is a user-defined value, though it is commonly equal to x86 or x64. Certain Platform
, as a configuration, may set PlatformTarget
[1].
Assigning PlatformTarget
First of all, MSBuild has an option to set project-level properties.
msbuild -property:PlatformTarget=x86
Then, as I said, certain Platform can set PlatformTarget to a value if it chooses to.
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<WarningsAsErrors>NU1605;CS0114</WarningsAsErrors>
<PlatformTarget>x86</PlatformTarget>
</PropertyGroup>
In this snippet, when Platform
is AnyCPU, PlatformTarget
is set to x86.
You can program in the proj file and insert a task that sets PlatformTarget
to your liking.
Next, before calling compiler, Microsoft default targets (C:\Program Files (x86)\dotnet\sdk\3.1.426\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.Sdk.props) may set PlatformTarget
in certain conditions and when PlatformTarget itself is empty.
<PropertyGroup Condition=" '$(_PlatformWithoutConfigurationInference)' == 'x64' ">
<PlatformTarget Condition=" '$(PlatformTarget)' == '' ">x64</PlatformTarget>
</PropertyGroup>
<PropertyGroup Condition=" '$(_PlatformWithoutConfigurationInference)' == 'x86' ">
<PlatformTarget Condition=" '$(PlatformTarget)' == '' ">x86</PlatformTarget>
</PropertyGroup>
<PropertyGroup Condition=" '$(_PlatformWithoutConfigurationInference)' == 'ARM' ">
<PlatformTarget Condition=" '$(PlatformTarget)' == '' ">ARM</PlatformTarget>
</PropertyGroup>
Non-emptiness of PlatformTarget?
In spite of the assignments, PlatformTarget
is not guaranteed to be non-empty. To verify, add a PostBuildEvent and print the value.
<Target Name="Output" AfterTargets="PostBuildEvent">
<Message Text="PlatformTarget = '$(PlatformTarget)'" />
</Target>
MSBuild prints PlatformTarget = ” on my Windows 10.
Is and how is PlatformTarget passed to the compiler? We have to dive into C:\Program Files\dotnet\sdk\3.1.426\Roslyn\Microsoft.CSharp.Core.targets. In the CoreCompile target, Csc task is called and Csc.Platform
receives the value of PlatformTarget.
Is the Csc task compatible with an empty string of PlatformTarget? Yes. The Csc task class inherits the ManagedCompiler class, and latter defines a nullable property Platform.
Also, I notice ManagedCompiler.PlatformWith32BitPreference
sets the property Platform
to “anycpu32bitpreferred” if it is null or empty.
Conclusion
So far, I discovered the trace of the MSBuild property PlatformTarget
and conclude that its value can remain empty throughout the compilation steps. When the value is empty, the compiler itself internally determines the architecture of the binary.
If I have a package or something that depends on the architecture of the output, I’m not able to use PlatformTarget to conditionally import a package in a smart way. That means, I must force users to specify an architecture, or I hard-code it in my csproj file.
参考资料
- Ben Villalobos. Platform vs. PlatformTarget In Any .NET Build. . 2021-09-22 [2024-01-24].↑