Bug 59286 - Xamarin.Forms default MSBuild items not handled
Summary: Xamarin.Forms default MSBuild items not handled
Status: RESOLVED FIXED
Alias: None
Product: Xamarin Studio
Classification: Desktop
Component: .NET Core support (show other bugs)
Version: 7.2 (d15-4)
Hardware: PC Mac OS
: Normal normal
Target Milestone: 15.4 SR1
Assignee: Matt Ward
URL:
Depends on:
Blocks:
 
Reported: 2017-09-07 11:44 UTC by Matt Ward
Modified: 2017-10-19 14:35 UTC (History)
11 users (show)

See Also:
Tags: No_Shiproom
Is this bug a regression?: ---
Last known good build:


Attachments

Description Matt Ward 2017-09-07 11:44:06 UTC
Latest Xamarin.Forms nightly builds and the last two 2.4.0.269 previews define their own MSBuild items that should be included by default.

2.4.0.269-pre2 is OK since due to a bug its default items are not added, but pre1 is broken. However a better test is probably the latest Xamarin.Forms nightly, such as 2.4.1.135-nightly

If you use that NuGet package into a .NET Standard 2.0 project and then add a new ContentPage file you will see two problems:

1) Compile Update items added for existing items.

    <Compile Condition=" '$(EnableDefaultCompileItems)' == 'true' " Update="App.xaml.cs">
      <DependentUpon>*.xaml</DependentUpon>
    </Compile>

2) A new MSBuild item is added for the new file even though it is included by default:

    <Compile Update="MyView.xaml.cs">
      <DependentUpon>MyView.xaml</DependentUpon>
    </Compile>
  </ItemGroup>
  <ItemGroup>
    <EmbeddedResource Include="MyView.xaml">
      <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
    </EmbeddedResource>
  </ItemGroup>

3) On reloading the project the new .xaml file is duplicated in the Solution window due to 2)
Comment 1 Matt Ward 2017-09-15 15:24:09 UTC
Repro steps:

1) Create a new .NET Standard 2.0 project.
2) Add Xamarin.Forms 2.4.1.135-nightly from the nightly build NuGet package source:
https://www.myget.org/F/xamarinforms-ci/api/v2
3) Add a ContentPage xaml file to the project.
4) Close and re-open the project.
5) Add a ContentView xaml file to the project.

Expected result:

Project file looks like:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>netstandard2.0</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Xamarin.Forms" Version="2.4.1.135-nightly" />
  </ItemGroup>
  <ItemGroup>
    <None Remove="MyPage.xaml" />
    <None Remove="MyView.xaml" />
  </ItemGroup>
  <ItemGroup>
    <EmbeddedResource Include="MyPage.xaml">
      <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
    </EmbeddedResource>
    <EmbeddedResource Include="MyView.xaml">
      <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
    </EmbeddedResource>
  </ItemGroup>
  <ItemGroup>
    <Compile Update="MyPage.xaml.cs">
      <DependentUpon>MyPage.xaml</DependentUpon>
    </Compile>
    <Compile Update="MyView.xaml.cs">
      <DependentUpon>MyView.xaml</DependentUpon>
    </Compile>
  </ItemGroup>
</Project>

Actual result:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>netstandard2.0</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Xamarin.Forms" Version="2.4.1.135-nightly" />
  </ItemGroup>
  <ItemGroup>
    <None Remove="MyPage.xaml" />
    <None Remove="MyView.xaml" />
  </ItemGroup>
  <ItemGroup>
    <EmbeddedResource Include="MyPage.xaml">
      <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
    </EmbeddedResource>
    <EmbeddedResource Include="MyView.xaml">
      <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
    </EmbeddedResource>
  </ItemGroup>
  <ItemGroup>
    <Compile Update="MyPage.xaml.cs">
      <DependentUpon>*.xaml</DependentUpon>  <!--------- File name changed
    </Compile>
    <Compile Update="MyView.xaml.cs">
      <DependentUpon>MyView.xaml</DependentUpon>
    </Compile>
  </ItemGroup>
</Project>

Also on project reload see duplicate .xaml files in the Solution window.
Also files are no longer nested in the Solution window.
Comment 2 Matt Ward 2017-09-15 15:30:25 UTC
Potentially the expected result in the repro steps in the previous comment should be:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>netstandard2.0</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Xamarin.Forms" Version="2.4.1.135-nightly" />
  </ItemGroup>

</Project>

