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

Don't use Targets* helper properties in libs #64500

Merged
merged 2 commits into from
Feb 12, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
1 change: 1 addition & 0 deletions Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -305,5 +305,6 @@
<PropertyGroup>
<CustomBeforeNoTargets>$(RepositoryEngineeringDir)NoTargetsSdk.BeforeTargets.targets</CustomBeforeNoTargets>
<CustomAfterTraversalProps>$(RepositoryEngineeringDir)TraversalSdk.AfterProps.props</CustomAfterTraversalProps>
<CustomAfterTraversalTargets>$(RepositoryEngineeringDir)TraversalSdk.AfterTargets.targets</CustomAfterTraversalTargets>
</PropertyGroup>
</Project>
76 changes: 49 additions & 27 deletions docs/coding-guidelines/project-guidelines.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ Below is a list of all the various options we pivot the project builds on:
## Individual build properties
The following are the properties associated with each build pivot

- `$(BuildTargetFramework) -> Any .NETCoreApp or .NETFramework TFM, e.g. net5.0`
- `$(BuildTargetFramework) -> Any .NETCoreApp or .NETFramework TFM, e.g. net7.0`
- `$(TargetOS) -> Windows | Linux | OSX | FreeBSD | [defaults to running OS when empty]`
- `$(Configuration) -> Release | [defaults to Debug when empty]`
- `$(TargetArchitecture) - x86 | x64 | arm | arm64 | [defaults to x64 when empty]`
Expand All @@ -37,22 +37,18 @@ Each project will define a set of supported TargetFrameworks
<PropertyGroup>
```

- `$(BuildSettings) -> $(BuildTargetFramework)[-$(TargetOS)][-$(Configuration)][-$(TargetArchitecture)]`
- Note this property should be file path safe and thus can be used in file names or directories that need to a unique path for a project configuration.
- The only required Build Settings value is the `$(BuildTargetFramework)` the others are optional.

Example:
Pure netstandard configuration:
Non cross-targeting project that targets .NETStandard:
```
<PropertyGroup>
<TargetFrameworks>netstandard2.0</TargetFrameworks>
<TargetFramework>netstandard2.0</TargetFramework>
<PropertyGroup>
```

All supported targets with unique windows/unix build for netcoreapp:
A cross-targeting project which targets specific platform with `$(NetCoreAppCurrent)` and one .NETFramework tfm:
```
<PropertyGroup>
<TargetFrameworks>$(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent)-Unix;$(NetFrameworkCurrent)</TargetFrameworks>
<TargetFrameworks>$(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent)-Unix;$(NetFrameworkMinimum)</TargetFrameworks>
<PropertyGroup>
```

Expand All @@ -61,15 +57,15 @@ All supported targets with unique windows/unix build for netcoreapp:
A full or individual project build is centered around BuildTargetFramework, TargetOS, Configuration and TargetArchitecture.

1. `$(BuildTargetFramework), $(TargetOS), $(Configuration), $(TargetArchitecture)` can individually be passed in to change the default values.
2. If nothing is passed to the build then we will default value of these properties from the environment. Example: `net5.0-[TargetOS Running On]-Debug-x64`.
3. While Building an individual project from the VS, we build the project for all latest netcoreapp target frameworks.
2. If nothing is passed to the build then we will default value of these properties from the environment. Example: `net7.0-[TargetOS Running On]-Debug-x64`.
3. When building an individual project (either from the CLI or an IDE), all target frameworks are built.

We also have `RuntimeOS` which can be passed to customize the specific OS and version needed for native package builds as well as package restoration. If not passed it will default based on the OS you are running on.

Any of the mentioned properties can be set via `/p:<Property>=<Value>` at the command line. When building using our run tool or any of the wrapper scripts around it (i.e. build.cmd) a number of these properties have aliases which make them easier to pass (run build.cmd/sh -? for the aliases).
Any of the mentioned properties can be set via `/p:<Property>=<Value>` at the command line. When building using any of the wrapper scripts around it (i.e. build.cmd) a number of these properties have aliases which make them easier to pass (run build.cmd/sh -? for the aliases).

## Selecting the correct BuildSettings
When building an individual project the `BuildTargetFramework` and `TargetOS` will be used to select the closest matching TargetFramework listed in the projects `TargetFrameworks` property. The rules used to select the targetFramework will consider compatible target frameworks and OS fallbacks.
When building an individual project the `BuildTargetFramework` and `TargetOS` will be used to select the compatible dependencies which are expressed as ProjectReference items.

## Supported full build settings
- .NET Core latest on current OS (default) -> `$(NetCoreAppCurrent)-[RunningOS]`
Expand All @@ -80,37 +76,64 @@ When building an individual project the `BuildTargetFramework` and `TargetOS` wi
## TargetFramework conditions
`TargetFramework` conditions should be avoided in the first PropertyGroup as that causes DesignTimeBuild issues: https://github.com/dotnet/project-system/issues/6143

1. Use an equality check if the TargetFramework isn't overloaded with the OS portion.
1. Use TargetFrameworkIdentifier to condition on an entire framework to differentiate between .NETCoreApp, .NETStandard and .NETFramework.
Example:
```
<PropertyGroup>
<TargetFrameworks>$(NetCoreAppCurrent);netstandard2.0;$(NetFrameworkMinimum)</TargetFrameworks>
</PropertyGroup>
<ItemGroup Condition="'$(TargetFrameworkIdentifier)' == '.NETCoreApp'">...</ItemGroup>
<ItemGroup Condition="'$(TargetFrameworkIdentifier)' == '.NETStandard'">...</ItemGroup>
<ItemGroup Condition="'$(TargetFrameworkIdentifier)' == '.NETFramework'">...</ItemGroup>
```
2. Use equality checks if you want to condition on specific runtime agnostic target frameworks (i.e. without the `-windows` suffix).
Example:
```
<PropertyGroup>
<TargetFrameworks>netstandard2.0;netstandard2.1</TargetFrameworks>
<TargetFrameworks>$(NetCoreAppCurrent);netstandard2.0;$(NetFrameworkMinimum)</TargetFrameworks>
</PropertyGroup>
<ItemGroup Condition="'$(TargetFramework)' == '$(NetCoreAppCurrent)'">...</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">...</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == '$(NetFrameworkMinimum)'">...</ItemGroup>
```
2. Use a StartsWith when you want to test for multiple .NETStandard or .NETFramework versions.
3. Use the `TargetPlatformIdentifier` property to condition on a .NETCoreApp platform specific target framework. Note that .NETStandard and .NETFramework target frameworks can't be platform specific.
Example:
```
<PropertyGroup>
<TargetFrameworks>netstandard2.0;netstandard2.1</TargetFrameworks>
<TargetFrameworks>$(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent)-OSX;$(NetCoreAppCurrent)</TargetFrameworks>
</PropertyGroup>
<ItemGroup Condition="'$(TargetPlatformIdentifier)' == 'windows'">...</ItemGroup>
<ItemGroup Condition="'$(TargetPlatformIdentifier)' == 'OSX'">...</ItemGroup>
```
Important: In contrast to the old `Targets*` checks, `TargetPlatformIdentifier` conditions apply to a single tfm only, inheritance between target frameworks can't be expressed. See the example below for Unix:
```
<PropertyGroup>
<TargetFrameworks>$(NetCoreAppCurrent)-Unix;$(NetCoreAppCurrent)-Linux;$(NetCoreAppCurrent)-android;$(NetCoreAppCurrent)-windows</TargetFrameworks>
</PropertyGroup>
<ItemGroup Condition="$(TargetFramework.StartsWith('netstandard'))>...</ItemGroup>
<ItemGroup Condition="'$(TargetPlatformIdentifier)' == 'Unix' or '$(TargetPlatformIdentifier)' == 'Linux' or '$(TargetPlatformIdentifier)' == 'android'">...</ItemGroup>
<!-- Negations make such conditions easier to write and read. -->
<ItemGroup Condition="'$(TargetPlatformIdentifier)' != 'windows'">...</ItemGroup>
```
3. Use a StartsWith if the TargetFramework is overloaded with the OS portion.
4. Set the `TargetPlatformIdentifier` property in the project to be able to condition on it in properties in the project file.
That is necessary as the SDK sets the `TargetPlatformIdentifier` in a .targets file after the project is evaluated. Because of that, the property isn't available during the project's evaluation and must be set manually.
Example:
```
<PropertyGroup>
<TargetFrameworks>netstandard2.0-windows;netstandard2.0-Unix</TargetFrameworks>
<TargetFrameworks>$(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent)-android</TargetFrameworks>
</PropertyGroup>
<!-- DesignTimeBuild requires all the TargetFramework Derived Properties to not be present in the first property group. -->
<PropertyGroup>
<TargetPlatformIdentifier>$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)'))</TargetPlatformIdentifier>
akoeplinger marked this conversation as resolved.
Show resolved Hide resolved
<DefineConstants Condition="'$(TargetPlatformIdentifier)' == 'android'">$(DefineConstants);ANDROID_USE_BUFFER</DefineConstants>
</PropertyGroup>
<ItemGroup Condition="$(TargetFramework.StartsWith('netstandard2.0'))>...</ItemGroup>
```
4. Use negations if that makes the conditions easier.
5. Use negations if that makes the conditions easier.
Example:
```
<PropertyGroup>
<TargetFrameworks>netstandard2.0;net462;net472;net5.0</TargetFrameworks>
<TargetFrameworks>$(NetCoreAppCurrent);netstandard2.0;net462</TargetFrameworks>
</PropertyGroup>
<ItemGroup Condition="!$(TargetFramework.StartsWith('net4'))>...</ItemGroup>
<ItemGroup Condition="'$(TargetFrameworkIdentifier)' != '.NETFramework'">...</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' != 'netstandard2.0'">...</ItemGroup>
```

Expand All @@ -119,11 +142,10 @@ Example:
Library projects should use the following directory layout.

```
src\<Library Name>\src - Contains the source code for the library.
src\<Library Name>\gen - Contains source code for the assembly's source generator.
src\<Library Name>\ref - Contains any reference assembly projects for the library.
src\<Library Name>\pkg - Contains package projects for the library.
src\<Library Name>\src - Contains the source code for the library.
src\<Library Name>\tests - Contains the test code for a library.
src\<Library Name>\gen - Contains source code for the assembly's source generator.
```

## ref
Expand Down
19 changes: 18 additions & 1 deletion eng/BeforeTargetFrameworkInference.targets
Original file line number Diff line number Diff line change
@@ -1,5 +1,22 @@
<Project>

<Import Project="$(MSBuildThisDirectory)targetframeworksuffix.props" Condition="'$(DesignTimeBuild)' == 'true'" />
<PropertyGroup>
<TargetPlatformSupported>true</TargetPlatformSupported>
<TargetPlatformVersionSupported>true</TargetPlatformVersionSupported>

<!-- Value of 0.0 produces versionless SupportedOSPlatform attribute.
This is required for platforms not expected to have a version,
and we currently omit the version for all platforms. -->
<SupportedOSPlatformVersion>0.0</SupportedOSPlatformVersion>

<!-- Disable setting a default Windows platform for .NETStandard and .NET Framework libraries.
This ensures that the TargetPlatformIdentifier property is empty for non .NETCoreApp tfms. -->
<_EnableDefaultWindowsPlatform>false</_EnableDefaultWindowsPlatform>
<_targetPlatformIdentifier Condition="$(TargetFramework.Contains('-'))">$(TargetFramework.SubString($([MSBuild]::Add($(TargetFramework.IndexOf('-')), 1))))</_targetPlatformIdentifier>
</PropertyGroup>

<PropertyGroup Condition="'$(_targetPlatformIdentifier)' != '' and '$(_targetPlatformIdentifier)' != 'windows'">
<TargetPlatformVersion>1.0</TargetPlatformVersion>
</PropertyGroup>

</Project>
18 changes: 18 additions & 0 deletions eng/TraversalSdk.AfterTargets.targets
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<Project>

<!-- Uses the Microsoft.DotNet.Build.Tasks.TargetFramework package to filter out target frameworks from ProjectReferences. -->
<PropertyGroup Condition="'$(FilterTraversalProjectReferences)' == 'true'">
<BuildDependsOn>$(BuildDependsOn);ResolveP2PReferences</BuildDependsOn>
<CleanDependsOn>$(CleanDependsOn);ResolveP2PReferences</CleanDependsOn>
<RebuildDependsOn>$(RebuildDependsOn);ResolveP2PReferences</RebuildDependsOn>
<TestDependsOn>$(TestDependsOn);ResolveP2PReferences</TestDependsOn>
<VSTestDependsOn>$(VSTestDependsOn);ResolveP2PReferences</VSTestDependsOn>
<PackDependsOn>$(PackDependsOn);ResolveP2PReferences</PackDependsOn>
<PublishDependsOn>$(PublishDependsOn);ResolveP2PReferences</PublishDependsOn>
</PropertyGroup>

<ItemGroup Condition="'$(FilterTraversalProjectReferences)' == 'true'">
<ProjectReference Update="@(ProjectReference)" SkipGetTargetFrameworkProperties="false" />
</ItemGroup>

</Project>
4 changes: 2 additions & 2 deletions eng/Version.Details.xml
Original file line number Diff line number Diff line change
Expand Up @@ -102,9 +102,9 @@
<Uri>https://github.com/dotnet/arcade</Uri>
<Sha>78eaf78761027d225030be2b28aaf4e8bf392929</Sha>
</Dependency>
<Dependency Name="Microsoft.DotNet.Build.Tasks.TargetFramework" Version="7.0.0-beta.22110.7">
<Dependency Name="Microsoft.DotNet.Build.Tasks.TargetFramework" Version="7.0.0-beta.22111.10">
<Uri>https://github.com/dotnet/arcade</Uri>
<Sha>78eaf78761027d225030be2b28aaf4e8bf392929</Sha>
<Sha>ff6cc4e9c3eef575f62a33a642ca80e79d27c9bb</Sha>
</Dependency>
<Dependency Name="Microsoft.DotNet.RemoteExecutor" Version="7.0.0-beta.22110.7">
<Uri>https://github.com/dotnet/arcade</Uri>
Expand Down
2 changes: 1 addition & 1 deletion eng/Versions.props
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@
<MicrosoftDotNetBuildTasksArchivesVersion>7.0.0-beta.22110.7</MicrosoftDotNetBuildTasksArchivesVersion>
<MicrosoftDotNetBuildTasksInstallersVersion>7.0.0-beta.22110.7</MicrosoftDotNetBuildTasksInstallersVersion>
<MicrosoftDotNetBuildTasksPackagingVersion>7.0.0-beta.22110.7</MicrosoftDotNetBuildTasksPackagingVersion>
<MicrosoftDotNetBuildTasksTargetFrameworkVersion>7.0.0-beta.22110.7</MicrosoftDotNetBuildTasksTargetFrameworkVersion>
<MicrosoftDotNetBuildTasksTargetFrameworkVersion>7.0.0-beta.22111.10</MicrosoftDotNetBuildTasksTargetFrameworkVersion>
<MicrosoftDotNetBuildTasksTemplatingVersion>7.0.0-beta.22110.7</MicrosoftDotNetBuildTasksTemplatingVersion>
<MicrosoftDotNetBuildTasksWorkloadsPackageVersion>7.0.0-beta.22110.7</MicrosoftDotNetBuildTasksWorkloadsPackageVersion>
<MicrosoftDotNetRemoteExecutorVersion>7.0.0-beta.22110.7</MicrosoftDotNetRemoteExecutorVersion>
Expand Down
6 changes: 3 additions & 3 deletions eng/packaging.targets
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@
<PackDependsOn>AddNETStandardCompatErrorFileForPackaging;IncludeAnalyzersInPackage;$(PackDependsOn)</PackDependsOn>
<BeforePack>AddNETStandardCompatErrorFileForPackaging;IncludeAnalyzersInPackage;$(BeforePack)</BeforePack>
<TargetsForTfmSpecificContentInPackage>$(TargetsForTfmSpecificContentInPackage);AddRuntimeSpecificFilesToPackage;IncludeProjectReferencesWithPackAttributeInPackage</TargetsForTfmSpecificContentInPackage>
<IncludeBuildOutput Condition="'$(TargetFrameworkIdentifier)' == '.NETCoreApp' and '$(TargetPlatformIdentifier)' != ''">false</IncludeBuildOutput>
<IncludeBuildOutput Condition="'$(TargetPlatformIdentifier)' != ''">false</IncludeBuildOutput>
<!-- Don't include target platform specific dependencies, since we use the target platform to represent RIDs instead -->
<SuppressDependenciesWhenPacking Condition="'$(TargetFrameworkIdentifier)' == '.NETCoreApp' and '$(TargetPlatformIdentifier)' != ''">true</SuppressDependenciesWhenPacking>
<SuppressDependenciesWhenPacking Condition="'$(TargetPlatformIdentifier)' != ''">true</SuppressDependenciesWhenPacking>
<PackageDesignerMarkerFile>$(MSBuildThisFileDirectory)useSharedDesignerContext.txt</PackageDesignerMarkerFile>
<!-- Generate packages for rid specific projects or for allconfigurations during build. -->
<!-- A package isn't generated if in servicing or in runtimelab. Intended to be overridden at project level. -->
Expand Down Expand Up @@ -101,7 +101,7 @@
DocumentationProjectOutputGroup;
SatelliteDllsProjectOutputGroup;
$(TargetsForTfmSpecificBuildOutput)"
Condition="'$(TargetFrameworkIdentifier)' == '.NETCoreApp' and '$(TargetPlatformIdentifier)' != ''">
Condition="'$(TargetPlatformIdentifier)' != ''">
<PropertyGroup>
<RuntimeSymbolPath>$(TargetDir)$(TargetName).pdb</RuntimeSymbolPath>
<_packageTargetRuntime>$(TargetPlatformIdentifier.ToLowerInvariant().Replace('windows', 'win'))</_packageTargetRuntime>
Expand Down
101 changes: 0 additions & 101 deletions eng/targetframeworksuffix.props

This file was deleted.

Loading