Skip to content

Commit 96ea326

Browse files
authored
Document custom reference resolution (#4806)
1 parent a026e7a commit 96ea326

10 files changed

+135
-17
lines changed

build/repo.targets

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,11 @@
6060
<ProjectListFile>$(MSBuildThisFileDirectory)..\eng\ProjectReferences.props</ProjectListFile>
6161
<ProjectListContent>
6262
<![CDATA[
63-
<!-- This file is automatically generated. Run `build.cmd /t:GenerateProjectList` to update. -->
63+
<!--
64+
This file is automatically generated. Run `build.cmd /t:GenerateProjectList` to update.
65+
66+
This file contains a map of assembly names to the projects that build them.
67+
-->
6468
<Project>
6569
<ItemGroup>
6670
@(_ProjectReferenceProvider->'<ProjectReferenceProvider Include="%(Identity)" ProjectPath="%24(RepositoryRoot)%(ProjectFileRelativePath)" />', '%0A ')

docs/README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Contributor documentation
2+
=========================
3+
4+
The primary audience for documentation in this folder is contributors to ASP.NET Core.
5+
If you are looking for documentation on to *use* ASP.NET Core, go to <https://docs.asp.net>.

docs/ReferenceResolution.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
`<Reference>` resolution
2+
========================
3+
4+
Most project files in this repo should use `<Reference>` instead of `<ProjectReference>` or `<PackageReference>`.
5+
This was done to enable ASP.NET Core's unique requirements without requiring most ASP.NET Core contributors
6+
to understand the complex rules for how versions and references should work. The build system will resolve
7+
Reference items to the correct type and version of references based on our servicing and update rules.
8+
9+
See [ResolveReferences.targets](/eng/targets/ResolveReferences.targets) for the exact implementation of custom
10+
`<Reference>` resolutions.
11+
12+
The requirements that led to this system are:
13+
14+
* Versions of external dependencies should be consistent.
15+
* Servicing updates of ASP.NET Core should minimize the number of assemblies which need to re-build and re-ship.
16+
* Newer versions of packages should not have lower dependency versions than previous releases.
17+
* Minimize the cascading effect of servicing updates where possible by keeping a consistent baseline of dependencies.
18+
19+
## Recommendations for writing a .csproj
20+
21+
* Use `<Reference>`
22+
* Do not use `<PackageReference>`
23+
* Only use `<ProjectReference>` in test projects
24+
* Name the .csproj file to match the assembly name.
25+
* Run `build.cmd /t:GenerateProjectList` when adding new projects
26+
* Use [eng/tools/BaseLineGenerator/](/eng/tools/BaselineGenerator/README.md) if you need to update baselines.
27+
28+
## Important files
29+
30+
* [eng/Baseline.xml](/eng/Baseline.xml) - this contains the 'baseline' of the latest servicing release for this branch. It should be modified and used to update the generated file, Baseline.Designer.props.
31+
* [eng/Dependencies.props](/eng/Dependencies.props) - contains a list of all package references that might be used in the repo.
32+
* [eng/PatchConfig.props](/eng/PatchConfig.props) - lists which assemblies or packages are patching in the current build.
33+
* [eng/ProjectReferences.props](/eng/ProjectReferences.props) - lists which assemblies or packages might be available to be referenced as a local project
34+
* [eng/Versions.props](/eng/Versions.props) - contains a list of versions which may be updated by automation.

eng/Baseline.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
<!--
2+
3+
This file contains a list of all the packages and their versions which were released in the last servicing
4+
build of ASP.NET Core 2.1.x. Update this list when preparing for a new patch.
5+
6+
-->
17
<Baseline Version="2.1.6">
28
<Package Id="dotnet-dev-certs" Version="2.1.1" />
39
<Package Id="dotnet-sql-cache" Version="2.1.1" />

eng/Dependencies.props

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,29 @@
1-
<!-- This file is a work in progress as we merge repos and move content here from build/dependencies.props. -->
1+
<!--
22
3+
This file contains a list of all the external dependencies used in ASP.NET Core. These dependencies
4+
are expressed as `<LatestPackageReference>`. These are used as inputs reference resolution, and
5+
may be turned into `<PackageReference>` items in projects.
6+
7+
`<BaselinePackageReference>` items should not be in this file. Those items appear in Baseline.Designer.props
8+
and are generated based on the last package release.
9+
-->
310
<Project>
411
<PropertyGroup>
512
<MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
613
</PropertyGroup>
714

15+
<ItemDefinitionGroup>
16+
<LatestPackageReference>
17+
<!-- Required. Expected to be an exact package version. Wildcards are not allowed. -->
18+
<Version></Version>
19+
</LatestPackageReference>
20+
</ItemDefinitionGroup>
21+
22+
<!-- This import is temporary and necessary while we work on https://github.com/aspnet/AspNetCore/issues/4246. -->
823
<Import Project="dependencies.temp.props" />
924

25+
<!-- These dependencies must use version variables because they may be overriden by ProdCon builds. -->
1026
<ItemGroup Label="ProdCon dependencies">
11-
<!-- These dependencies must use version variables because they may be overriden by ProdCon builds. -->
1227
<LatestPackageReference Include="Microsoft.AspNetCore.BenchmarkRunner.Sources" Version="$(MicrosoftAspNetCoreBenchmarkRunnerSourcesPackageVersion)" />
1328
<LatestPackageReference Include="Microsoft.AspNetCore.Certificates.Generation.Sources" Version="$(MicrosoftAspNetCoreCertificatesGenerationSourcesPackageVersion)" />
1429
<LatestPackageReference Include="Microsoft.AspNetCore.Testing" Version="$(MicrosoftAspNetCoreTestingPackageVersion)" />
@@ -82,13 +97,4 @@
8297
<LatestPackageReference Include="xunit" Version="2.4.0" />
8398
</ItemGroup>
8499

85-
<ItemGroup Condition=" '$(IsTestProject)' == 'true' ">
86-
<Reference Include="Microsoft.AspNetCore.Testing" />
87-
<Reference Include="Microsoft.NET.Test.Sdk" />
88-
<Reference Include="Moq" />
89-
<Reference Include="xunit" />
90-
<Reference Include="xunit.analyzers" />
91-
<Reference Include="xunit.runner.visualstudio" />
92-
</ItemGroup>
93-
94100
</Project>

eng/PatchConfig.props

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,13 @@
1+
<!--
2+
3+
This file contains a list of the package IDs which are patching in a given release.
4+
5+
CAUTION: due to limitations in MSBuild, the format of the PackagesInPatch property is picky.
6+
When adding a new package, make sure the new line ends with a semicolon and starts with a space.
7+
Later on, this will be checked using this condition:
8+
9+
<IsPackageInThisPatch>$(PackagesInPatch.Contains(' $(PackageId);'))</IsPackageInThisPatch>
10+
-->
111
<Project>
212
<PropertyGroup>
313
<MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>

eng/ProjectReferences.props

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
<!-- This file is automatically generated. Run `build.cmd /t:GenerateProjectList` to update. -->
1+
<!--
2+
This file is automatically generated. Run `build.cmd /t:GenerateProjectList` to update.
3+
4+
This file contains a map of assembly names to the projects that build them.
5+
-->
26
<Project>
37
<ItemGroup>
48
<ProjectReferenceProvider Include="Microsoft.AspNetCore" ProjectPath="$(RepositoryRoot)src\DefaultBuilder\src\Microsoft.AspNetCore.csproj" />

eng/Versions.props

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<!--
2+
3+
This file defines the versions of external dependencies used by ASP.NET Core.
4+
This file might be updated by automation.
5+
6+
TODO: move versions from build/dependencies.props into this location. Depends on https://github.com/aspnet/AspNetCore/issues/4246.
7+
-->
8+
<Project />

eng/targets/CSharp.Common.props

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,13 @@
1111
<PackageReference Include="Internal.AspNetCore.Sdk" PrivateAssets="All" Version="$(InternalAspNetCoreSdkPackageVersion)" />
1212
</ItemGroup>
1313

14+
<ItemGroup Condition=" '$(IsTestProject)' == 'true' ">
15+
<Reference Include="Microsoft.AspNetCore.Testing" />
16+
<Reference Include="Microsoft.NET.Test.Sdk" />
17+
<Reference Include="Moq" />
18+
<Reference Include="xunit" />
19+
<Reference Include="xunit.analyzers" />
20+
<Reference Include="xunit.runner.visualstudio" />
21+
</ItemGroup>
22+
1423
</Project>

eng/targets/ResolveReferences.targets

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,21 @@
1+
<!--
2+
3+
The targets in this file are used to implement custom <Reference> resolution.
4+
For more details, see /docs/ReferenceResolution.md.
5+
6+
Properties which can be set by projects. If unset, these will be inferred.
7+
8+
* UseLatestPackageReferences = resolve `<Reference>` items to the latest version of PackageReferences in eng/Dependencies.props.
9+
* UseProjectReferences = prefer project references to packages
10+
* IsProjectReferenceProvider = when true, the assembly in this project should be available as a ProjectReferenceProvider (see below).
11+
12+
Items used by the resolution strategy:
13+
14+
* BaselinePackageReference = a list of packages that were reference in the last release of the project currently building
15+
* LatestPackageReference = a list of the latest versions of packages
16+
* Reference = a list of the references which are needed for compilation or runtime
17+
* ProjectReferenceProvider = a list which maps of assembly names to the project file that produces it
18+
-->
119
<Project>
220

321
<PropertyGroup>
@@ -31,16 +49,22 @@
3149
</PropertyGroup>
3250

3351
<ItemGroup>
52+
<!-- Packages which are implicitly defined by the .NET Core SDK. -->
3453
<_ImplicitPackageReference Include="@(PackageReference->WithMetadataValue('IsImplicitlyDefined', 'true'))" />
54+
<!-- Capture a list of references which were set explicitly in the project. -->
3555
<_ExplicitPackageReference Include="@(PackageReference)" Exclude="@(_ImplicitPackageReference)" />
56+
<!-- Special case: ignore the reference to Internal.AspNetCore.Sdk, which is defined in eng/targets/Cpp.Common.props. -->
3657
<_ExplicitPackageReference Remove="Internal.AspNetCore.Sdk" />
3758

38-
<UnusedProjectReferenceProvider Include="@(ProjectReferenceProvider)" Exclude="@(Reference)" />
59+
<_UnusedProjectReferenceProvider Include="@(ProjectReferenceProvider)" Exclude="@(Reference)" />
3960

40-
<!-- Order matters. Projects should be used when possible instead of packages. -->
61+
<!--
62+
Turn Reference items into a ProjectReference when UseProjectReferences is true.
63+
Order matters. This comes before package resolution because projects should be used when possible instead of packages.
64+
-->
4165
<_ProjectReferenceByAssemblyName Condition="'$(UseProjectReferences)' == 'true'"
4266
Include="@(ProjectReferenceProvider)"
43-
Exclude="@(UnusedProjectReferenceProvider)" />
67+
Exclude="@(_UnusedProjectReferenceProvider)" />
4468

4569
<ProjectReference Include="@(_ProjectReferenceByAssemblyName->'%(ProjectPath)')" />
4670

@@ -51,12 +75,18 @@
5175
<Reference Remove="@(Reference)" />
5276
</ItemGroup>
5377

78+
<!--
79+
This target resolves remaining Referene items to Packages, if possible. If not, they are left as Reference items fo the SDK to resolve.
80+
This executes on NuGet restore and during DesignTimeBuild. It should not run in the outer, cross-targeting build.
81+
-->
5482
<Target Name="ResolveCustomReferences" BeforeTargets="CollectPackageReferences;ResolveAssemblyReferencesDesignTime;ResolveAssemblyReferences" Condition=" '$(TargetFramework)' != '' ">
5583
<ItemGroup>
5684
<Reference Include="@(_ReferenceTemp)" />
5785
<_ReferenceTemp Remove="@(_ReferenceTemp)" />
5886

87+
<!-- Identify if any references were present in the last release of this package, but have been removed. -->
5988
<UnusedBaselinePackageReference Include="@(BaselinePackageReference)" Exclude="@(Reference);@(_ProjectReferenceByAssemblyName)" />
89+
6090
<!--
6191
MSBuild does not provide a way to join on matching identities in a Condition,
6292
but you can do a cartesian product of two item groups and filter out mismatched id's in a second pass.
@@ -101,7 +131,8 @@
101131
<_PrivatePackageReferenceWithVersion Remove="@(_PrivatePackageReferenceWithVersion)" />
102132
<_ImplicitPackageReference Remove="@(_ImplicitPackageReference)" />
103133
</ItemGroup>
104-
<!--
134+
135+
<!-- TODO: when we finish https://github.com/aspnet/AspNetCore/issues/4246, introduce errors to force projects to use custom resolution.
105136
<Error Condition="@(_ExplicitPackageReference->Count()) != 0"
106137
Text="PackageReference items are not allowed. Use &lt;Reference&gt; instead. " /> -->
107138

@@ -117,6 +148,7 @@
117148
Text="Could not resolve this reference. Could not locate the package or project for &quot;%(Reference.Identity)&quot;" />
118149
</Target>
119150

151+
<!-- These targets are used to generate the map of assembly name to project files. See also the /t:GenerateProjectList target in build/repo.targets. -->
120152
<Target Name="GetReferencesProvided" Returns="@(ProvidesReference)">
121153
<ItemGroup>
122154
<_TargetFramework Remove="@(_TargetFramework)" />

0 commit comments

Comments
 (0)