Since removing the ItemGroups mostly works - the files are not nested but they have the correct BuildActions. Also the Xamarin.Forms NuGet package includes its own MSBuild items that are imported.
Comment 3 Matt Ward 2017-09-15 16:45:02 UTC
The duplicate .xaml files in the Solution window seem to be because the file globs defined by the Xamarin.Forms NuGet package include metadata properties so the glob is ignored in Project.SaveProjectItem:

https://github.com/mono/monodevelop/blob/0718c0e51b296cdd8641b0708bd3ed766c1a49cb/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/Project.cs#L3412

Properties defined are:

{[MSBuildPropertyGroup:
    SubType=Designer
    Generator=MSBuild:UpdateDesignTimeXaml
]}
Comment 4 Luis Aguilera 2017-09-27 14:33:11 UTC
we're going to try to get this fixed for 15.4... we don't have a lot of time left, but let's see if we can get the fix in before Oct 2.
Comment 5 Matt Ward 2017-09-27 15:26:58 UTC
With no files in the project and using Xamarin.Forms 2.4.1.2644, or a nightly build from the CI server, building the project fails in VS Mac with an error about:

error CS0103: The name 'InitializeComponent' does not exist in the current context

Which is because the obj/Debug/netstandard2.0/MyPage.xaml.g.cs file is not being generated:

Target _CoreXamlG:
  Skipping target "_CoreXamlG" because it has no inputs.

MSBuild on the command line works OK and will generate this file:

_CoreXamlG:
  Source: MyPage.xaml
  Language: C#
  AssemblyName: test
  OutputFile obj/Debug/netstandard2.0/test.MyPage.xaml.g.cs
Comment 6 Matt Ward 2017-09-27 16:47:59 UTC
File nesting seems to be broken due to the DependentUpon property being evaluated uses the wildcard information so %(FileName) gets set to "*.xaml" instead of the correct filename.

<Compile Update="**\*.xaml$(DefaultLanguageSourceExtension)" DependentUpon="%(Filename)" SubType="Code" />

The property evaluation is done in the DefaultMSBuildEngine's CreateEvaluatedItem

https://github.com/mono/monodevelop/blob/master/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.MSBuild/DefaultMSBuildEngine.cs#L946

It looks like this evaluation of the properties needs to be done later using the file found that matches the wildcard in the UpdateEvaluatedItem method.

https://github.com/mono/monodevelop/blob/master/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.MSBuild/DefaultMSBuildEngine.cs#L385-L403

A new MSBuildEvaluationContext should be created and SetItemContext called with the file being updated so the correct information is evaluated in GetMetadataValue:

https://github.com/mono/monodevelop/blob/master/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.MSBuild/MSBuildEvaluationContext.cs#L305
Comment 7 Matt Ward 2017-09-28 09:50:39 UTC
Comparing diagnostic msbuild output vs VS Mac build output:

MSBuild:
https://gist.github.com/mrward/b3b2925140a99d8aafd5ec87a8ef5fe8

VS Mac:
https://gist.github.com/mrward/469f9c2b673e3818e5cd7e26c5a66199

VS Mac does not recognise the .xaml file as an EmbeddedResource, it is treated as a None item, which then causes the XamlG to not have any files to process so the MyPage.xaml.g.cs file is not generated.

VSMac:

None
    MyPage.xaml

MSBuild:

EmbeddedResource
    MyPage.xaml
        SubType = Designer
        Generator = MSBuild:UpdateDesignTimeXaml
Comment 8 Matt Ward 2017-09-28 10:48:30 UTC
The build problem seems to be that the MSBuildSDKsPath is not defined when building with VS Mac. This then results in the default items .props and .targets not being imported.

Xamarin.Forms.props:

<Import Project="$(MSBuildThisFileDirectory)Xamarin.Forms.DefaultItems.props" Condition="'$(MSBuildSDKsPath)'!=''" />

Xamarin.Forms.targets:

<Import Project="$(MSBuildThisFileDirectory)Xamarin.Forms.DefaultItems.targets" Condition="'$(MSBuildSDKsPath)'!=''" />

Removing the condition fixes the build error when no files explicitly listed are in the .csproj but the project has a MyPage.xaml and a MyPage.xaml.cs.

MSBuild seems to define the MSBuildSDKsPath property. dotnet cli also defines this property. Note that the dotnet cli build fails due to the Xamarin.Forms NuGet package using an MSBuild type presumably that dotnet cli does not support:

