[msbuild][mac][ios] Fix referencing netstandard projects (#2643)

Building a XI or XM (Modern) project that references a netstandard 2.0
project with msbuild fails because of a missing reference to
`netstandard.dll`.

AppDelegate.cs(21,52): error CS0012: The type 'Object' is defined in an assembly that is not referenced. You must add a reference to assembly 'netstandard, Version=2.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51'.

The reason is that XI and XM (Modern) projects have
`$(TargetFrameworkIdentifier) != .NETFramework`, so targets from
`Microsoft.NET.Build.Extensions` which provide ns2.0 support don't get
imported. `ImplicitlyExpandNETStandardFacades` in particular, which
would have added a reference to `netstandard.dll`.

`netstandard.dll` gets included as part of the facades expanded by
`ImplicitlyExpandDesignTimeFacades`, but this gets skipped if the
project does not have a `System.Runtime` dependent reference.

Instead, we want to expand the facades if any reference depends on
`System.Runtime` OR `netstandard`. And for that we scan all the
references for a `netstandard` dependency using the
`GetDependsOnNETStandard` task.

Partially fixes bxc #58504 .
This commit is contained in:
Ankit Jain 2017-09-13 11:39:57 -04:00 коммит произвёл Chris Hamons
Родитель 47713d4e86
Коммит 30f75f722a
2 изменённых файлов: 60 добавлений и 3 удалений

Просмотреть файл

@ -33,13 +33,42 @@ Copyright (c) 2017 Microsoft Corp. (www.microsoft.com)
</PropertyGroup>
<!-- Implicitly references all portable design-time facades if the user is referencing a System.Runtime-based portable library -->
<UsingTask
TaskName="GetDependsOnNETStandard"
Condition="'$(IsXBuild)' != 'true'"
AssemblyFile="$(MSBuildExtensionsPath)\Microsoft\Microsoft.NET.Build.Extensions\tools\net46\Microsoft.NET.Build.Extensions.Tasks.dll" />
<Target Name="ImplicitlyExpandDesignTimeFacades" DependsOnTargets="$(ImplicitlyExpandDesignTimeFacadesDependsOn)">
<ItemGroup>
<XM_CandidateNETStandardReferences Include="@(Reference);@(_ResolvedProjectReferencePaths)" />
<XM_InboxNETStandardFolders Include="$(TargetFrameworkDirectory)" />
</ItemGroup>
<PropertyGroup>
<!-- Does one of our dependencies reference a System.Runtime-based portable library? -->
<_HasReferenceToSystemRuntime Condition="'$(DependsOnSystemRuntime)' == 'true' or '%(_ResolvedProjectReferencePaths.TargetPlatformIdentifier)' == 'Portable'">true</_HasReferenceToSystemRuntime>
<XM_NETStandardInbox Condition="'$(XM_NETStandardInbox)' == '' and Exists('%(XM_InboxNETStandardFolders.Identity)\netstandard.dll')">true</XM_NETStandardInbox>
</PropertyGroup>
<ItemGroup Condition="'$(_HasReferenceToSystemRuntime)' == 'true'">
<!--
Facades are expanded if we have a reference that depends on System.Runtime .
This file is imported for Modern projects, which have have `$(TargetFrameworkIdentifier) != .NETFramework`, so Microsoft.NET.Build.Extensions
(which provides support for ns 2.0 projects) doesn't get imported. And netstandard.dll reference, even if required, doesn't get added.
So, we need to check if any references depend on `netstandard`. And if so, expand the facades, which include netstandard.dll .
If $(_HasReferenceToSystemRuntime) is true, then the facades are going to be expanded anyway, so don't run this.
-->
<GetDependsOnNETStandard
Condition="'$(_HasReferenceToSystemRuntime)' != 'true' and '$(IsXBuild)' != 'true' and '$(DependsOnNETStandard)' == '' and '@(XM_CandidateNETStandardReferences)' != ''"
References="@(XM_CandidateNETStandardReferences)">
<Output TaskParameter="DependsOnNETStandard" PropertyName="XM_DependsOnNETStandard" />
</GetDependsOnNETStandard>
<ItemGroup Condition="'$(_HasReferenceToSystemRuntime)' == 'true' or ('$(XM_NETStandardInbox)' == 'true' and '$(XM_DependsOnNETStandard)' == 'true')">
<_DesignTimeFacadeAssemblies Include="%(DesignTimeFacadeDirectories.Identity)*.dll"/>
<_DesignTimeFacadeAssemblies_Names Include="@(_DesignTimeFacadeAssemblies->'%(FileName)')">

Просмотреть файл

@ -155,14 +155,42 @@ Copyright (C) 2013-2016 Xamarin. All rights reserved.
<Optimize />
</_BundleResourceWithLogicalName>
</ItemDefinitionGroup>
<UsingTask
TaskName="GetDependsOnNETStandard"
Condition="'$(IsXBuild)' != 'true'"
AssemblyFile="$(MSBuildExtensionsPath)\Microsoft\Microsoft.NET.Build.Extensions\tools\net46\Microsoft.NET.Build.Extensions.Tasks.dll" />
<Target Name="ImplicitlyExpandDesignTimeFacades" Condition="'$(ImplicitlyExpandDesignTimeFacades)' == 'true'" DependsOnTargets="$(ImplicitlyExpandDesignTimeFacadesDependsOn)">
<ItemGroup>
<XI_CandidateNETStandardReferences Include="@(Reference);@(_ResolvedProjectReferencePaths)" />
<XI_InboxNETStandardFolders Include="$(TargetFrameworkDirectory)" />
</ItemGroup>
<PropertyGroup>
<_HasReferenceToSystemRuntime Condition="'$(DependsOnSystemRuntime)' == 'true' or '%(_ResolvedProjectReferencePaths.TargetPlatformIdentifier)' == 'Portable'
or '%(ReferenceDependencyPaths.Filename)' == 'System.Runtime'">true</_HasReferenceToSystemRuntime>
<XI_NETStandardInbox Condition="'$(XI_NETStandardInbox)' == '' and Exists('%(XI_InboxNETStandardFolders.Identity)\netstandard.dll')">true</XI_NETStandardInbox>
</PropertyGroup>
<ItemGroup Condition="'$(_HasReferenceToSystemRuntime)' == 'true'">
<!--
Facades are expanded if we have a reference that depends on System.Runtime .
XI projects have `$(TargetFrameworkIdentifier) != .NETFramework`, so Microsoft.NET.Build.Extensions (which provides support for ns 2.0 projects) doesn't get
imported. And netstandard.dll reference, even if required, doesn't get added.
So, we need to check if any references depend on `netstandard`. And if so, expand the facades, which include netstandard.dll .
If $(_HasReferenceToSystemRuntime) is true, then the facades are going to be expanded anyway, so don't run this.
-->
<GetDependsOnNETStandard
Condition="'$(_HasReferenceToSystemRuntime)' != 'true' and '$(IsXBuild)' != 'true' and '$(DependsOnNETStandard)' == '' and '@(XI_CandidateNETStandardReferences)' != ''"
References="@(XI_CandidateNETStandardReferences)">
<Output TaskParameter="DependsOnNETStandard" PropertyName="XI_DependsOnNETStandard" />
</GetDependsOnNETStandard>
<ItemGroup Condition="'$(_HasReferenceToSystemRuntime)' == 'true' or ('$(XI_NETStandardInbox)' == 'true' and '$(XI_DependsOnNETStandard)' == 'true')">
<_DesignTimeFacadeAssemblies Include="%(DesignTimeFacadeDirectories.Identity)*.dll"/>
<ReferencePath Remove="@(_DesignTimeFacadeAssemblies)"/>
<ReferencePath Include="%(_DesignTimeFacadeAssemblies.Identity)">