* [WPF] Add WpfLightToolkit in the Xamarin Forms Wpf projet
* Delete WpfLightToolkit dependency
* [WPF] Add WpfLightToolkit in the Xamarin Forms Wpf projet
* Delete WpfLightToolkit dependency
Some links about design-time builds:
- https://github.com/dotnet/project-system/blob/master/docs/design-time-builds.md
- https://daveaglick.com/posts/running-a-design-time-build-with-msbuild-apis
In Visual Studio 2017 (Windows), a "design-time" build is what drives
Intellisense in cases such as using `x:Name` in XAML (or
`Resource.designer.cs` in a plain Xamarin.Android app). Improving our
"design-time" build speed will improve general performance in the IDE
such as project load and how long Intellisense takes to update. Since
XamlC is not needed during a design-time build, it is an "easy-win" to
just disable it. XamlC can take a bit of time for projects with a lot
of XAML.
This might also help with: https://github.com/xamarin/Xamarin.Forms/issues/3004
Although we should probably not do anything to specifically support
NCrunch; hopefully, NCrunch is running under the context of a
design-time build.
* [XamlG] builds incrementally, add MSBuild integration tests
Context: https://github.com/xamarin/Xamarin.Forms/pull/2230
The main performance problem with the collection of MSBuild targets in
`Xamarin.Forms.targets` is they don't build incrementally. I addressed
this with `XamlC` using a "stamp" file; however, it is not quite so
easy to setup the same thing with `XamlG`.
They way "incremental" builds are setup in MSBuild, is by specifying
the `Inputs` and `Outputs` of a `<Target />`. MSBuild will partially
build a target when some outputs are not up to date, and skip it
entirely if they are all up to date.
The best docs I can find on MSBuild incremental builds:
https://msdn.microsoft.com/en-us/library/ms171483.aspx
Unfortunately a few things had to happen to make this work for
`XamlG`:
- Define a new target `_FindXamlGFiles` that is invoked before `XamlG`
- `_FindXamlGFiles` defines the `_XamlGInputs` and `_XamlGOutputs`
`<ItemGroup />`'s
- `_FindXamlGFiles` must also define `<Compile />` and `<FileWrites />`,
in case the `XamlG` target is skipped
- `XamlGTask` now needs to get passed in a list of `OutputFiles`,
since we have computed these paths ahead of time
- `XamlGTask` should validate the lengths of `XamlFiles` and
`OutputFiles` match, used error message from MSBuild proper:
a691a44f0e/src/Tasks/Copy.cs (L505)
`XamlG` now builds incrementally!
To give some context on how much improvement we can see with build
times, consider the following command:
msbuild Xamarin.Forms.ControlGallery.Android/Xamarin.Forms.ControlGallery.Android.csproj
If you run it once, it will take a while--this change will not improve
the first build. On the second build with the exact same command, it
*should* be much faster.
Before this commit, the second build on my machine takes:
40.563s
After the change:
23.692s
`XamlG` has cascading impact on build times when it isn't built
incrementally:
- The C# assembly always changes
- Hence, `XamlC` will always run
- Hence, `GenerateJavaStubs` will always run
- Hence, `javac.exe` and `dx.jar` will always run
I am making other improvements like this in Xamarin.Android itself,
that will further improve these times, such as:
https://github.com/xamarin/xamarin-android/pull/1693
~~ New MSBuild Integration Tests ~~
Added some basic MSBuild testing infrastructure:
- Tests write project files to `bin/Debug/temp/TestName`
- Each test has an `sdkStyle` flag for testing the new project system
versus the old one
- `[TearDown]` deletes the entire directory, with a retry for
`IOException` on Windows
- Used the `Microsoft.Build.Locator` NuGet package for locating
`MSBuild.exe` on Windows
- These tests take 2-5 seconds each
So for example, the simplest test, `BuildAProject` writes to
`Xamarin.Forms.Xaml.UnitTests\bin\Debug\temp\BuildAProject(False)\test.csproj`:
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration>Debug</Configuration>
<Platform>AnyCPU</Platform>
<OutputType>Library</OutputType>
<OutputPath>bin\Debug</OutputPath>
<TargetFrameworkVersion>v4.7</TargetFrameworkVersion>
</PropertyGroup>
<ItemGroup>
<Reference Include="mscorlib" />
<Reference Include="System" />
<Reference Include="Xamarin.Forms.Core.dll">
<HintPath>..\..\Xamarin.Forms.Core.dll</HintPath>
</Reference>
<Reference Include="Xamarin.Forms.Xaml.dll">
<HintPath>..\..\Xamarin.Forms.Xaml.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="AssemblyInfo.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Import Project="..\..\..\..\..\.nuspec\Xamarin.Forms.targets" />
<ItemGroup>
<EmbeddedResource Include="MainPage.xaml" />
</ItemGroup>
</Project>
Invokes `msbuild`, and checks the intermediate output for files being
generated.
Tested scenarios:
- Build a simple project
- Build, then build again, and make sure targets were skipped
- Build, then clean, make sure files are gone
- Build, with linked files
- Design-time build
- Call `UpdateDesignTimeXaml` directly
- Build, add a new file, build again
- Build, update timestamp on a file, build again
- XAML file with random XML content
- XAML file with invalid XML content
- A general `EmbeddedResource` that shouldn't go through XamlG
Adding these tests found a bug! `IncrementalClean` was deleting
`XamlC.stamp`. I fixed this by using `<ItemGroup />`, which will be
propery evaluated even if the target is skipped.
~~ Other Changes ~~
- `FilesWrite` is actually supposed to be `FileWrites`, see canonical
source of how `Clean` works and what `FileWrites` is here:
https://github.com/Microsoft/msbuild/issues/2408#issuecomment-321082997
- Moved `DummyBuildEngine` into `MSBuild` directory--makes sense?
maybe don't need to?
- Added a `XamlGDifferentInputOutputLengths` test to check the error
message
- Expanded `DummyBuildEngine` so you can assert against log messages
- Changed a setting in `.Xamarin.Forms.Android.sln` so the unit test
project is built
- My VS IDE monkeyed with a few files, and I kept any *good* (or
relevant) changes: `Xamarin.Forms.UnitTests.csproj`,
`Xamarin.Forms.Xaml.UnitTests\app.config`, etc.
There were some checks for `%(TargetPath)` being blank in the C# code
of `XamlGTask`. In that case it was using `Path.GetRandomFileName`,
but we can't do this if we are setting up inputs and outputs for
`XamlG`. I presume this is from the designer and/or design-time builds
before `DependsOnTargets="PrepareResourceNames"` was added. I tested
design-time builds in VS on Windows, and `$(TargetPath)` was set. To
be sure we don't break anything here, I exclude inputs to `XamlG` if
`%(TargetPath)` is somehow blank.
See relevant MSBuild code for `%(TargetPath)` here:
0515178090/src/Tasks/Microsoft.Common.CurrentVersion.targets (L2822)
~~ Future changes ~~
CssG needs the exact same setup, as it was patterned after `XamlG`.
This should probably be done in a future PR.
* [msbuild] improved lookup of Xamarin.Forms.targets in integration tests
Context: https://devdiv.visualstudio.com/DevDiv/_build?buildId=1717939
Context: https://devdiv.visualstudio.com/DevDiv/_build?buildId=1718306
It looks like the VSTS builds for release branches are running tests
in a staging directory. This means we can't reliably import
`Xamarin.Forms.targets` as what was working locally in the
Xamarin.Forms source tree.
So to fix this:
- Look for `.nuspec/Xamarin.Forms.targets`, at the default location
and then using the `BUILD_SOURCESDIRECTORY` environment variable as
a fallback
- Copy all `*.targets` files to the test directory
- Our `*.csproj` files under test can import the file from there.
We have to copy the targets files here to be sure that MSBuild can
load `Xamarin.Forms.Build.Tasks.dll`, which is also referenced by the
unit tests.
I also made the tests abort earlier if they can't find
`Xamarin.Forms.targets`.
Context: https://github.com/jonathanpeppers/XamarinAndroidBuildTimes
After doing a profiling/review of Xamarin.Android project build times, I
noticed that the `XamlC` target was running on every build no matter
what. The project I used was the Forms Master/Detail template from VS
2017 15.6.4.
In my test repo, I was timing the following situations:
1. Completely clean/fresh build
2. Build again, no changes
3. Change C#, build again
4. Change `AndroidResource` XML, build again
In all cases `XamlC` was running, due to the task not having setup
proper inputs and outputs for the MSBuild target. Thinking about it, it
seemed like we could skip `XamlC` as long as the input assembly did not
change, such as case no. 2 or no. 4.
Changes to the `XamlC` target:
- Setup `$(IntermediateOutputPath)$(TargetFileName)` (the assembly) as input
- Setup a `XamlC.stamp` file as an output
- `<Touch />` the `XamlC.stamp` file after running the `XamlCTask`
- Add to the `FileWrites` MSBuild item, so that the `IncrementalClean`
target doesn't delete the stamp file
On my Windows machine, this improved the following build times for cases:
1. same (XamlC should run)
2. 3.685s -> 2.887s
3. same (XamlC should run) (would also be same as XAML changing)
4. 12.126s -> 11.214s
Since this was basically an empty project, I suspect the improvements
would be more drastic for apps with lots of XAML and using `XamlC`.
* Add demo/test pages for new properties
* Test attributes for new Slider properties
* Implement slider thumb color and thumb image on UWP
* Use nameof for ThumbImage property
* Added GTK Platform and Maps nuspecs
* Added new GTK nuspecs to the solution
* Changes from PR feedback: Renamed Xamarin.Forms.Platform.GTK.nuspec to Xamarin.Forms.GTK.nuspec and discarded changes in the main sln
* Changed Xamarin.Forms.GTK nuspec identifier
* Updated nuspec (copyright year and Platform id)