error MSB4062: The "Xamarin.Forms.Build.Tasks.FixedCreateCSharpManifestResourceName" task could not be loaded from the assembly 2.4.0.280/build/netstandard1.0/Xamarin.Forms.Build.Tasks.dll. Could not load file or assembly 'Microsoft.Build.Utilities.v4.0, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'. The system cannot find the file specified.
Comment 9 Matt Ward 2017-09-28 11:09:07 UTC
The MSBuildSdksPath seems to be defined by Mono's MSBuild.dll.config file:

    <msbuildToolsets default="15.0">
      <toolset toolsVersion="15.0">
        ...
        <property name="MSBuildSdksPath" value="$([MSBuild]::GetToolsDirectory32())\Sdks" />

https://gist.github.com/mrward/aa9be7e9ec209f97abf0dbe24fc55882


MonoDevelop.Projects.Formats.MSBuild.exe.config file defines it as property for the import search path:

  <msbuildToolsets default="15.0">
    <toolset toolsVersion="15.0">
      <property name="MSBuildBinPath" value="/Library/Frameworks/Mono.framework/Versions/5.4.0/lib/mono/msbuild/15.0/bin" />
      <property name="MSBuildRuntimeVersion" value="4.0.30319" />
      <property name="MSBuildToolsPath" value="/Library/Frameworks/Mono.framework/Versions/5.4.0/lib/mono/msbuild/15.0/bin" />
      <property name="MSBuildToolsPath32" value="$(MSBuildBinPath)" />
      <property name="MSBuildToolsPath64" value="$(MSBuildBinPath)" />
      <property name="RoslynTargetsPath" value="$(MSBuildToolsPath)\Roslyn" />
      <property name="TargetFrameworkRootPathSearchPathsOSX" value="/Library/Frameworks/Mono.framework/External/xbuild-frameworks/" />
      <property name="VisualStudioVersion" value="15.0" />
      <projectImportSearchPaths>
        <searchPaths os="osx">
          <property name="MSBuildExtensionsPath" value="/Library/Frameworks/Mono.framework/External/xbuild/;/Volumes/SeagateMac/downloads/vsmac-d154-7.2.0.623/Visual Studio.app/Contents/Resources/lib/monodevelop/AddIns/docker/MSbuild" />
          <property name="MSBuildExtensionsPath32" value="/Library/Frameworks/Mono.framework/External/xbuild/" />
          <property name="MSBuildExtensionsPath64" value="/Library/Frameworks/Mono.framework/External/xbuild/" />
          <property name="MSBuildSDKsPath" value="/usr/local/share/dotnet/sdk/2.0.0/Sdks" />
        </searchPaths>
      </projectImportSearchPaths>
    </toolset>

https://gist.github.com/mrward/65eeb2e7fe6b7fdf2a0e1e7cd492d52a

Mono's MSBuild does not define it as property for the project import search paths presumably because this is not needed since it is defined globally.

MSBuild that ships with VS 2017 on Windows also defines the MSBuildSDKsPath property in its MSBuild.exe.config.
Comment 10 Matt Ward 2017-09-29 17:42:40 UTC
Status update:

Branch created with work in progress:

https://github.com/mono/monodevelop/tree/support-xamarin-forms-2.4

Issues (Fixed):

1) InitializeComponent Build error
2) File nesting in Solution window
3) Compile items with DependentUpon being added to project file on saving

Issues (Not yet fixed):

A) MSBuild items added to project file on creating a new .xaml file
   - Causes duplicate files in the Solution window on re-opening the solution.

I suspect there will be some other problems found once A) is fixed - such as custom metadata applied to items where MSBuild update items should be added to the project file.
Comment 11 Matt Ward 2017-10-03 12:52:07 UTC
A) MSBuild items being added to project file on creating a new .xaml file is now fixed on the support-xamarin-forms-2.4 branch.

Testing the branch the following problems have been identified and are not yet fixed. Renaming seems to be problematic independent of using Xamarin.Forms 2.4.

 - Add ContentPage with xaml then change build action to None for .xaml file.
 - Add ContentPage with xaml and then remove .xaml but do not delete .xaml file
 - Add ContentPage with xaml and then remove .xaml.cs file but do not delete .xaml.cs file
 - Add ContentPage with xaml. Then both .xaml and .xaml.cs file removed from the project but not deleted. Then edit .csproj and remove associated MSBuild items
 - Add ContentPage with xaml then rename .xaml file
 - Add ContentPage with xaml then rename .xaml.cs file

More detailed test steps:

https://gist.github.com/mrward/0c6f15ac2d781d1c154b76766e87c505
Comment 12 Matt Ward 2017-10-03 13:10:28 UTC
Opened a pull request against master for the existing changes:

