If for a source project a contract project exists, then the contract project's TargetPath should be passed to the compiler. This is handled by the SDK by default when `ProduceReferenceAssembly` is true. As dotnet/runtime doesn't use the `ProduceReferenceAssembly` feature yet, a custom target adds the necessary `ReferenceAssembly` metadata to the `TargetPathWithTargetPlatformMoniker` item which then is transformed to references for the compiler. That works fine on the CLI as the `GetTargetPathWithTargetPlatformMoniker` target runs after the ProjectReference to the ContractProject is resolved and its target path is available.
Inside VS the target ordering is different and the `ResolvedMatchingContract` item was empty as the ProjectReference to the contract wasn't yet resolved. The fix for that is to add a dependency onto the `ResolveProjectReferences` target to guarantee that the `ResolvedMatchingContract` item is populated in time.
Noticed this when the build of System.ComponentModel.Composition.Registration failed because the implementation assembly of System.ComponentModel.Composition was passed to the compiler instead of the reference assembly.
<!-- Allow P2Ps that target a source project to build against the corresponding ref project. -->
<Target Name="AnnotateTargetPathWithTargetPlatformMonikerWithReferenceAssembly"
Condition="'$(HasMatchingContract)' == 'true'"
+ DependsOnTargets="ResolveProjectReferences"
AfterTargets="GetTargetPathWithTargetPlatformMoniker">
<ItemGroup>
<TargetPathWithTargetPlatformMoniker ReferenceAssembly="@(ResolvedMatchingContract)" />