diff --git a/.gitignore b/.gitignore
index 64a922a868..16afffe74a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -152,3 +152,10 @@ $RECYCLE.BIN/
#################
*.userprefs
*.nugetreferenceswitcher
+
+#################
+## Cake
+#################
+tools/
+.nuget
+artifacts/
diff --git a/.travis.yml b/.travis.yml
index efa277ef1b..af7d5dbebf 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -4,17 +4,8 @@ os:
- osx
mono:
- latest
-solution: Avalonia.travis-mono.sln
-before_install:
- - mkdir -p .nuget
- - wget -O .nuget/nuget.exe https://dist.nuget.org/win-x86-commandline/latest/nuget.exe
-install:
- - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt-get install -y gtk-sharp2 ; fi
- - mono .nuget/nuget.exe restore Avalonia.sln
- - mono .nuget/nuget.exe install xunit.runner.console -Version 2.1.0 -OutputDirectory testrunner
script:
- - xbuild /p:Platform=Mono /p:Configuration=Release Avalonia.sln
- - ./tests/run-tests.sh
+ - ./build.sh --target "Travis" --platform "Mono" --configuration "Release"
notifications:
email: false
webhooks:
diff --git a/NuGet.Config b/NuGet.Config
new file mode 100644
index 0000000000..2a1e0af74d
--- /dev/null
+++ b/NuGet.Config
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/appveyor.yml b/appveyor.yml
index 5b7be0823d..eaa384fac3 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -1,31 +1,27 @@
-version: 1.0.{build}
os: Visual Studio 2015
-before_build:
-- git submodule update --init
-- nuget restore Avalonia.sln
-
+platform:
+- Any CPU
+configuration:
+- Release
environment:
- myget_key:
- secure: XOgD5bJUKNOS2kDDgb+affS4pDcslxALh+xvvnr1Koy0PjXlhILsBdNhxRe0KcNm
-
+ NUGET_API_KEY:
+ secure: Xv89dlP2MSBZKhl1nrWSxqcDgCXB0HRhOd4SWQ+jRJ7QoLxQel5mLTipXM++J3G5
+ NUGET_API_URL: https://www.nuget.org/api/v2/package
+ MYGET_API_KEY:
+ secure: OtVfyN3ErqQrDTnWH2HDfJDlCiu/i4/X4wFmK3ZXXP7HmCiXYPSbTjMPwwdOxRaK
+ MYGET_API_URL: https://www.myget.org/F/avalonia-ci/api/v2/package
install:
- if not exist gtk-sharp-2.12.26.msi appveyor DownloadFile http://download.xamarin.com/GTKforWindows/Windows/gtk-sharp-2.12.26.msi
- msiexec /i gtk-sharp-2.12.26.msi /qn /norestart
- cmd: set PATH=%programfiles(x86)%\GtkSharp\2.12\bin\;%PATH%
-
-cache:
- - gtk-sharp-2.12.26.msi
-
-configuration:
- - Release
-
-after_test:
+before_build:
+- git submodule update --init
+build_script:
+- ps: .\build.ps1 -Target "AppVeyor" -Platform "$env:platform" -Configuration "$env:configuration"
+after_build:
- .\packages\JetBrains.dotMemoryUnit.2.1.20150828.125449\tools\dotMemoryUnit.exe -targetExecutable="%xunit20%\xunit.console.x86.exe" -returnTargetExitCode --"tests\Avalonia.LeakTests\bin\Release\Avalonia.LeakTests.dll"
-- ps: nuget\build-appveyor.ps1
-
+test: off
artifacts:
- - path: nuget\*.nupkg
-
-build:
- project: Avalonia.sln
- verbosity: minimal
+ - path: artifacts\nuget\*.nupkg
+cache:
+ - gtk-sharp-2.12.26.msi
diff --git a/build.cake b/build.cake
new file mode 100644
index 0000000000..e1e8cbb426
--- /dev/null
+++ b/build.cake
@@ -0,0 +1,769 @@
+///////////////////////////////////////////////////////////////////////////////
+// ADDINS
+///////////////////////////////////////////////////////////////////////////////
+
+#addin "nuget:?package=Polly&version=4.2.0"
+#addin "nuget:?package=NuGet.Core&version=2.12.0"
+
+///////////////////////////////////////////////////////////////////////////////
+// TOOLS
+///////////////////////////////////////////////////////////////////////////////
+
+#tool "nuget:?package=xunit.runner.console&version=2.1.0"
+
+///////////////////////////////////////////////////////////////////////////////
+// USINGS
+///////////////////////////////////////////////////////////////////////////////
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using Polly;
+using NuGet;
+
+///////////////////////////////////////////////////////////////////////////////
+// ARGUMENTS
+///////////////////////////////////////////////////////////////////////////////
+
+var target = Argument("target", "Default");
+var platform = Argument("platform", "Any CPU");
+var configuration = Argument("configuration", "Release");
+
+///////////////////////////////////////////////////////////////////////////////
+// CONFIGURATION
+///////////////////////////////////////////////////////////////////////////////
+
+var MainRepo = "AvaloniaUI/Avalonia";
+var MasterBranch = "master";
+var AssemblyInfoPath = File("./src/Shared/SharedAssemblyInfo.cs");
+var ReleasePlatform = "Any CPU";
+var ReleaseConfiguration = "Release";
+var MSBuildSolution = "./Avalonia.sln";
+var XBuildSolution = "./Avalonia.sln";
+
+///////////////////////////////////////////////////////////////////////////////
+// PARAMETERS
+///////////////////////////////////////////////////////////////////////////////
+
+var isPlatformAnyCPU = StringComparer.OrdinalIgnoreCase.Equals(platform, "Any CPU");
+var isPlatformX86 = StringComparer.OrdinalIgnoreCase.Equals(platform, "x86");
+var isPlatformX64 = StringComparer.OrdinalIgnoreCase.Equals(platform, "x64");
+var isLocalBuild = BuildSystem.IsLocalBuild;
+var isRunningOnUnix = IsRunningOnUnix();
+var isRunningOnWindows = IsRunningOnWindows();
+var isRunningOnAppVeyor = BuildSystem.AppVeyor.IsRunningOnAppVeyor;
+var isPullRequest = BuildSystem.AppVeyor.Environment.PullRequest.IsPullRequest;
+var isMainRepo = StringComparer.OrdinalIgnoreCase.Equals(MainRepo, BuildSystem.AppVeyor.Environment.Repository.Name);
+var isMasterBranch = StringComparer.OrdinalIgnoreCase.Equals(MasterBranch, BuildSystem.AppVeyor.Environment.Repository.Branch);
+var isTagged = BuildSystem.AppVeyor.Environment.Repository.Tag.IsTag
+ && !string.IsNullOrWhiteSpace(BuildSystem.AppVeyor.Environment.Repository.Tag.Name);
+var isReleasable = StringComparer.OrdinalIgnoreCase.Equals(ReleasePlatform, platform)
+ && StringComparer.OrdinalIgnoreCase.Equals(ReleaseConfiguration, configuration);
+var isMyGetRelease = !isTagged && isReleasable;
+var isNuGetRelease = isTagged && isReleasable;
+
+///////////////////////////////////////////////////////////////////////////////
+// VERSION
+///////////////////////////////////////////////////////////////////////////////
+
+var version = ParseAssemblyInfo(AssemblyInfoPath).AssemblyVersion;
+
+if (isRunningOnAppVeyor)
+{
+ if (isTagged)
+ {
+ // Use Tag Name as version
+ version = BuildSystem.AppVeyor.Environment.Repository.Tag.Name;
+ }
+ else
+ {
+ // Use AssemblyVersion with Build as version
+ version += "-build" + EnvironmentVariable("APPVEYOR_BUILD_NUMBER") + "-alpha";
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// DIRECTORIES
+///////////////////////////////////////////////////////////////////////////////
+
+var artifactsDir = (DirectoryPath)Directory("./artifacts");
+var nugetRoot = artifactsDir.Combine("nuget");
+
+var dirSuffix = configuration;
+var dirSuffixSkia = (isPlatformAnyCPU ? "x86" : platform) + "/" + configuration;
+var dirSuffixIOS = "iPhone" + "/" + configuration;
+
+var buildDirs =
+ GetDirectories("./src/**/bin/" + dirSuffix) +
+ GetDirectories("./src/**/obj/" + dirSuffix) +
+ GetDirectories("./src/Markup/**/bin/" + dirSuffix) +
+ GetDirectories("./src/Markup/**/obj/" + dirSuffix) +
+ GetDirectories("./src/Android/**/bin/" + dirSuffix) +
+ GetDirectories("./src/Android/**/obj/" + dirSuffix) +
+ GetDirectories("./src/Gtk/**/bin/" + dirSuffix) +
+ GetDirectories("./src/Gtk/**/obj/" + dirSuffix) +
+ GetDirectories("./src/iOS/**/bin/" + dirSuffixIOS) +
+ GetDirectories("./src/iOS/**/obj/" + dirSuffixIOS) +
+ (DirectoryPath)Directory("./src/Skia/Avalonia.Skia.Android/bin/" + dirSuffix) +
+ (DirectoryPath)Directory("./src/Skia/Avalonia.Skia.Android/obj/" + dirSuffix) +
+ (DirectoryPath)Directory("./src/Skia/Avalonia.Skia.Android.TestApp/bin/" + dirSuffix) +
+ (DirectoryPath)Directory("./src/Skia/Avalonia.Skia.Android.TestApp/obj/" + dirSuffix) +
+ (DirectoryPath)Directory("./src/Skia/Avalonia.Skia.Desktop/bin/" + dirSuffixSkia) +
+ (DirectoryPath)Directory("./src/Skia/Avalonia.Skia.Desktop/obj/" + dirSuffixSkia) +
+ (DirectoryPath)Directory("./src/Skia/Avalonia.Skia.iOS/bin/" + dirSuffixIOS) +
+ (DirectoryPath)Directory("./src/Skia/Avalonia.Skia.iOS/obj/" + dirSuffixIOS) +
+ (DirectoryPath)Directory("./src/Skia/Avalonia.Skia.iOS.TestApp/bin/" + dirSuffixIOS) +
+ (DirectoryPath)Directory("./src/Skia/Avalonia.Skia.iOS.TestApp/obj/" + dirSuffixIOS) +
+ GetDirectories("./src/Windows/**/bin/" + dirSuffix) +
+ GetDirectories("./src/Windows/**/obj/" + dirSuffix) +
+ GetDirectories("./tests/**/bin/" + dirSuffix) +
+ GetDirectories("./tests/**/obj/" + dirSuffix) +
+ GetDirectories("./Samples/**/bin/" + dirSuffix) +
+ GetDirectories("./Samples/**/obj/" + dirSuffix);
+
+///////////////////////////////////////////////////////////////////////////////
+// NUGET NUSPECS
+///////////////////////////////////////////////////////////////////////////////
+
+Information("Getting git modules:");
+
+IEnumerable subModules;
+var gitSettings = new ProcessSettings { Arguments = "config --file .gitmodules --get-regexp path", RedirectStandardOutput = true };
+var exitCode = StartProcess("git", gitSettings, out subModules);
+if (exitCode != 0)
+{
+ throw new Exception("Failed to retrieve git submodule paths.");
+}
+
+var ignoredSubModulesPaths = subModules.Select(m =>
+{
+ var path = m.Split(' ')[1];
+ Information(path);
+ return ((DirectoryPath)Directory(path)).FullPath;
+}).ToList();
+
+var normalizePath = new Func(
+ path => path.Replace(System.IO.Path.DirectorySeparatorChar, System.IO.Path.AltDirectorySeparatorChar).ToUpperInvariant());
+
+// Key: Package Id
+// Value is Tuple where Item1: Package Version, Item2: The packages.config file path.
+var packageVersions = new Dictionary>>();
+
+System.IO.Directory.EnumerateFiles(((DirectoryPath)Directory("./src")).FullPath, "packages.config", SearchOption.AllDirectories).ToList().ForEach(fileName =>
+{
+ if (!ignoredSubModulesPaths.Any(i => normalizePath(fileName).Contains(normalizePath(i))))
+ {
+ var file = new PackageReferenceFile(fileName);
+ foreach (PackageReference packageReference in file.GetPackageReferences())
+ {
+ IList> versions;
+ packageVersions.TryGetValue(packageReference.Id, out versions);
+ if (versions == null)
+ {
+ versions = new List>();
+ packageVersions[packageReference.Id] = versions;
+ }
+ versions.Add(Tuple.Create(packageReference.Version.ToString(), fileName));
+ }
+ }
+});
+
+Information("Checking installed NuGet package dependencies versions:");
+
+packageVersions.ToList().ForEach(package =>
+{
+ var packageVersion = package.Value.First().Item1;
+ bool isValidVersion = package.Value.All(x => x.Item1 == packageVersion);
+ if (!isValidVersion)
+ {
+ Information("Error: package {0} has multiple versions installed:", package.Key);
+ foreach (var v in package.Value)
+ {
+ Information("{0}, file: {1}", v.Item1, v.Item2);
+ }
+ throw new Exception("Detected multiple NuGet package version installed for different projects.");
+ }
+});
+
+Information("Setting NuGet package dependencies versions:");
+
+var SerilogVersion = packageVersions["Serilog"].FirstOrDefault().Item1;
+var SplatVersion = packageVersions["Splat"].FirstOrDefault().Item1;
+var SpracheVersion = packageVersions["Sprache"].FirstOrDefault().Item1;
+var SystemReactiveVersion = packageVersions["System.Reactive"].FirstOrDefault().Item1;
+var SkiaSharpVersion = packageVersions["SkiaSharp"].FirstOrDefault().Item1;
+var SharpDXVersion = packageVersions["SharpDX"].FirstOrDefault().Item1;
+var SharpDXDirect2D1Version = packageVersions["SharpDX.Direct2D1"].FirstOrDefault().Item1;
+var SharpDXDXGIVersion = packageVersions["SharpDX.DXGI"].FirstOrDefault().Item1;
+
+Information("Package: Serilog, version: {0}", SerilogVersion);
+Information("Package: Splat, version: {0}", SplatVersion);
+Information("Package: Sprache, version: {0}", SpracheVersion);
+Information("Package: System.Reactive, version: {0}", SystemReactiveVersion);
+Information("Package: SkiaSharp, version: {0}", SkiaSharpVersion);
+Information("Package: SharpDX, version: {0}", SharpDXVersion);
+Information("Package: SharpDX.Direct2D1, version: {0}", SharpDXDirect2D1Version);
+Information("Package: SharpDX.DXGI, version: {0}", SharpDXDXGIVersion);
+
+var SetNuGetNuspecCommonProperties = new Action ((nuspec) => {
+ nuspec.Version = version;
+ nuspec.Authors = new [] { "Avalonia Team" };
+ nuspec.Owners = new [] { "stevenk" };
+ nuspec.LicenseUrl = new Uri("http://opensource.org/licenses/MIT");
+ nuspec.ProjectUrl = new Uri("https://github.com/AvaloniaUI/Avalonia/");
+ nuspec.RequireLicenseAcceptance = false;
+ nuspec.Symbols = false;
+ nuspec.NoPackageAnalysis = true;
+ nuspec.Description = "The Avalonia UI framework";
+ nuspec.Copyright = "Copyright 2015";
+ nuspec.Tags = new [] { "Avalonia" };
+});
+
+var coreLibraries = new string[][]
+{
+ new [] { "./src/", "Avalonia.Animation", ".dll" },
+ new [] { "./src/", "Avalonia.Animation", ".xml" },
+ new [] { "./src/", "Avalonia.Base", ".dll" },
+ new [] { "./src/", "Avalonia.Base", ".xml" },
+ new [] { "./src/", "Avalonia.Controls", ".dll" },
+ new [] { "./src/", "Avalonia.Controls", ".xml" },
+ new [] { "./src/", "Avalonia.DesignerSupport", ".dll" },
+ new [] { "./src/", "Avalonia.DesignerSupport", ".xml" },
+ new [] { "./src/", "Avalonia.Diagnostics", ".dll" },
+ new [] { "./src/", "Avalonia.Diagnostics", ".xml" },
+ new [] { "./src/", "Avalonia.Input", ".dll" },
+ new [] { "./src/", "Avalonia.Input", ".xml" },
+ new [] { "./src/", "Avalonia.Interactivity", ".dll" },
+ new [] { "./src/", "Avalonia.Interactivity", ".xml" },
+ new [] { "./src/", "Avalonia.Layout", ".dll" },
+ new [] { "./src/", "Avalonia.Layout", ".xml" },
+ new [] { "./src/", "Avalonia.Logging.Serilog", ".dll" },
+ new [] { "./src/", "Avalonia.Logging.Serilog", ".xml" },
+ new [] { "./src/", "Avalonia.SceneGraph", ".dll" },
+ new [] { "./src/", "Avalonia.SceneGraph", ".xml" },
+ new [] { "./src/", "Avalonia.Styling", ".dll" },
+ new [] { "./src/", "Avalonia.Styling", ".xml" },
+ new [] { "./src/", "Avalonia.ReactiveUI", ".dll" },
+ new [] { "./src/", "Avalonia.Themes.Default", ".dll" },
+ new [] { "./src/", "Avalonia.Themes.Default", ".xml" },
+ new [] { "./src/Markup/", "Avalonia.Markup", ".dll" },
+ new [] { "./src/Markup/", "Avalonia.Markup", ".xml" },
+ new [] { "./src/Markup/", "Avalonia.Markup.Xaml", ".dll" },
+ new [] { "./src/Markup/", "Avalonia.Markup.Xaml", ".xml" }
+};
+
+var coreLibrariesFiles = coreLibraries.Select((lib) => {
+ return (FilePath)File(lib[0] + lib[1] + "/bin/" + dirSuffix + "/" + lib[1] + lib[2]);
+}).ToList();
+
+var coreLibrariesNuSpecContent = coreLibrariesFiles.Select((file) => {
+ return new NuSpecContent {
+ Source = file.FullPath, Target = "lib/portable-windows8+net45"
+ };
+});
+
+var nuspecNuGetSettingsCore = new []
+{
+ ///////////////////////////////////////////////////////////////////////////////
+ // Avalonia
+ ///////////////////////////////////////////////////////////////////////////////
+ new NuGetPackSettings()
+ {
+ Id = "Avalonia",
+ Dependencies = new []
+ {
+ new NuSpecDependency() { Id = "Serilog", Version = SerilogVersion },
+ new NuSpecDependency() { Id = "Splat", Version = SplatVersion },
+ new NuSpecDependency() { Id = "Sprache", Version = SpracheVersion },
+ new NuSpecDependency() { Id = "System.Reactive", Version = SystemReactiveVersion }
+ },
+ Files = coreLibrariesNuSpecContent.ToList(),
+ BasePath = Directory("./"),
+ OutputDirectory = nugetRoot
+ },
+ ///////////////////////////////////////////////////////////////////////////////
+ // Avalonia.HtmlRenderer
+ ///////////////////////////////////////////////////////////////////////////////
+ new NuGetPackSettings()
+ {
+ Id = "Avalonia.HtmlRenderer",
+ Dependencies = new []
+ {
+ new NuSpecDependency() { Id = "Avalonia", Version = version }
+ },
+ Files = new []
+ {
+ new NuSpecContent { Source = "Avalonia.HtmlRenderer.dll", Target = "lib/portable-windows8+net45" }
+ },
+ BasePath = Directory("./src/Avalonia.HtmlRenderer/bin/" + dirSuffix),
+ OutputDirectory = nugetRoot
+ }
+};
+
+var nuspecNuGetSettingsMobile = new []
+{
+ ///////////////////////////////////////////////////////////////////////////////
+ // Avalonia.Android
+ ///////////////////////////////////////////////////////////////////////////////
+ new NuGetPackSettings()
+ {
+ Id = "Avalonia.Android",
+ Dependencies = new []
+ {
+ new NuSpecDependency() { Id = "Avalonia", Version = version },
+ new NuSpecDependency() { Id = "Avalonia.Skia.Android", Version = version }
+ },
+ Files = new []
+ {
+ new NuSpecContent { Source = "Avalonia.Android.dll", Target = "lib/MonoAndroid10" }
+ },
+ BasePath = Directory("./src/Android/Avalonia.Android/bin/" + dirSuffix),
+ OutputDirectory = nugetRoot
+ },
+ ///////////////////////////////////////////////////////////////////////////////
+ // Avalonia.Skia.Android
+ ///////////////////////////////////////////////////////////////////////////////
+ new NuGetPackSettings()
+ {
+ Id = "Avalonia.Skia.Android",
+ Dependencies = new []
+ {
+ new NuSpecDependency() { Id = "Avalonia", Version = version },
+ new NuSpecDependency() { Id = "SkiaSharp", Version = SkiaSharpVersion }
+ },
+ Files = new []
+ {
+ new NuSpecContent { Source = "Avalonia.Skia.Android.dll", Target = "lib/MonoAndroid10" }
+ },
+ BasePath = Directory("./src/Skia/Avalonia.Skia.Android/bin/" + dirSuffix),
+ OutputDirectory = nugetRoot
+ },
+ ///////////////////////////////////////////////////////////////////////////////
+ // Avalonia.iOS
+ ///////////////////////////////////////////////////////////////////////////////
+ new NuGetPackSettings()
+ {
+ Id = "Avalonia.iOS",
+ Dependencies = new []
+ {
+ new NuSpecDependency() { Id = "Avalonia", Version = version },
+ new NuSpecDependency() { Id = "Avalonia.Skia.iOS", Version = version }
+ },
+ Files = new []
+ {
+ new NuSpecContent { Source = "Avalonia.iOS.dll", Target = "lib/Xamarin.iOS10" }
+ },
+ BasePath = Directory("./src/iOS/Avalonia.iOS/bin/" + dirSuffixIOS),
+ OutputDirectory = nugetRoot
+ },
+ ///////////////////////////////////////////////////////////////////////////////
+ // Avalonia.Skia.iOS
+ ///////////////////////////////////////////////////////////////////////////////
+ new NuGetPackSettings()
+ {
+ Id = "Avalonia.Skia.iOS",
+ Dependencies = new []
+ {
+ new NuSpecDependency() { Id = "Avalonia", Version = version },
+ new NuSpecDependency() { Id = "SkiaSharp", Version = SkiaSharpVersion }
+ },
+ Files = new []
+ {
+ new NuSpecContent { Source = "Avalonia.Skia.iOS.dll", Target = "lib/Xamarin.iOS10" }
+ },
+ BasePath = Directory("./src/Skia/Avalonia.Skia.iOS/bin/" + dirSuffixIOS),
+ OutputDirectory = nugetRoot
+ },
+ ///////////////////////////////////////////////////////////////////////////////
+ // Avalonia.Mobile
+ ///////////////////////////////////////////////////////////////////////////////
+ new NuGetPackSettings()
+ {
+ Id = "Avalonia.Mobile",
+ Dependencies = new []
+ {
+ new NuSpecDependency() { Id = "Avalonia.Android", Version = version },
+ new NuSpecDependency() { Id = "Avalonia.iOS", Version = version }
+ },
+ Files = new NuSpecContent[]
+ {
+ new NuSpecContent { Source = "licence.md", Target = "" }
+ },
+ BasePath = Directory("./"),
+ OutputDirectory = nugetRoot
+ }
+};
+
+var nuspecNuGetSettingsDesktop = new []
+{
+ ///////////////////////////////////////////////////////////////////////////////
+ // Avalonia.Win32
+ ///////////////////////////////////////////////////////////////////////////////
+ new NuGetPackSettings()
+ {
+ Id = "Avalonia.Win32",
+ Dependencies = new []
+ {
+ new NuSpecDependency() { Id = "Avalonia", Version = version }
+ },
+ Files = new []
+ {
+ new NuSpecContent { Source = "Avalonia.Win32.dll", Target = "lib/net45" }
+ },
+ BasePath = Directory("./src/Windows/Avalonia.Win32/bin/" + dirSuffix),
+ OutputDirectory = nugetRoot
+ },
+ ///////////////////////////////////////////////////////////////////////////////
+ // Avalonia.Direct2D1
+ ///////////////////////////////////////////////////////////////////////////////
+ new NuGetPackSettings()
+ {
+ Id = "Avalonia.Direct2D1",
+ Dependencies = new []
+ {
+ new NuSpecDependency() { Id = "Avalonia", Version = version },
+ new NuSpecDependency() { Id = "SharpDX", Version = SharpDXVersion },
+ new NuSpecDependency() { Id = "SharpDX.Direct2D1", Version = SharpDXDirect2D1Version },
+ new NuSpecDependency() { Id = "SharpDX.DXGI", Version = SharpDXDXGIVersion }
+ },
+ Files = new []
+ {
+ new NuSpecContent { Source = "Avalonia.Direct2D1.dll", Target = "lib/net45" }
+ },
+ BasePath = Directory("./src/Windows/Avalonia.Direct2D1/bin/" + dirSuffix),
+ OutputDirectory = nugetRoot
+ },
+ ///////////////////////////////////////////////////////////////////////////////
+ // Avalonia.Gtk
+ ///////////////////////////////////////////////////////////////////////////////
+ new NuGetPackSettings()
+ {
+ Id = "Avalonia.Gtk",
+ Dependencies = new []
+ {
+ new NuSpecDependency() { Id = "Avalonia", Version = version }
+ },
+ Files = new []
+ {
+ new NuSpecContent { Source = "Avalonia.Gtk.dll", Target = "lib/net45" }
+ },
+ BasePath = Directory("./src/Gtk/Avalonia.Gtk/bin/" + dirSuffix),
+ OutputDirectory = nugetRoot
+ },
+ ///////////////////////////////////////////////////////////////////////////////
+ // Avalonia.Cairo
+ ///////////////////////////////////////////////////////////////////////////////
+ new NuGetPackSettings()
+ {
+ Id = "Avalonia.Cairo",
+ Dependencies = new []
+ {
+ new NuSpecDependency() { Id = "Avalonia", Version = version }
+ },
+ Files = new []
+ {
+ new NuSpecContent { Source = "Avalonia.Cairo.dll", Target = "lib/net45" }
+ },
+ BasePath = Directory("./src/Gtk/Avalonia.Cairo/bin/" + dirSuffix),
+ OutputDirectory = nugetRoot
+ },
+ ///////////////////////////////////////////////////////////////////////////////
+ // Avalonia.Skia.Desktop
+ ///////////////////////////////////////////////////////////////////////////////
+ new NuGetPackSettings()
+ {
+ Id = "Avalonia.Skia.Desktop",
+ Dependencies = new []
+ {
+ new NuSpecDependency() { Id = "Avalonia", Version = version },
+ new NuSpecDependency() { Id = "SkiaSharp", Version = SkiaSharpVersion }
+ },
+ Files = new []
+ {
+ new NuSpecContent { Source = "Avalonia.Skia.Desktop.dll", Target = "lib/net45" }
+ },
+ BasePath = Directory("./src/Skia/Avalonia.Skia.Desktop/bin/" + dirSuffixSkia),
+ OutputDirectory = nugetRoot
+ },
+ ///////////////////////////////////////////////////////////////////////////////
+ // Avalonia.Desktop
+ ///////////////////////////////////////////////////////////////////////////////
+ new NuGetPackSettings()
+ {
+ Id = "Avalonia.Desktop",
+ Dependencies = new []
+ {
+ new NuSpecDependency() { Id = "Avalonia.Win32", Version = version },
+ new NuSpecDependency() { Id = "Avalonia.Direct2D1", Version = version },
+ new NuSpecDependency() { Id = "Avalonia.Gtk", Version = version },
+ new NuSpecDependency() { Id = "Avalonia.Cairo", Version = version },
+ new NuSpecDependency() { Id = "Avalonia.Skia.Desktop", Version = version }
+ },
+ Files = new NuSpecContent[]
+ {
+ new NuSpecContent { Source = "licence.md", Target = "" }
+ },
+ BasePath = Directory("./"),
+ OutputDirectory = nugetRoot
+ }
+};
+
+var nuspecNuGetSettings = new List();
+
+nuspecNuGetSettings.AddRange(nuspecNuGetSettingsCore);
+nuspecNuGetSettings.AddRange(nuspecNuGetSettingsDesktop);
+nuspecNuGetSettings.AddRange(nuspecNuGetSettingsMobile);
+
+nuspecNuGetSettings.ForEach((nuspec) => SetNuGetNuspecCommonProperties(nuspec));
+
+var nugetPackages = nuspecNuGetSettings.Select(nuspec => {
+ return nuspec.OutputDirectory.CombineWithFilePath(string.Concat(nuspec.Id, ".", nuspec.Version, ".nupkg"));
+}).ToArray();
+
+///////////////////////////////////////////////////////////////////////////////
+// INFORMATION
+///////////////////////////////////////////////////////////////////////////////
+
+Information("Building version {0} of Avalonia ({1}, {2}, {3}) using version {4} of Cake.",
+ version,
+ platform,
+ configuration,
+ target,
+ typeof(ICakeContext).Assembly.GetName().Version.ToString());
+
+if (isRunningOnAppVeyor)
+{
+ Information("Repository Name: " + BuildSystem.AppVeyor.Environment.Repository.Name);
+ Information("Repository Branch: " + BuildSystem.AppVeyor.Environment.Repository.Branch);
+}
+
+Information("Target: " + target);
+Information("Platform: " + platform);
+Information("Configuration: " + configuration);
+Information("IsLocalBuild: " + isLocalBuild);
+Information("IsRunningOnUnix: " + isRunningOnUnix);
+Information("IsRunningOnWindows: " + isRunningOnWindows);
+Information("IsRunningOnAppVeyor: " + isRunningOnAppVeyor);
+Information("IsPullRequest: " + isPullRequest);
+Information("IsMainRepo: " + isMainRepo);
+Information("IsMasterBranch: " + isMasterBranch);
+Information("IsTagged: " + isTagged);
+Information("IsReleasable: " + isReleasable);
+Information("IsMyGetRelease: " + isMyGetRelease);
+Information("IsNuGetRelease: " + isNuGetRelease);
+
+///////////////////////////////////////////////////////////////////////////////
+// TASKS
+///////////////////////////////////////////////////////////////////////////////
+
+Task("Clean")
+ .Does(() =>
+{
+ CleanDirectories(buildDirs);
+ CleanDirectory(artifactsDir);
+ CleanDirectory(nugetRoot);
+});
+
+Task("Restore-NuGet-Packages")
+ .IsDependentOn("Clean")
+ .Does(() =>
+{
+ var maxRetryCount = 5;
+ var toolTimeout = 1d;
+ Policy
+ .Handle()
+ .Retry(maxRetryCount, (exception, retryCount, context) => {
+ if (retryCount == maxRetryCount)
+ {
+ throw exception;
+ }
+ else
+ {
+ Verbose("{0}", exception);
+ toolTimeout+=0.5;
+ }})
+ .Execute(()=> {
+ if(isRunningOnWindows)
+ {
+ NuGetRestore(MSBuildSolution, new NuGetRestoreSettings {
+ ToolTimeout = TimeSpan.FromMinutes(toolTimeout)
+ });
+ }
+ else
+ {
+ NuGetRestore(XBuildSolution, new NuGetRestoreSettings {
+ ToolTimeout = TimeSpan.FromMinutes(toolTimeout)
+ });
+ }
+ });
+});
+
+Task("Build")
+ .IsDependentOn("Restore-NuGet-Packages")
+ .Does(() =>
+{
+ if(isRunningOnWindows)
+ {
+ MSBuild(MSBuildSolution, settings => {
+ settings.SetConfiguration(configuration);
+ settings.WithProperty("Platform", "\"" + platform + "\"");
+ settings.SetVerbosity(Verbosity.Minimal);
+ settings.WithProperty("Windows", "True");
+ settings.UseToolVersion(MSBuildToolVersion.VS2015);
+ settings.SetNodeReuse(false);
+ });
+ }
+ else
+ {
+ XBuild(XBuildSolution, settings => {
+ settings.SetConfiguration(configuration);
+ settings.WithProperty("Platform", "\"" + platform + "\"");
+ settings.SetVerbosity(Verbosity.Minimal);
+ });
+ }
+});
+
+Task("Run-Unit-Tests")
+ .IsDependentOn("Build")
+ .Does(() =>
+{
+ var pattern = "./tests/Avalonia.*.UnitTests/bin/" + dirSuffix + "/Avalonia.*.UnitTests.dll";
+
+ Func ExcludeWindowsTests = i => {
+ return !(i.Path.FullPath.IndexOf("Direct2D", StringComparison.OrdinalIgnoreCase) >= 0);
+ };
+
+ var unitTests = isRunningOnWindows ? GetFiles(pattern) : GetFiles(pattern, ExcludeWindowsTests);
+
+ if (isRunningOnWindows)
+ {
+ var windowsTests = GetFiles("./tests/Avalonia.DesignerSupport.Tests/bin/" + dirSuffix + "/*Tests.dll") +
+ GetFiles("./tests/Avalonia.LeakTests/bin/" + dirSuffix + "/*Tests.dll") +
+ GetFiles("./tests/Avalonia.RenderTests/bin/" + dirSuffix + "/*Tests.dll");
+
+ unitTests += windowsTests;
+ }
+
+ var toolPath = (isPlatformAnyCPU || isPlatformX86) ?
+ "./tools/xunit.runner.console/tools/xunit.console.x86.exe" :
+ "./tools/xunit.runner.console/tools/xunit.console.exe";
+
+ var settings = new XUnit2Settings
+ {
+ ToolPath = toolPath,
+ Parallelism = ParallelismOption.None
+ };
+
+ if (isRunningOnWindows)
+ {
+ settings.NoAppDomain = false;
+ }
+
+ foreach (var file in unitTests)
+ {
+ Information("Running test " + file.GetFilenameWithoutExtension());
+ XUnit2(file.FullPath, settings);
+ }
+});
+
+Task("Create-NuGet-Packages")
+ .IsDependentOn("Run-Unit-Tests")
+ .Does(() =>
+{
+ foreach(var nuspec in nuspecNuGetSettings)
+ {
+ NuGetPack(nuspec);
+ }
+});
+
+Task("Publish-MyGet")
+ .IsDependentOn("Create-NuGet-Packages")
+ .WithCriteria(() => !isLocalBuild)
+ .WithCriteria(() => !isPullRequest)
+ .WithCriteria(() => isMainRepo)
+ .WithCriteria(() => isMasterBranch)
+ .WithCriteria(() => isMyGetRelease)
+ .Does(() =>
+{
+ var apiKey = EnvironmentVariable("MYGET_API_KEY");
+ if(string.IsNullOrEmpty(apiKey))
+ {
+ throw new InvalidOperationException("Could not resolve MyGet API key.");
+ }
+
+ var apiUrl = EnvironmentVariable("MYGET_API_URL");
+ if(string.IsNullOrEmpty(apiUrl))
+ {
+ throw new InvalidOperationException("Could not resolve MyGet API url.");
+ }
+
+ foreach(var nupkg in nugetPackages)
+ {
+ NuGetPush(nupkg, new NuGetPushSettings {
+ Source = apiUrl,
+ ApiKey = apiKey
+ });
+ }
+})
+.OnError(exception =>
+{
+ Information("Publish-MyGet Task failed, but continuing with next Task...");
+});
+
+Task("Publish-NuGet")
+ .IsDependentOn("Create-NuGet-Packages")
+ .WithCriteria(() => !isLocalBuild)
+ .WithCriteria(() => !isPullRequest)
+ .WithCriteria(() => isMainRepo)
+ .WithCriteria(() => isMasterBranch)
+ .WithCriteria(() => isNuGetRelease)
+ .Does(() =>
+{
+ var apiKey = EnvironmentVariable("NUGET_API_KEY");
+ if(string.IsNullOrEmpty(apiKey))
+ {
+ throw new InvalidOperationException("Could not resolve NuGet API key.");
+ }
+
+ var apiUrl = EnvironmentVariable("NUGET_API_URL");
+ if(string.IsNullOrEmpty(apiUrl))
+ {
+ throw new InvalidOperationException("Could not resolve NuGet API url.");
+ }
+
+ foreach(var nupkg in nugetPackages)
+ {
+ NuGetPush(nupkg, new NuGetPushSettings {
+ ApiKey = apiKey,
+ Source = apiUrl
+ });
+ }
+})
+.OnError(exception =>
+{
+ Information("Publish-NuGet Task failed, but continuing with next Task...");
+});
+
+///////////////////////////////////////////////////////////////////////////////
+// TARGETS
+///////////////////////////////////////////////////////////////////////////////
+
+Task("Package")
+ .IsDependentOn("Create-NuGet-Packages");
+
+Task("Default")
+ .IsDependentOn("Package");
+
+Task("AppVeyor")
+ .IsDependentOn("Publish-MyGet")
+ .IsDependentOn("Publish-NuGet");
+
+Task("Travis")
+ .IsDependentOn("Run-Unit-Tests");
+
+///////////////////////////////////////////////////////////////////////////////
+// EXECUTE
+///////////////////////////////////////////////////////////////////////////////
+
+RunTarget(target);
diff --git a/build.ps1 b/build.ps1
new file mode 100644
index 0000000000..c0f9714b91
--- /dev/null
+++ b/build.ps1
@@ -0,0 +1,193 @@
+##########################################################################
+# This is the Cake bootstrapper script for PowerShell.
+# This file was downloaded from https://github.com/cake-build/resources
+# Feel free to change this file to fit your needs.
+##########################################################################
+
+<#
+
+.SYNOPSIS
+This is a Powershell script to bootstrap a Cake build.
+
+.DESCRIPTION
+This Powershell script will download NuGet if missing, restore NuGet tools (including Cake)
+and execute your Cake build script with the parameters you provide.
+
+.PARAMETER Script
+The build script to execute.
+.PARAMETER Target
+The build script target to run.
+.PARAMETER Platform
+The build platform to use.
+.PARAMETER Configuration
+The build configuration to use.
+.PARAMETER Verbosity
+Specifies the amount of information to be displayed.
+.PARAMETER Experimental
+Tells Cake to use the latest Roslyn release.
+.PARAMETER WhatIf
+Performs a dry run of the build script.
+No tasks will be executed.
+.PARAMETER Mono
+Tells Cake to use the Mono scripting engine.
+.PARAMETER SkipToolPackageRestore
+Skips restoring of packages.
+.PARAMETER ScriptArgs
+Remaining arguments are added here.
+
+.LINK
+http://cakebuild.net
+
+#>
+
+[CmdletBinding()]
+Param(
+ [string]$Script = "build.cake",
+ [string]$Target = "Default",
+ [ValidateSet("Any CPU", "x86", "x64", "Mono", "iPhone")]
+ [string]$Platform = "Any CPU",
+ [ValidateSet("Release", "Debug")]
+ [string]$Configuration = "Release",
+ [ValidateSet("Quiet", "Minimal", "Normal", "Verbose", "Diagnostic")]
+ [string]$Verbosity = "Verbose",
+ [switch]$Experimental,
+ [Alias("DryRun","Noop")]
+ [switch]$WhatIf,
+ [switch]$Mono,
+ [switch]$SkipToolPackageRestore,
+ [Parameter(Position=0,Mandatory=$false,ValueFromRemainingArguments=$true)]
+ [string[]]$ScriptArgs
+)
+
+[Reflection.Assembly]::LoadWithPartialName("System.Security") | Out-Null
+function MD5HashFile([string] $filePath)
+{
+ if ([string]::IsNullOrEmpty($filePath) -or !(Test-Path $filePath -PathType Leaf))
+ {
+ return $null
+ }
+
+ [System.IO.Stream] $file = $null;
+ [System.Security.Cryptography.MD5] $md5 = $null;
+ try
+ {
+ $md5 = [System.Security.Cryptography.MD5]::Create()
+ $file = [System.IO.File]::OpenRead($filePath)
+ return [System.BitConverter]::ToString($md5.ComputeHash($file))
+ }
+ finally
+ {
+ if ($file -ne $null)
+ {
+ $file.Dispose()
+ }
+ }
+}
+
+Write-Host "Preparing to run build script..."
+
+if(!$PSScriptRoot){
+ $PSScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent
+}
+
+$TOOLS_DIR = Join-Path $PSScriptRoot "tools"
+$NUGET_EXE = Join-Path $TOOLS_DIR "nuget.exe"
+$CAKE_EXE = Join-Path $TOOLS_DIR "Cake/Cake.exe"
+$NUGET_URL = "https://dist.nuget.org/win-x86-commandline/latest/nuget.exe"
+$PACKAGES_CONFIG = Join-Path $TOOLS_DIR "packages.config"
+$PACKAGES_CONFIG_MD5 = Join-Path $TOOLS_DIR "packages.config.md5sum"
+
+# Should we use mono?
+$UseMono = "";
+if($Mono.IsPresent) {
+ Write-Verbose -Message "Using the Mono based scripting engine."
+ $UseMono = "-mono"
+}
+
+# Should we use the new Roslyn?
+$UseExperimental = "";
+if($Experimental.IsPresent -and !($Mono.IsPresent)) {
+ Write-Verbose -Message "Using experimental version of Roslyn."
+ $UseExperimental = "-experimental"
+}
+
+# Is this a dry run?
+$UseDryRun = "";
+if($WhatIf.IsPresent) {
+ $UseDryRun = "-dryrun"
+}
+
+# Make sure tools folder exists
+if ((Test-Path $PSScriptRoot) -and !(Test-Path $TOOLS_DIR)) {
+ Write-Verbose -Message "Creating tools directory..."
+ New-Item -Path $TOOLS_DIR -Type directory | out-null
+}
+
+# Make sure that packages.config exist.
+if (!(Test-Path $PACKAGES_CONFIG)) {
+ Write-Verbose -Message "Downloading packages.config..."
+ try { (New-Object System.Net.WebClient).DownloadFile("http://cakebuild.net/download/bootstrapper/packages", $PACKAGES_CONFIG) } catch {
+ Throw "Could not download packages.config."
+ }
+}
+
+# Try find NuGet.exe in path if not exists
+if (!(Test-Path $NUGET_EXE)) {
+ Write-Verbose -Message "Trying to find nuget.exe in PATH..."
+ $existingPaths = $Env:Path -Split ';' | Where-Object { (![string]::IsNullOrEmpty($_)) -and (Test-Path $_) }
+ $NUGET_EXE_IN_PATH = Get-ChildItem -Path $existingPaths -Filter "nuget.exe" | Select -First 1
+ if ($NUGET_EXE_IN_PATH -ne $null -and (Test-Path $NUGET_EXE_IN_PATH.FullName)) {
+ Write-Verbose -Message "Found in PATH at $($NUGET_EXE_IN_PATH.FullName)."
+ $NUGET_EXE = $NUGET_EXE_IN_PATH.FullName
+ }
+}
+
+# Try download NuGet.exe if not exists
+if (!(Test-Path $NUGET_EXE)) {
+ Write-Verbose -Message "Downloading NuGet.exe..."
+ try {
+ (New-Object System.Net.WebClient).DownloadFile($NUGET_URL, $NUGET_EXE)
+ } catch {
+ Throw "Could not download NuGet.exe."
+ }
+}
+
+# Save nuget.exe path to environment to be available to child processed
+$ENV:NUGET_EXE = $NUGET_EXE
+
+# Restore tools from NuGet?
+if(-Not $SkipToolPackageRestore.IsPresent) {
+ Push-Location
+ Set-Location $TOOLS_DIR
+
+ # Check for changes in packages.config and remove installed tools if true.
+ [string] $md5Hash = MD5HashFile($PACKAGES_CONFIG)
+ if((!(Test-Path $PACKAGES_CONFIG_MD5)) -Or
+ ($md5Hash -ne (Get-Content $PACKAGES_CONFIG_MD5 ))) {
+ Write-Verbose -Message "Missing or changed package.config hash..."
+ Remove-Item * -Recurse -Exclude packages.config,nuget.exe
+ }
+
+ Write-Verbose -Message "Restoring tools from NuGet..."
+ $NuGetOutput = Invoke-Expression "&`"$NUGET_EXE`" install -ExcludeVersion -OutputDirectory `"$TOOLS_DIR`""
+
+ if ($LASTEXITCODE -ne 0) {
+ Throw "An error occured while restoring NuGet tools."
+ }
+ else
+ {
+ $md5Hash | Out-File $PACKAGES_CONFIG_MD5 -Encoding "ASCII"
+ }
+ Write-Verbose -Message ($NuGetOutput | out-string)
+ Pop-Location
+}
+
+# Make sure that Cake has been installed.
+if (!(Test-Path $CAKE_EXE)) {
+ Throw "Could not find Cake.exe at $CAKE_EXE"
+}
+
+# Start Cake
+Write-Host "Running build script..."
+Invoke-Expression "& `"$CAKE_EXE`" `"$Script`" -target=`"$Target`" -platform=`"$Platform`" -configuration=`"$Configuration`" -verbosity=`"$Verbosity`" $UseMono $UseDryRun $UseExperimental $ScriptArgs"
+exit $LASTEXITCODE
\ No newline at end of file
diff --git a/build.sh b/build.sh
new file mode 100755
index 0000000000..c9c9637e1f
--- /dev/null
+++ b/build.sh
@@ -0,0 +1,103 @@
+#!/usr/bin/env bash
+
+##########################################################################
+# This is the Cake bootstrapper script for Linux and OS X.
+# This file was downloaded from https://github.com/cake-build/resources
+# Feel free to change this file to fit your needs.
+##########################################################################
+
+# Define directories.
+SCRIPT_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
+TOOLS_DIR=$SCRIPT_DIR/tools
+NUGET_EXE=$TOOLS_DIR/nuget.exe
+CAKE_EXE=$TOOLS_DIR/Cake/Cake.exe
+PACKAGES_CONFIG=$TOOLS_DIR/packages.config
+PACKAGES_CONFIG_MD5=$TOOLS_DIR/packages.config.md5sum
+
+# Define md5sum or md5 depending on Linux/OSX
+MD5_EXE=
+if [[ "$(uname -s)" == "Darwin" ]]; then
+ MD5_EXE="md5 -r"
+else
+ MD5_EXE="md5sum"
+fi
+
+# Define default arguments.
+SCRIPT="build.cake"
+TARGET="Default"
+CONFIGURATION="Release"
+PLATFORM="Any CPU"
+VERBOSITY="verbose"
+DRYRUN=
+SHOW_VERSION=false
+SCRIPT_ARGUMENTS=()
+
+# Parse arguments.
+for i in "$@"; do
+ case $1 in
+ -s|--script) SCRIPT="$2"; shift ;;
+ -t|--target) TARGET="$2"; shift ;;
+ -p|--platform) PLATFORM="$2"; shift ;;
+ -c|--configuration) CONFIGURATION="$2"; shift ;;
+ -v|--verbosity) VERBOSITY="$2"; shift ;;
+ -d|--dryrun) DRYRUN="-dryrun" ;;
+ --version) SHOW_VERSION=true ;;
+ --) shift; SCRIPT_ARGUMENTS+=("$@"); break ;;
+ *) SCRIPT_ARGUMENTS+=("$1") ;;
+ esac
+ shift
+done
+
+# Make sure the tools folder exist.
+if [ ! -d "$TOOLS_DIR" ]; then
+ mkdir "$TOOLS_DIR"
+fi
+
+# Make sure that packages.config exist.
+if [ ! -f "$TOOLS_DIR/packages.config" ]; then
+ echo "Downloading packages.config..."
+ curl -Lsfo "$TOOLS_DIR/packages.config" http://cakebuild.net/download/bootstrapper/packages
+ if [ $? -ne 0 ]; then
+ echo "An error occured while downloading packages.config."
+ exit 1
+ fi
+fi
+
+# Download NuGet if it does not exist.
+if [ ! -f "$NUGET_EXE" ]; then
+ echo "Downloading NuGet..."
+ curl -Lsfo "$NUGET_EXE" https://dist.nuget.org/win-x86-commandline/latest/nuget.exe
+ if [ $? -ne 0 ]; then
+ echo "An error occured while downloading nuget.exe."
+ exit 1
+ fi
+fi
+
+# Restore tools from NuGet.
+pushd "$TOOLS_DIR" >/dev/null
+if [ ! -f $PACKAGES_CONFIG_MD5 ] || [ "$( cat $PACKAGES_CONFIG_MD5 | sed 's/\r$//' )" != "$( $MD5_EXE $PACKAGES_CONFIG | awk '{ print $1 }' )" ]; then
+ find . -type d ! -name . | xargs rm -rf
+fi
+
+mono "$NUGET_EXE" install -ExcludeVersion
+if [ $? -ne 0 ]; then
+ echo "Could not restore NuGet packages."
+ exit 1
+fi
+
+$MD5_EXE $PACKAGES_CONFIG | awk '{ print $1 }' >| $PACKAGES_CONFIG_MD5
+
+popd >/dev/null
+
+# Make sure that Cake has been installed.
+if [ ! -f "$CAKE_EXE" ]; then
+ echo "Could not find Cake.exe at '$CAKE_EXE'."
+ exit 1
+fi
+
+# Start Cake
+if $SHOW_VERSION; then
+ exec mono "$CAKE_EXE" -version
+else
+ exec mono "$CAKE_EXE" $SCRIPT -verbosity=$VERBOSITY -platform="$PLATFORM" -configuration="$CONFIGURATION" -target=$TARGET $DRYRUN "${SCRIPT_ARGUMENTS[@]}"
+fi
diff --git a/docs/tutorial/nuget.md b/docs/tutorial/nuget.md
new file mode 100644
index 0000000000..314575258c
--- /dev/null
+++ b/docs/tutorial/nuget.md
@@ -0,0 +1,86 @@
+# Avalonia NuGet Packages
+
+Avalonia is divided into several `NuGet` packages.
+
+* The `Avalonia` package contains core portable class libraries.
+* The `Dekstop` and `Mobile` packages contain platform specific windowing and rendering back-ends.
+* The `Avalonia.Desktop` package is intended to be used by the end users targeting multiple desktop platforms (`Windows`, `Linux` and `OSX`).
+* The `Avalonia.iOS` and `Avalonia.Android` packages are intended to be used by the end users targeting specific mobile platforms.
+* The `Avalonia.Mobile` package is intended to be used by the end users targeting multiple mobile platforms (`Android` and `iOS`).
+
+## Core
+
+* Avalonia (.nupkg)
+ - Avalonia.Animation (.dll)
+ - Avalonia.Base (.dll)
+ - Avalonia.Controls (.dll)
+ - Avalonia.DesignerSupport (.dll)
+ - Avalonia.Diagnostics (.dll)
+ - Avalonia.Input (.dll)
+ - Avalonia.Interactivity (.dll)
+ - Avalonia.Layout (.dll)
+ - Avalonia.Logging.Serilog (.dll)
+ - Avalonia.SceneGraph (.dll)
+ - Avalonia.Styling (.dll)
+ - Avalonia.ReactiveUI (.dll)
+ - Avalonia.Themes.Default (.dll)
+ - Avalonia.Markup (.dll)
+ - Avalonia.Markup.Xaml (.dll)
+ - Serilog (.nupkg)
+ - Splat (.nupkg)
+ - Sprache (.nupkg)
+ - System.Reactive (.nupkg)
+
+* Avalonia.HtmlRenderer (.nupkg)
+ - Avalonia (.nupkg)
+
+## Desktop
+
+* Avalonia.Win32 (.nupkg)
+ - Avalonia.Win32 (.dll)
+ - Avalonia (.nupkg)
+
+* Avalonia.Direct2D1 (.nupkg)
+ - Avalonia.Direct2D1 (.dll)
+ - Avalonia (.nupkg)
+ - SharpDX (.nupkg)
+ - SharpDX.Direct2D1 (.nupkg)
+ - SharpDX.DXGI (.nupkg)
+
+* Avalonia.Gtk (.nupkg)
+ - Avalonia.Gtk (.dll)
+ - Avalonia (.nupkg)
+
+* Avalonia.Cairo (.nupkg)
+ - Avalonia.Cairo (.dll)
+ - Avalonia (.nupkg)
+
+* Avalonia.Skia.Desktop (.nupkg)
+ - Avalonia.Skia.Desktop (.dll)
+ - Avalonia (.nupkg)
+ - SkiaSharp (.nupkg)
+
+* Avalonia.Desktop (.nupkg)
+ - Avalonia.Win32 (.nupkg)
+ - Avalonia.Direct2D1 (.nupkg)
+ - Avalonia.Gtk (.nupkg)
+ - Avalonia.Cairo (.nupkg)
+ - Avalonia.Skia.Desktop (.nupkg)
+
+## Mobile
+
+* Avalonia.Android (.nupkg)
+ - Avalonia.Android (.dll)
+ - Avalonia.Skia.Android (.dll)
+ - Avalonia (.nupkg)
+ - SkiaSharp (.nupkg)
+
+* Avalonia.iOS (.nupkg)
+ - Avalonia.iOS (.dll)
+ - Avalonia.Skia.iOS (.dll)
+ - Avalonia (.nupkg)
+ - SkiaSharp (.nupkg)
+
+* Avalonia.Mobile (.nupkg)
+ - Avalonia.Android (.nupkg)
+ - Avalonia.iOS (.nupkg)
diff --git a/docs/tutorial/toc.yml b/docs/tutorial/toc.yml
index 9f4a411cf4..4f46813cd8 100644
--- a/docs/tutorial/toc.yml
+++ b/docs/tutorial/toc.yml
@@ -1,2 +1,6 @@
- name: Getting Started
href: gettingstarted.md
+- name: Avalonia NuGet Packages
+ href: nuget.md
+- name: Avalonia for WPF Developers
+ href: from-wpf.md
diff --git a/nuget/.gitignore b/nuget/.gitignore
deleted file mode 100644
index 32f9557fad..0000000000
--- a/nuget/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-Avalonia
-*.nupkg
\ No newline at end of file
diff --git a/nuget/build-appveyor.ps1 b/nuget/build-appveyor.ps1
deleted file mode 100644
index 1441a6a79a..0000000000
--- a/nuget/build-appveyor.ps1
+++ /dev/null
@@ -1,35 +0,0 @@
-$ErrorActionPreference = "Stop"
-$scriptpath = $MyInvocation.MyCommand.Path
-$dir = Split-Path $scriptpath
-Push-Location $dir
-
-
-sv version $env:APPVEYOR_BUILD_NUMBER
-#sv version "1-debug"
-
-sv version 0.4.1-build$version-alpha
-sv key $env:myget_key
-
-. ".\include.ps1"
-.\build-version.ps1 $version
-
-sv reponame $env:APPVEYOR_REPO_NAME
-sv repobranch $env:APPVEYOR_REPO_BRANCH
-sv pullreq $env:APPVEYOR_PULL_REQUEST_NUMBER
-
-echo "Checking for publishing"
-echo "$reponame $repobranch $pullreq"
-if ([string]::IsNullOrWhiteSpace($pullreq))
-{
- echo "Build is not a PR"
- if($repobranch -eq "master")
- {
- echo "Repo branch matched"
- foreach($pkg in $Packages)
- {
- nuget.exe push "$($pkg).$($version).nupkg" $key -Source https://www.myget.org/F/avalonia-ci/api/v2/package
- }
- }
-}
-
-
diff --git a/nuget/build-version.ps1 b/nuget/build-version.ps1
deleted file mode 100644
index c59789ddb8..0000000000
--- a/nuget/build-version.ps1
+++ /dev/null
@@ -1,84 +0,0 @@
-$ErrorActionPreference = "Stop"
-
-. ".\include.ps1"
-
-foreach($pkg in $Packages)
-{
- rm -Force -Recurse .\$pkg -ErrorAction SilentlyContinue
-}
-
-rm -Force -Recurse *.nupkg -ErrorAction SilentlyContinue
-Copy-Item template Avalonia -Recurse
-sv lib "Avalonia\lib\portable-windows8+net45"
-sv build "Avalonia.Desktop\lib\net45"
-
-sv skia_root "Avalonia.Skia.Desktop"
-sv skia_lib "Avalonia.Skia.Desktop\lib\net45"
-sv android "Avalonia.Android\lib\MonoAndroid10"
-sv ios "Avalonia.iOS\lib\Xamarin.iOS10"
-
-mkdir $lib -ErrorAction SilentlyContinue
-mkdir $build -ErrorAction SilentlyContinue
-mkdir $skia_lib
-mkdir $android
-mkdir $ios
-
-
-Copy-Item ..\src\Avalonia.Animation\bin\Release\Avalonia.Animation.dll $lib
-Copy-Item ..\src\Avalonia.Animation\bin\Release\Avalonia.Animation.xml $lib
-Copy-Item ..\src\Avalonia.Base\bin\Release\Avalonia.Base.dll $lib
-Copy-Item ..\src\Avalonia.Base\bin\Release\Avalonia.Base.xml $lib
-Copy-Item ..\src\Avalonia.Controls\bin\Release\Avalonia.Controls.dll $lib
-Copy-Item ..\src\Avalonia.Controls\bin\Release\Avalonia.Controls.xml $lib
-Copy-Item ..\src\Avalonia.DesignerSupport\bin\Release\Avalonia.DesignerSupport.dll $lib
-Copy-Item ..\src\Avalonia.DesignerSupport\bin\Release\Avalonia.DesignerSupport.xml $lib
-Copy-Item ..\src\Avalonia.Diagnostics\bin\Release\\Avalonia.Diagnostics.dll $lib
-Copy-Item ..\src\Avalonia.Diagnostics\bin\Release\\Avalonia.Diagnostics.xml $lib
-Copy-Item ..\src\Avalonia.Input\bin\Release\Avalonia.Input.dll $lib
-Copy-Item ..\src\Avalonia.Input\bin\Release\Avalonia.Input.xml $lib
-Copy-Item ..\src\Avalonia.Interactivity\bin\Release\Avalonia.Interactivity.dll $lib
-Copy-Item ..\src\Avalonia.Interactivity\bin\Release\Avalonia.Interactivity.xml $lib
-Copy-Item ..\src\Avalonia.Layout\bin\Release\Avalonia.Layout.dll $lib
-Copy-Item ..\src\Avalonia.Layout\bin\Release\Avalonia.Layout.xml $lib
-Copy-Item ..\src\Avalonia.Logging.Serilog\bin\Release\Avalonia.Logging.Serilog.dll $lib
-Copy-Item ..\src\Avalonia.Logging.Serilog\bin\Release\Avalonia.Logging.Serilog.xml $lib
-Copy-Item ..\src\Avalonia.SceneGraph\bin\Release\Avalonia.SceneGraph.dll $lib
-Copy-Item ..\src\Avalonia.SceneGraph\bin\Release\Avalonia.SceneGraph.xml $lib
-Copy-Item ..\src\Avalonia.Styling\bin\Release\Avalonia.Styling.dll $lib
-Copy-Item ..\src\Avalonia.Styling\bin\Release\Avalonia.Styling.xml $lib
-Copy-Item ..\src\Avalonia.Themes.Default\bin\Release\Avalonia.Themes.Default.dll $lib
-Copy-Item ..\src\Avalonia.Themes.Default\bin\Release\Avalonia.Themes.Default.xml $lib
-Copy-Item ..\src\Markup\Avalonia.Markup\bin\Release\Avalonia.Markup.dll $lib
-Copy-Item ..\src\Markup\Avalonia.Markup\bin\Release\Avalonia.Markup.xml $lib
-Copy-Item ..\src\Markup\Avalonia.Markup.Xaml\bin\Release\Avalonia.Markup.Xaml.dll $lib
-Copy-Item ..\src\Markup\Avalonia.Markup.Xaml\bin\Release\Avalonia.Markup.Xaml.xml $lib
-Copy-Item ..\src\Avalonia.HtmlRenderer\bin\Release\Avalonia.HtmlRenderer.dll $lib
-Copy-Item ..\src\Avalonia.ReactiveUI\bin\Release\Avalonia.ReactiveUI.dll $lib
-
-Copy-Item ..\src\Windows\Avalonia.Direct2D1\bin\Release\Avalonia.Direct2D1.dll $build
-Copy-Item ..\src\Windows\Avalonia.Win32\bin\Release\Avalonia.Win32.dll $build
-Copy-Item ..\src\Gtk\Avalonia.Gtk\bin\Release\Avalonia.Gtk.dll $build
-Copy-Item ..\src\Gtk\Avalonia.Cairo\bin\Release\Avalonia.Cairo.dll $build
-
-Copy-Item ..\src\Skia\Avalonia.Skia.Desktop\bin\x86\Release\Avalonia.Skia.Desktop.dll $skia_lib
-
-Copy-Item ..\src\Android\Avalonia.Android\bin\Release\Avalonia.Android.dll $android
-Copy-Item ..\src\Skia\Avalonia.Skia.Android\bin\Release\Avalonia.Skia.Android.dll $android
-
-Copy-Item ..\src\iOS\Avalonia.iOS\bin\iPhone\Release\Avalonia.iOS.dll $ios
-Copy-Item ..\src\Skia\Avalonia.Skia.iOS\bin\iPhone\Release\Avalonia.Skia.iOS.dll $ios
-
-foreach($pkg in $Packages)
-{
- (gc Avalonia\$pkg.nuspec).replace('#VERSION#', $args[0]) | sc $pkg\$pkg.nuspec
-}
-
-foreach($pkg in $Packages)
-{
- nuget.exe pack $pkg\$pkg.nuspec
-}
-
-foreach($pkg in $Packages)
-{
- rm -Force -Recurse .\$pkg
-}
\ No newline at end of file
diff --git a/nuget/build.ps1 b/nuget/build.ps1
deleted file mode 100644
index 43c3748bdf..0000000000
--- a/nuget/build.ps1
+++ /dev/null
@@ -1 +0,0 @@
-.\build-version.ps1 0.4.1
\ No newline at end of file
diff --git a/nuget/include.ps1 b/nuget/include.ps1
deleted file mode 100644
index bde8ebb731..0000000000
--- a/nuget/include.ps1
+++ /dev/null
@@ -1 +0,0 @@
-$Packages = @("Avalonia", "Avalonia.Desktop", "Avalonia.Skia.Desktop", "Avalonia.Android", "Avalonia.iOS")
\ No newline at end of file
diff --git a/nuget/template/Avalonia.Android.nuspec b/nuget/template/Avalonia.Android.nuspec
deleted file mode 100644
index cdba3b5b0e..0000000000
--- a/nuget/template/Avalonia.Android.nuspec
+++ /dev/null
@@ -1,28 +0,0 @@
-
-
-
- Avalonia.Android
- #VERSION#
- Avalonia Team
- stevenk
- http://opensource.org/licenses/MIT
- https://github.com/AvaloniaUI/Avalonia/
- false
- The Avalonia UI framework
-
- Copyright 2015
- Avalonia
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/nuget/template/Avalonia.Desktop.nuspec b/nuget/template/Avalonia.Desktop.nuspec
deleted file mode 100644
index 70bebd3349..0000000000
--- a/nuget/template/Avalonia.Desktop.nuspec
+++ /dev/null
@@ -1,30 +0,0 @@
-
-
-
- Avalonia.Desktop
- #VERSION#
- Avalonia Team
- stevenk
- http://opensource.org/licenses/MIT
- https://github.com/AvaloniaUI/Avalonia/
- false
- The Avalonia UI framework
-
- Copyright 2015
- Avalonia
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/nuget/template/Avalonia.Skia.Desktop.nuspec b/nuget/template/Avalonia.Skia.Desktop.nuspec
deleted file mode 100644
index 928b6d3e24..0000000000
--- a/nuget/template/Avalonia.Skia.Desktop.nuspec
+++ /dev/null
@@ -1,20 +0,0 @@
-
-
-
- Avalonia.Skia.Desktop
- #VERSION#
- Avalonia Team
- stevenk
- http://opensource.org/licenses/MIT
- https://github.com/AvaloniaUI/Avalonia/
- false
- The Avalonia UI framework
-
- Copyright 2015
- Avalonia
-
-
-
-
-
-
\ No newline at end of file
diff --git a/nuget/template/Avalonia.iOS.nuspec b/nuget/template/Avalonia.iOS.nuspec
deleted file mode 100644
index d6b8e3fbe6..0000000000
--- a/nuget/template/Avalonia.iOS.nuspec
+++ /dev/null
@@ -1,27 +0,0 @@
-
-
-
- Avalonia.iOS
- #VERSION#
- Avalonia Team
- stevenk
- http://opensource.org/licenses/MIT
- https://github.com/AvaloniaUI/Avalonia/
- false
- The Avalonia UI framework
-
- Copyright 2015
- Avalonia
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/nuget/template/Avalonia.nuspec b/nuget/template/Avalonia.nuspec
deleted file mode 100644
index 55918715a1..0000000000
--- a/nuget/template/Avalonia.nuspec
+++ /dev/null
@@ -1,26 +0,0 @@
-
-
-
- Avalonia
- #VERSION#
- Avalonia Team
- stevenk
- http://opensource.org/licenses/MIT
- https://github.com/AvaloniaUI/Avalonia/
- false
- The Avalonia UI framework
- Initial alpha release.
- Copyright 2015
- Avalonia
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/src/Shared/SharedAssemblyInfo.cs b/src/Shared/SharedAssemblyInfo.cs
index 4a1bebb868..63111eebf4 100644
--- a/src/Shared/SharedAssemblyInfo.cs
+++ b/src/Shared/SharedAssemblyInfo.cs
@@ -13,6 +13,6 @@ using System.Resources;
[assembly: AssemblyTrademark("")]
[assembly: NeutralResourcesLanguage("en")]
-[assembly: AssemblyVersion("0.4.0")]
-[assembly: AssemblyFileVersion("0.4.0")]
-[assembly: AssemblyInformationalVersion("0.4.0")]
+[assembly: AssemblyVersion("0.4.1")]
+[assembly: AssemblyFileVersion("0.4.1")]
+[assembly: AssemblyInformationalVersion("0.4.1")]