https://github.com/mono/monodevelop/pull/3132
Comment 13 Matt Ward 2017-10-06 09:01:52 UTC
A fix has been merged to master.

  Commit: 92e62d21e7ee36456e6ffcc2b0c700f83b8a8d8f
  Visual Studio Mac 7.4.0.274 (master)

This also requires an update to md-addins otherwise items are still added to the project file when adding a new content page with xaml to the project - this is fixed in:

  Visual Studio Mac 7.4.0.275 (master)

Issues identified in comment 11 remain and will be addressed later on.

This fix will need to be backported to d15-5 and d15-4.
Comment 14 Matt Ward 2017-10-06 10:06:32 UTC
Fix for d15-5:

https://github.com/mono/monodevelop/pull/3159
Comment 15 David Ortinau [MSFT] 2017-10-06 13:53:16 UTC
Thanks Matt, this is looking great! 

I'm on build 281 this morning. 

The only problem I've seen so far is copy/move files from a PCL to the .NET Standard 2.0 project still adds them to the project file and results in the nesting issue, files missing from the solution tree, and an embedded resource error message. 

If I remove the files from the project file it's all fine. I can close and reopen the solution and still fine. Builds, etc.

I didn't see mention in this thread of the copy/move scenario, so wanted to raise it. Adding new files seems fine in my review (after adding the XF nuget that is).

https://www.screencast.com/t/LUvhvBT0
Comment 16 Matt Ward 2017-10-06 15:52:29 UTC
Fix for d15-4:

https://github.com/mono/monodevelop/pull/3164

Not looked at copying/moving files across projects.

Copying/moving works OK if the PCL project is created and a new ContentPage with .xaml file is added to the project using a fixed VS Mac. If you have an existing PCL project then this will not work since the .xaml file does not have the SubType MSBuild property set to Designer. In this case the project model currently decides that the MSBuild item should not have the SubType set, and not use the default from the wildcard provided by the Xamarin.Forms default items, so VS Mac will instead add an Include item. This then causes a duplicate file if the solution is reloaded. This is not great behaviour for Xamarin.Forms 2.4, if we are expecting customers to be copying files from an existing PCL project to a .NET Standard project. I will add some more test scenarios to the gist list - I was planning to create one or more separate bug reports for the remaining issues - probably in VSTS. Some of the scenarios in the gist do not seem to work in VS 2017 on Windows.
Comment 17 David Ortinau [MSFT] 2017-10-06 21:23:20 UTC
Clarification, my screencast shows a Shared Proj scenario. I also just test a PCL and got the same embedded resource error.

/usr/local/share/dotnet/sdk/2.0.0/Sdks/Microsoft.NET.Sdk/build/Microsoft.NET.Sdk.DefaultItems.targets(5,5): Error: Duplicate 'EmbeddedResource' items were included. The .NET SDK includes 'EmbeddedResource' items from your project directory by default. You can either remove these items from your project file, or set the 'EnableDefaultEmbeddedResourceItems' property to 'false' if you want to explicitly include them in your project file. For more information, see https://aka.ms/sdkimplicititems. The duplicate items were: 'App.xaml'; 'WannaPCLPage.xaml' (WannaPCL.Standard)


I'm on master build, VSMac 7.4 Build 281.
Comment 18 Matt Ward 2017-10-10 17:32:02 UTC
The MonoDevelop fixes have been included in d15-5 in commit:

0a9c6a5b6bb0084c0c7dfb03462d22901bfd5657 (d15-5)
VS Mac 7.3.0.690

However the fixes required in md-addins have not yet been merged so adding a new .xaml file will still be broken in the above build since the .xaml file templates have not been updated.
Comment 19 Jacky Waswani 2017-10-11 04:46:21 UTC
This issue have been verified on 15.5 Master builds and Original Issue mentioned in the comment 1 is Fixed and Expected Output was same as mentioned in comment 2

Verified on Build

Build taken from - https://code.internalx.com/Wrench/BuildDetails?buildId=29f4ae3f227bfae30cd77bb79d0822f

Build info
=== Visual Studio Enterprise 2017 for Mac (Preview) ===
Version 7.3 Preview (7.3 build 678)
=== Xamarin.iOS ===
Version: 11.2.0.8 (Visual Studio Enterprise)
=== Xamarin.Android ===
Version: 8.1.0.19 (Visual Studio Enterprise)
=== Xamarin.Mac ===
Version: 4.0.0.80 (Visual Studio Enterprise)
=== Build Information ===

Release ID: 703000678
Git revision: 9e66cbf5c4b4ba91d09daab7ff6385909cf0b6dd
Build date: 2017-10-06 06:14:13-04
Xamarin addins: d3235169df224ab629341d8f571befbf13016f31
Build lane: monodevelop-lion-d15-5-support-xamarin-forms-2.4

Main Scenario tested
-adding a new xaml file and checking duplicates in the solution windows
Bug 59286 is FIXED
-https://screencast.com/t/lziZnnIUwCA

But as this issue needs to tracked down for further investigation , We are not marking this defect as Resolved/Verified Fixed.
Comment 20 Gaurav Ganorkar 2017-10-13 13:01:59 UTC
This issue is no longer reproducible , i have checked it on the D15-4 build

=== Visual Studio Enterprise 2017 for Mac (Preview) ===
Version 7.2 Preview (7.2 build 645)
=== .NET Core ===
Runtime: /usr/local/share/dotnet/dotnet
Runtime Version: 2.0.0
SDK: /usr/local/share/dotnet/sdk/2.0.0/Sdks
SDK Version: 2.0.0
MSBuild SDKs: /Library/Frameworks/Mono.framework/Versions/5.4.1/lib/mono/msbuild/15.0/bin/Sdks
=== Xamarin.iOS ===
Version: 11.4.0.84 (Visual Studio Enterprise)
=== Xamarin.Mac ===
Version: 4.0.0.84 (Visual Studio Enterprise)


Full Build info - https://gist.github.com/GLjackyvaswani/137421d95e1e2282eb019c93bd59f912

Screencast link - https://www.screencast.com/t/wC2AcZd5

Beside this also verified the scenarios that were mentioned in the Comment 11 gist.(https://gist.github.com/mrward/0c6f15ac2d781d1c154b76766e87c505)
Results are mentioned in the trello card- https://trello.com/c/kpogTBSV/107-vsmac-bug-59286-xamarinforms-default-msbuild-items-not-handled
Comment 21 Eduard Schäfer 2017-10-17 12:38:18 UTC
Could you tell when this fix will be released?
I still have the issue mentioned in Comment 17 by David Ortinau in the preview channel.
Comment 22 Matt Ward 2017-10-18 12:36:18 UTC
MonoDevelop fixes are included in commit:

f6a56524685a1ea518401017272f3c80ab68cb5b (monodevelop d15-4)

Requires md-addins reference bump in commit

0e6c9fcf9d49a89f0e2b230c86a132ddf09b0ea1 (monodevelop d15-4)

Above commit corresponds to VS Mac 7.2.1.17
Comment 23 Matt Ward 2017-10-18 12:59:43 UTC
@Eduard - Not sure exactly what you are testing. Visual Studio for Mac 7.3 build 692 that is on the alpha channel only contains one part of the fix. So if you create a .NET Standard project, install the Xamarin.Forms 2.4 NuGet package, then add a new content page with xaml file you will get the duplicate EmbeddedResource items currently since the file template has not been updated so the .xaml file is being added to the project file. I expect a later Visual Studio for Mac 7.3 release on the alpha channel will resolve this.
Comment 24 Eduard Schäfer 2017-10-18 13:04:56 UTC
Thank you for your response. I tried the exact same thing you have described with 7.3 build 692 with Xamarin.Forms 2.4.

I will wait for the next alpha release and will check it again. Do you know when the alpha release is planned?
Comment 25 Matt Ward 2017-10-19 13:00:34 UTC
No definite date for the next alpha release. There is a workaround you can apply to VS for Mac 7.3.0.692 to fix this:

1) Right click the Visual Studio.app file in Finder and select Show Package Contents.
2) Go to the folder: Visual Studio.app/Contents/Resources/lib/monodevelop/AddIns/Xamarin.Forms.Addin
3) Here there are two file xaml file templates you can modify:
   a) Forms-ContentPage-Xaml.xft
   b) Forms-ContentView-Xaml.xft

The change needed in both of these files is to add a SubType="Designer" attribute to the .xaml file. So the Forms-ContentPage-Xaml.xft file would have the following:

		<File name="${Name}.xaml" 
			  DefaultExtension=".xaml" 
			  AddStandardHeader="False" 
			  BuildAction="EmbeddedResource"
			  SubType="Designer"
			  CustomTool="MSBuild:UpdateDesignTimeXaml"
			  src="../Templates/Core/ContentPage.xaml"/>

Once the file is saved then on restarting VS for Mac you should be able to add new xaml files without the project file being modified and breaking the build.
Comment 26 Eduard Schäfer 2017-10-19 14:35:15 UTC
Thanks, worked perfectly.

Note You need to log in before you can comment on or make changes to this bug.