diff --git a/.nuke b/.nuke new file mode 100644 index 00000000000..e69de29bb2d diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index b0c0c807cbe..00000000000 --- a/.travis.yml +++ /dev/null @@ -1,24 +0,0 @@ -language: csharp -os: - - linux -dist: trusty -osx_image: xcode8.3 -env: - global: - - DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1 - - DOTNET_CLI_TELEMETRY_OPTOUT=1 -mono: - - 5.2.0 -dotnet: 2.1.200 -script: - - sudo apt-get update - - sudo apt-get install castxml - - ./build.sh --target "Travis" --configuration "Release" -notifications: - email: false - webhooks: - urls: - - https://webhooks.gitter.im/e/98f653320ef2b7506c05 - on_success: change - on_failure: always - on_start: never diff --git a/Avalonia.sln b/Avalonia.sln index df60ff4a75e..e006cadb5a8 100644 --- a/Avalonia.sln +++ b/Avalonia.sln @@ -191,6 +191,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Desktop", "src\Ava EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.Build.Tasks", "src\Avalonia.Build.Tasks\Avalonia.Build.Tasks.csproj", "{BF28998D-072C-439A-AFBB-2FE5021241E0}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "_build", "nukebuild\_build.csproj", "{3F00BC43-5095-477F-93D8-E65B08179A00}" +EndProject Global GlobalSection(SharedMSBuildProjectFiles) = preSolution src\Shared\RenderHelpers\RenderHelpers.projitems*{3c4c0cb4-0c0f-4450-a37b-148c84ff905f}*SharedItemsImports = 13 @@ -216,6 +218,10 @@ Global Release|iPhoneSimulator = Release|iPhoneSimulator EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution + {3F00BC43-5095-477F-93D8-E65B08179A00}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3F00BC43-5095-477F-93D8-E65B08179A00}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3F00BC43-5095-477F-93D8-E65B08179A00}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3F00BC43-5095-477F-93D8-E65B08179A00}.Release|Any CPU.Build.0 = Release|Any CPU {B09B78D8-9B26-48B0-9149-D64A2F120F3F}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU {B09B78D8-9B26-48B0-9149-D64A2F120F3F}.Ad-Hoc|Any CPU.Build.0 = Release|Any CPU {B09B78D8-9B26-48B0-9149-D64A2F120F3F}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU diff --git a/appveyor.yml b/appveyor.yml deleted file mode 100644 index 484fb4586f2..00000000000 --- a/appveyor.yml +++ /dev/null @@ -1,23 +0,0 @@ -os: Visual Studio 2017 -skip_branch_with_pr: true -configuration: -- Release -environment: - DOTNET_SKIP_FIRST_TIME_EXPERIENCE: 1 - DOTNET_CLI_TELEMETRY_OPTOUT: 1 - 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 -init: -- ps: if (Test-Path env:nuget_address) {[System.IO.File]::AppendAllText("C:\Windows\System32\drivers\etc\hosts", "`n$($env:nuget_address)`tapi.nuget.org")} -before_build: -- git submodule update --init -build_script: -- ps: .\build.ps1 -Target "AppVeyor" -Configuration "$env:configuration" - -test: off -artifacts: - - path: artifacts\nuget\*.nupkg - - path: artifacts\zip\*.zip - - path: artifacts\inspectcode.xml diff --git a/azure-pipelines.yml b/azure-pipelines.yml index f6929f8deec..8c5380e65e6 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -11,19 +11,18 @@ jobs: sudo apt-get install castxml - task: CmdLine@2 - displayName: 'Install Cake' + displayName: 'Install Nuke' inputs: script: | - dotnet tool install -g Cake.Tool --version 0.30.0 - + dotnet tool install --global Nuke.GlobalTool --version 0.12.3 - task: CmdLine@2 - displayName: 'Run Cake' + displayName: 'Run Nuke' inputs: script: | export PATH="$PATH:$HOME/.dotnet/tools" dotnet --info printenv - dotnet cake build.cake -target="Azure-Linux" -configuration="Release" + nuke --target CiAzureLinux --configuration=Release - task: PublishTestResults@2 inputs: @@ -55,13 +54,13 @@ jobs: script: brew install castxml - task: CmdLine@2 - displayName: 'Install Cake' + displayName: 'Install Nuke' inputs: script: | - dotnet tool install -g Cake.Tool --version 0.30.0 + dotnet tool install --global Nuke.GlobalTool --version 0.12.3 - task: CmdLine@2 - displayName: 'Run Cake' + displayName: 'Run Nuke' inputs: script: | export COREHOST_TRACE=0 @@ -72,7 +71,7 @@ jobs: export PATH="$PATH:$HOME/.dotnet/tools" dotnet --info printenv - dotnet cake build.cake -target="Azure-OSX" -configuration="Release" + nuke --target CiAzureOSX --configuration Release - task: PublishTestResults@2 inputs: @@ -97,17 +96,17 @@ jobs: vmImage: 'vs2017-win2016' steps: - task: CmdLine@2 - displayName: 'Install Cake' + displayName: 'Install Nuke' inputs: script: | - dotnet tool install -g Cake.Tool --version 0.30.0 + dotnet tool install --global Nuke.GlobalTool --version 0.12.3 - task: CmdLine@2 - displayName: 'Run Cake' + displayName: 'Run Nuke' inputs: script: | set PATH=%PATH%;%USERPROFILE%\.dotnet\tools - dotnet cake build.cake -target="Azure-Windows" -configuration="Release" + nuke --target CiAzureWindows --configuration Release - task: PublishTestResults@2 inputs: diff --git a/build.cake b/build.cake deleted file mode 100644 index f10a12c4e61..00000000000 --- a/build.cake +++ /dev/null @@ -1,312 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -// TOOLS -/////////////////////////////////////////////////////////////////////////////// - -#tool "nuget:?package=NuGet.CommandLine&version=4.7.1" -#tool "nuget:?package=JetBrains.ReSharper.CommandLineTools&version=2018.2.3" -#tool "nuget:?package=xunit.runner.console&version=2.3.1" -#tool "nuget:?package=JetBrains.dotMemoryUnit&version=3.0.20171219.105559" - -/////////////////////////////////////////////////////////////////////////////// -// USINGS -/////////////////////////////////////////////////////////////////////////////// - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Linq; - -/////////////////////////////////////////////////////////////////////////////// -// SCRIPTS -/////////////////////////////////////////////////////////////////////////////// - -#load "./parameters.cake" - -/////////////////////////////////////////////////////////////////////////////// -// SETUP -/////////////////////////////////////////////////////////////////////////////// - -Setup(context => -{ - var parameters = new Parameters(context); - - Information("Building version {0} of Avalonia ({1}) using version {2} of Cake.", - parameters.Version, - parameters.Configuration, - typeof(ICakeContext).Assembly.GetName().Version.ToString()); - - if (parameters.IsRunningOnAppVeyor) - { - Information("Repository Name: " + BuildSystem.AppVeyor.Environment.Repository.Name); - Information("Repository Branch: " + BuildSystem.AppVeyor.Environment.Repository.Branch); - } - Information("Target:" + context.TargetTask.Name); - Information("Configuration: " + parameters.Configuration); - Information("IsLocalBuild: " + parameters.IsLocalBuild); - Information("IsRunningOnUnix: " + parameters.IsRunningOnUnix); - Information("IsRunningOnWindows: " + parameters.IsRunningOnWindows); - Information("IsRunningOnAppVeyor: " + parameters.IsRunningOnAppVeyor); - Information("IsRunnongOnAzure:" + parameters.IsRunningOnAzure); - Information("IsPullRequest: " + parameters.IsPullRequest); - Information("IsMainRepo: " + parameters.IsMainRepo); - Information("IsMasterBranch: " + parameters.IsMasterBranch); - Information("IsReleaseBranch: " + parameters.IsReleaseBranch); - Information("IsTagged: " + parameters.IsTagged); - Information("IsReleasable: " + parameters.IsReleasable); - Information("IsMyGetRelease: " + parameters.IsMyGetRelease); - Information("IsNuGetRelease: " + parameters.IsNuGetRelease); - - return parameters; -}); - -/////////////////////////////////////////////////////////////////////////////// -// TEARDOWN -/////////////////////////////////////////////////////////////////////////////// - -Teardown((context, buildContext) => -{ - Information("Finished running tasks."); -}); - -/////////////////////////////////////////////////////////////////////////////// -// TASKS -/////////////////////////////////////////////////////////////////////////////// - -Task("Clean-Impl") - .Does(data => -{ - CleanDirectories(data.BuildDirs); - CleanDirectory(data.ArtifactsDir); - CleanDirectory(data.NugetRoot); - CleanDirectory(data.ZipRoot); - CleanDirectory(data.TestResultsRoot); -}); - -void DotNetCoreBuild(Parameters parameters) -{ - var settings = new DotNetCoreBuildSettings - { - Configuration = parameters.Configuration, - MSBuildSettings = new DotNetCoreMSBuildSettings - { - Properties = - { - { "PackageVersion", new [] { parameters.Version } } - } - } - }; - - DotNetCoreBuild(parameters.MSBuildSolution, settings); -} - -Task("Build-Impl") - .Does(data => -{ - if(data.IsRunningOnWindows) - { - MSBuild(data.MSBuildSolution, settings => { - settings.SetConfiguration(data.Configuration); - settings.SetVerbosity(Verbosity.Minimal); - settings.WithProperty("iOSRoslynPathHackRequired", "true"); - settings.WithProperty("PackageVersion", data.Version); - settings.UseToolVersion(MSBuildToolVersion.VS2017); - settings.WithRestore(); - }); - } - else - { - DotNetCoreBuild(data); - } -}); - -void RunCoreTest(string project, Parameters parameters, bool coreOnly = false) -{ - if(!project.EndsWith(".csproj")) - project = System.IO.Path.Combine(project, System.IO.Path.GetFileName(project)+".csproj"); - Information("Running tests from " + project); - var frameworks = new List(){"netcoreapp2.0"}; - foreach(var fw in frameworks) - { - if(!fw.StartsWith("netcoreapp") && coreOnly) - continue; - Information("Running for " + fw); - - var settings = new DotNetCoreTestSettings { - Configuration = parameters.Configuration, - Framework = fw, - NoBuild = true, - NoRestore = true - }; - - if (parameters.PublishTestResults) - { - settings.Logger = "trx"; - settings.ResultsDirectory = parameters.TestResultsRoot; - } - - DotNetCoreTest(project, settings); - } -} - -Task("Run-Unit-Tests-Impl") - .WithCriteria((context, data) => !data.SkipTests) - .Does(data => -{ - RunCoreTest("./tests/Avalonia.Base.UnitTests", data, false); - RunCoreTest("./tests/Avalonia.Controls.UnitTests", data, false); - RunCoreTest("./tests/Avalonia.Input.UnitTests", data, false); - RunCoreTest("./tests/Avalonia.Interactivity.UnitTests", data, false); - RunCoreTest("./tests/Avalonia.Layout.UnitTests", data, false); - RunCoreTest("./tests/Avalonia.Markup.UnitTests", data, false); - RunCoreTest("./tests/Avalonia.Markup.Xaml.UnitTests", data, false); - RunCoreTest("./tests/Avalonia.Styling.UnitTests", data, false); - RunCoreTest("./tests/Avalonia.Visuals.UnitTests", data, false); - RunCoreTest("./tests/Avalonia.Skia.UnitTests", data, false); - RunCoreTest("./tests/Avalonia.ReactiveUI.UnitTests", data, false); - if (data.IsRunningOnWindows) - { - RunCoreTest("./tests/Avalonia.Direct2D1.UnitTests", data, false); - } -}); - -Task("Run-Designer-Tests-Impl") - .WithCriteria((context, data) => !data.SkipTests) - .Does(data => -{ - RunCoreTest("./tests/Avalonia.DesignerSupport.Tests", data, false); -}); - -Task("Run-Render-Tests-Impl") - .WithCriteria((context, data) => !data.SkipTests) - .WithCriteria((context, data) => data.IsRunningOnWindows) - .Does(data => -{ - RunCoreTest("./tests/Avalonia.Skia.RenderTests/Avalonia.Skia.RenderTests.csproj", data, true); - RunCoreTest("./tests/Avalonia.Direct2D1.RenderTests/Avalonia.Direct2D1.RenderTests.csproj", data, true); -}); - -Task("Run-Leak-Tests-Impl") - .WithCriteria((context, data) => !data.SkipTests) - .WithCriteria((context, data) => data.IsRunningOnWindows) - .Does(() => -{ - var dotMemoryUnit = Context.Tools.Resolve("dotMemoryUnit.exe"); - var leakTestsExitCode = StartProcess(dotMemoryUnit, new ProcessSettings - { - Arguments = new ProcessArgumentBuilder() - .Append(Context.Tools.Resolve("xunit.console.x86.exe").FullPath) - .Append("--propagate-exit-code") - .Append("--") - .Append("tests\\Avalonia.LeakTests\\bin\\Release\\net461\\Avalonia.LeakTests.dll"), - Timeout = 120000 - }); - - if (leakTestsExitCode != 0) - { - throw new Exception("Leak Tests failed"); - } -}); - -Task("Zip-Files-Impl") - .Does(data => -{ - Zip(data.BinRoot, data.ZipCoreArtifacts); - - Zip(data.NugetRoot, data.ZipNuGetArtifacts); - - Zip(data.ZipSourceControlCatalogDesktopDirs, - data.ZipTargetControlCatalogDesktopDirs, - GetFiles(data.ZipSourceControlCatalogDesktopDirs.FullPath + "/*.dll") + - GetFiles(data.ZipSourceControlCatalogDesktopDirs.FullPath + "/*.config") + - GetFiles(data.ZipSourceControlCatalogDesktopDirs.FullPath + "/*.so") + - GetFiles(data.ZipSourceControlCatalogDesktopDirs.FullPath + "/*.dylib") + - GetFiles(data.ZipSourceControlCatalogDesktopDirs.FullPath + "/*.exe")); -}); - -void DotNetCorePack(Parameters parameters) -{ - var settings = new DotNetCorePackSettings - { - Configuration = parameters.Configuration, - MSBuildSettings = new DotNetCoreMSBuildSettings - { - Properties = - { - { "PackageVersion", new [] { parameters.Version } } - } - } - }; - - DotNetCorePack(parameters.MSBuildSolution, settings); -} - -Task("Create-NuGet-Packages-Impl") - .Does(data => -{ - if(data.IsRunningOnWindows) - { - MSBuild(data.MSBuildSolution, settings => { - settings.SetConfiguration(data.Configuration); - settings.SetVerbosity(Verbosity.Minimal); - settings.WithProperty("iOSRoslynPathHackRequired", "true"); - settings.WithProperty("PackageVersion", data.Version); - settings.UseToolVersion(MSBuildToolVersion.VS2017); - settings.WithRestore(); - settings.WithTarget("Pack"); - }); - } - else - { - DotNetCorePack(data); - } -}); - -/////////////////////////////////////////////////////////////////////////////// -// TARGETS -/////////////////////////////////////////////////////////////////////////////// - -Task("Build") - .IsDependentOn("Clean-Impl") - .IsDependentOn("Build-Impl"); - -Task("Run-Tests") - .IsDependentOn("Build") - .IsDependentOn("Run-Unit-Tests-Impl") - .IsDependentOn("Run-Render-Tests-Impl") - .IsDependentOn("Run-Designer-Tests-Impl") - .IsDependentOn("Run-Leak-Tests-Impl"); - -Task("Package") - .IsDependentOn("Run-Tests") - .IsDependentOn("Create-NuGet-Packages-Impl"); - -Task("AppVeyor") - .IsDependentOn("Package") - .IsDependentOn("Zip-Files-Impl"); - -Task("Travis") - .IsDependentOn("Run-Tests"); - -Task("Azure-Linux") - .IsDependentOn("Run-Tests"); - -Task("Azure-OSX") - .IsDependentOn("Package") - .IsDependentOn("Zip-Files-Impl"); - -Task("Azure-Windows") - .IsDependentOn("Package") - .IsDependentOn("Zip-Files-Impl"); - -/////////////////////////////////////////////////////////////////////////////// -// EXECUTE -/////////////////////////////////////////////////////////////////////////////// - -var target = Context.Argument("target", "Default"); - -if (target == "Default") -{ - target = Context.IsRunningOnWindows() ? "Package" : "Run-Tests"; -} - -RunTarget(target); diff --git a/build.ps1 b/build.ps1 index 46696db2b23..57e2f800758 100644 --- a/build.ps1 +++ b/build.ps1 @@ -1,201 +1,69 @@ -########################################################################## -# 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 SkipTests -Skips unit tests -.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", "NetCoreOnly", "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, + #[switch]$CustomParam, [Parameter(Position=0,Mandatory=$false,ValueFromRemainingArguments=$true)] - [string[]]$ScriptArgs + [string[]]$BuildArguments ) -[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 -} +Write-Output "Windows PowerShell $($Host.Version)" -$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" +Set-StrictMode -Version 2.0; $ErrorActionPreference = "Stop"; $ConfirmPreference = "None"; trap { exit 1 } +$PSScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent -# Should we use mono? -$UseMono = ""; -if($Mono.IsPresent) { - Write-Verbose -Message "Using the Mono based scripting engine." - $UseMono = "-mono" -} +########################################################################### +# CONFIGURATION +########################################################################### -# Should we use the new Roslyn? -$UseExperimental = ""; -if($Experimental.IsPresent -and !($Mono.IsPresent)) { - Write-Verbose -Message "Using experimental version of Roslyn." - $UseExperimental = "-experimental" -} +$BuildProjectFile = "$PSScriptRoot\nukebuild\_build.csproj" +$TempDirectory = "$PSScriptRoot\\.tmp" -# Is this a dry run? -$UseDryRun = ""; -if($WhatIf.IsPresent) { - $UseDryRun = "-dryrun" -} +$DotNetGlobalFile = "$PSScriptRoot\\global.json" +$DotNetInstallUrl = "https://raw.githubusercontent.com/dotnet/cli/master/scripts/obtain/dotnet-install.ps1" +$DotNetChannel = "Current" -# Is this a dry run? -$UseSkipTests = ""; -if($SkipTests.IsPresent) { - $UseSkipTests = "-skip-tests" -} +$env:DOTNET_SKIP_FIRST_TIME_EXPERIENCE = 1 +$env:DOTNET_CLI_TELEMETRY_OPTOUT = 1 +$env:NUGET_XMLDOC_MODE = "skip" -# 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 -} +########################################################################### +# EXECUTION +########################################################################### -# 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." - } +function ExecSafe([scriptblock] $cmd) { + & $cmd + if ($LASTEXITCODE) { exit $LASTEXITCODE } } -# 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 +# If global.json exists, load expected version +if (Test-Path $DotNetGlobalFile) { + $DotNetGlobal = $(Get-Content $DotNetGlobalFile | Out-String | ConvertFrom-Json) + if ($DotNetGlobal.PSObject.Properties["sdk"] -and $DotNetGlobal.sdk.PSObject.Properties["version"]) { + $DotNetVersion = $DotNetGlobal.sdk.version } } -# 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." - } +# If dotnet is installed locally, and expected version is not set or installation matches the expected version +if ((Get-Command "dotnet" -ErrorAction SilentlyContinue) -ne $null -and ` + (!(Test-Path variable:DotNetVersion) -or $(& dotnet --version) -eq $DotNetVersion)) { + $env:DOTNET_EXE = (Get-Command "dotnet").Path } - -# 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 +else { + $DotNetDirectory = "$TempDirectory\dotnet-win" + $env:DOTNET_EXE = "$DotNetDirectory\dotnet.exe" + + # Download install script + $DotNetInstallFile = "$TempDirectory\dotnet-install.ps1" + md -force $TempDirectory > $null + (New-Object System.Net.WebClient).DownloadFile($DotNetInstallUrl, $DotNetInstallFile) + + # Install by channel or version + if (!(Test-Path variable:DotNetVersion)) { + ExecSafe { & $DotNetInstallFile -InstallDir $DotNetDirectory -Channel $DotNetChannel -NoPath } + } else { + ExecSafe { & $DotNetInstallFile -InstallDir $DotNetDirectory -Version $DotNetVersion -NoPath } } - - 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" -} +Write-Output "Microsoft (R) .NET Core SDK version $(& $env:DOTNET_EXE --version)" -# Start Cake -Write-Host "Running build script..." -Invoke-Expression "& `"$CAKE_EXE`" `"$Script`" -target=`"$Target`" -platform=`"$Platform`" -configuration=`"$Configuration`" -verbosity=`"$Verbosity`" $UseSkipTests $UseMono $UseDryRun $UseExperimental $ScriptArgs" -exit $LASTEXITCODE \ No newline at end of file +ExecSafe { & $env:DOTNET_EXE run --project $BuildProjectFile -- $BuildArguments } diff --git a/build.sh b/build.sh index 206a55d1711..40b1c225a69 100755 --- a/build.sh +++ b/build.sh @@ -1,105 +1,72 @@ #!/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. -########################################################################## +echo $(bash --version 2>&1 | head -n 1) -# 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= -SKIP_TESTS= -SHOW_VERSION=false -SCRIPT_ARGUMENTS=() - -# Parse arguments. +#CUSTOMPARAM=0 +BUILD_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 ;; - --skip-tests) SKIP_TESTS="-skip-tests"; shift ;; - -v|--verbosity) VERBOSITY="$2"; shift ;; - -d|--dryrun) DRYRUN="-dryrun" ;; - --version) SHOW_VERSION=true ;; - --) shift; SCRIPT_ARGUMENTS+=("$@"); break ;; - *) SCRIPT_ARGUMENTS+=("$1") ;; + case $(echo $1 | awk '{print tolower($0)}') in + # -custom-param) CUSTOMPARAM=1;; + *) BUILD_ARGUMENTS+=("$1") ;; esac shift done -# Make sure the tools folder exist. -if [ ! -d "$TOOLS_DIR" ]; then - mkdir "$TOOLS_DIR" -fi +set -eo pipefail +SCRIPT_DIR=$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd) -# 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 +########################################################################### +# CONFIGURATION +########################################################################### -# 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 +BUILD_PROJECT_FILE="$SCRIPT_DIR/nukebuild/_build.csproj" +TEMP_DIRECTORY="$SCRIPT_DIR//.tmp" -# 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 +DOTNET_GLOBAL_FILE="$SCRIPT_DIR//global.json" +DOTNET_INSTALL_URL="https://raw.githubusercontent.com/dotnet/cli/master/scripts/obtain/dotnet-install.sh" +DOTNET_CHANNEL="Current" -mono "$NUGET_EXE" install -ExcludeVersion -if [ $? -ne 0 ]; then - echo "Could not restore NuGet packages." - exit 1 -fi +export DOTNET_CLI_TELEMETRY_OPTOUT=1 +export DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1 +export NUGET_XMLDOC_MODE="skip" -$MD5_EXE $PACKAGES_CONFIG | awk '{ print $1 }' >| $PACKAGES_CONFIG_MD5 +########################################################################### +# EXECUTION +########################################################################### -popd >/dev/null +function FirstJsonValue { + perl -nle 'print $1 if m{"'$1'": "([^"\-]+)",?}' <<< ${@:2} +} -# Make sure that Cake has been installed. -if [ ! -f "$CAKE_EXE" ]; then - echo "Could not find Cake.exe at '$CAKE_EXE'." - exit 1 +# If global.json exists, load expected version +if [ -f "$DOTNET_GLOBAL_FILE" ]; then + DOTNET_VERSION=$(FirstJsonValue "version" $(cat "$DOTNET_GLOBAL_FILE")) + if [ "$DOTNET_VERSION" == "" ]; then + unset DOTNET_VERSION + fi fi -# Start Cake -if $SHOW_VERSION; then - exec mono "$CAKE_EXE" -version +# If dotnet is installed locally, and expected version is not set or installation matches the expected version +if [[ -x "$(command -v dotnet)" && (-z ${DOTNET_VERSION+x} || $(dotnet --version) == "$DOTNET_VERSION") ]]; then + export DOTNET_EXE="$(command -v dotnet)" else - exec mono "$CAKE_EXE" $SCRIPT -verbosity=$VERBOSITY -platform="$PLATFORM" -configuration="$CONFIGURATION" -target=$TARGET $DRYRUN $SKIP_TESTS "${SCRIPT_ARGUMENTS[@]}" + DOTNET_DIRECTORY="$TEMP_DIRECTORY/dotnet-unix" + export DOTNET_EXE="$DOTNET_DIRECTORY/dotnet" + + # Download install script + DOTNET_INSTALL_FILE="$TEMP_DIRECTORY/dotnet-install.sh" + mkdir -p "$TEMP_DIRECTORY" + curl -Lsfo "$DOTNET_INSTALL_FILE" "$DOTNET_INSTALL_URL" + chmod +x "$DOTNET_INSTALL_FILE" + + # Install by channel or version + if [ -z ${DOTNET_VERSION+x} ]; then + "$DOTNET_INSTALL_FILE" --install-dir "$DOTNET_DIRECTORY" --channel "$DOTNET_CHANNEL" --no-path + else + "$DOTNET_INSTALL_FILE" --install-dir "$DOTNET_DIRECTORY" --version "$DOTNET_VERSION" --no-path + fi fi + +echo "Microsoft (R) .NET Core SDK version $("$DOTNET_EXE" --version)" + +"$DOTNET_EXE" run --project "$BUILD_PROJECT_FILE" -- ${BUILD_ARGUMENTS[@]} diff --git a/cake.config b/cake.config deleted file mode 100644 index 8089cd40841..00000000000 --- a/cake.config +++ /dev/null @@ -1,15 +0,0 @@ -; This is the default configuration file for Cake. -; This file was downloaded from https://github.com/cake-build/resources - -[Nuget] -Source=https://api.nuget.org/v3/index.json -UseInProcessClient=true -LoadDependencies=false - -[Paths] -Tools=./tools -Addins=./tools/Addins -Modules=./tools/Modules - -[Settings] -SkipVerification=false diff --git a/nukebuild/Build.cs b/nukebuild/Build.cs new file mode 100644 index 00000000000..1014aa1b47d --- /dev/null +++ b/nukebuild/Build.cs @@ -0,0 +1,231 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using System.Threading; +using Nuke.Common; +using Nuke.Common.Git; +using Nuke.Common.ProjectModel; +using Nuke.Common.Tooling; +using Nuke.Common.Tools.DotNet; +using Nuke.Common.Tools.MSBuild; +using Nuke.Common.Utilities; +using static Nuke.Common.EnvironmentInfo; +using static Nuke.Common.IO.FileSystemTasks; +using static Nuke.Common.IO.PathConstruction; +using static Nuke.Common.Tools.MSBuild.MSBuildTasks; +using static Nuke.Common.Tools.DotNet.DotNetTasks; +using static Nuke.Common.Tools.Xunit.XunitTasks; + + +/* + Before editing this file, install support plugin for your IDE, + running and debugging a particular target (optionally without deps) would be way easier + ReSharper/Rider - https://plugins.jetbrains.com/plugin/10803-nuke-support + VSCode - https://marketplace.visualstudio.com/items?itemName=nuke.support + + */ + +partial class Build : NukeBuild +{ + BuildParameters Parameters { get; set; } + protected override void OnBuildInitialized() + { + Parameters = new BuildParameters(this); + Information("Building version {0} of Avalonia ({1}) using version {2} of Nuke.", + Parameters.Version, + Parameters.Configuration, + typeof(NukeBuild).Assembly.GetName().Version.ToString()); + + if (Parameters.IsLocalBuild) + { + Information("Repository Name: " + Parameters.RepositoryName); + Information("Repository Branch: " + Parameters.RepositoryBranch); + } + Information("Configuration: " + Parameters.Configuration); + Information("IsLocalBuild: " + Parameters.IsLocalBuild); + Information("IsRunningOnUnix: " + Parameters.IsRunningOnUnix); + Information("IsRunningOnWindows: " + Parameters.IsRunningOnWindows); + Information("IsRunningOnAzure:" + Parameters.IsRunningOnAzure); + Information("IsPullRequest: " + Parameters.IsPullRequest); + Information("IsMainRepo: " + Parameters.IsMainRepo); + Information("IsMasterBranch: " + Parameters.IsMasterBranch); + Information("IsReleaseBranch: " + Parameters.IsReleaseBranch); + Information("IsReleasable: " + Parameters.IsReleasable); + Information("IsMyGetRelease: " + Parameters.IsMyGetRelease); + Information("IsNuGetRelease: " + Parameters.IsNuGetRelease); + } + + Target Clean => _ => _.Executes(() => + { + DeleteDirectories(Parameters.BuildDirs); + EnsureCleanDirectories(Parameters.BuildDirs); + EnsureCleanDirectory(Parameters.ArtifactsDir); + EnsureCleanDirectory(Parameters.NugetRoot); + EnsureCleanDirectory(Parameters.ZipRoot); + EnsureCleanDirectory(Parameters.TestResultsRoot); + }); + + Target Compile => _ => _ + .DependsOn(Clean) + .Executes(() => + { + + if (Parameters.IsRunningOnWindows) + MSBuild(Parameters.MSBuildSolution, c => c + .SetArgumentConfigurator(a => a.Add("/r")) + .SetConfiguration(Parameters.Configuration) + .SetVerbosity(MSBuildVerbosity.Minimal) + .AddProperty("PackageVersion", Parameters.Version) + .AddProperty("iOSRoslynPathHackRequired", "true") + .SetToolsVersion(MSBuildToolsVersion._15_0) + .AddTargets("Build") + ); + + else + DotNetBuild(Parameters.MSBuildSolution, c => c + .AddProperty("PackageVersion", Parameters.Version) + .SetConfiguration(Parameters.Configuration) + ); + }); + + void RunCoreTest(string project, bool coreOnly = false) + { + if(!project.EndsWith(".csproj")) + project = System.IO.Path.Combine(project, System.IO.Path.GetFileName(project)+".csproj"); + Information("Running tests from " + project); + var frameworks = new List(){"netcoreapp2.0"}; + foreach(var fw in frameworks) + { + if(!fw.StartsWith("netcoreapp") && coreOnly) + continue; + Information("Running for " + fw); + DotNetTest(c => + { + c = c + .SetProjectFile(project) + .SetConfiguration(Parameters.Configuration) + .SetFramework(fw) + .EnableNoBuild() + .EnableNoRestore(); + // NOTE: I can see that we could maybe add another extension method "Switch" or "If" to make this more convenient + if (Parameters.PublishTestResults) + c = c.SetLogger("trx").SetResultsDirectory(Parameters.TestResultsRoot); + return c; + }); + } + } + + Target RunCoreLibsTests => _ => _ + .OnlyWhen(() => !Parameters.SkipTests) + .DependsOn(Compile) + .Executes(() => + { + RunCoreTest("./tests/Avalonia.Base.UnitTests", false); + RunCoreTest("./tests/Avalonia.Controls.UnitTests", false); + RunCoreTest("./tests/Avalonia.Input.UnitTests", false); + RunCoreTest("./tests/Avalonia.Interactivity.UnitTests", false); + RunCoreTest("./tests/Avalonia.Layout.UnitTests", false); + RunCoreTest("./tests/Avalonia.Markup.UnitTests", false); + RunCoreTest("./tests/Avalonia.Markup.Xaml.UnitTests", false); + RunCoreTest("./tests/Avalonia.Styling.UnitTests", false); + RunCoreTest("./tests/Avalonia.Visuals.UnitTests", false); + RunCoreTest("./tests/Avalonia.Skia.UnitTests", false); + RunCoreTest("./tests/Avalonia.ReactiveUI.UnitTests", false); + }); + + Target RunRenderTests => _ => _ + .OnlyWhen(() => !Parameters.SkipTests && Parameters.IsRunningOnWindows) + .DependsOn(Compile) + .Executes(() => + { + RunCoreTest("./tests/Avalonia.Skia.RenderTests/Avalonia.Skia.RenderTests.csproj", true); + RunCoreTest("./tests/Avalonia.Direct2D1.RenderTests/Avalonia.Direct2D1.RenderTests.csproj", true); + }); + + Target RunDesignerTests => _ => _ + .OnlyWhen(() => !Parameters.SkipTests && Parameters.IsRunningOnWindows) + .DependsOn(Compile) + .Executes(() => + { + RunCoreTest("./tests/Avalonia.DesignerSupport.Tests", false); + }); + + [PackageExecutable("JetBrains.dotMemoryUnit", "dotMemoryUnit.exe")] readonly Tool DotMemoryUnit; + + Target RunLeakTests => _ => _ + .OnlyWhen(() => !Parameters.SkipTests && Parameters.IsRunningOnWindows) + .DependsOn(Compile) + .Executes(() => + { + var testAssembly = "tests\\Avalonia.LeakTests\\bin\\Release\\net461\\Avalonia.LeakTests.dll"; + DotMemoryUnit( + $"{XunitPath.DoubleQuoteIfNeeded()} --propagate-exit-code -- {testAssembly}", + timeout: 120_000); + }); + + Target ZipFiles => _ => _ + .After(CreateNugetPackages, Compile, RunCoreLibsTests, Package) + .Executes(() => + { + var data = Parameters; + Zip(data.ZipCoreArtifacts, data.BinRoot); + Zip(data.ZipNuGetArtifacts, data.NugetRoot); + Zip(data.ZipTargetControlCatalogDesktopDir, + GlobFiles(data.ZipSourceControlCatalogDesktopDir, "*.dll").Concat( + GlobFiles(data.ZipSourceControlCatalogDesktopDir, "*.config")).Concat( + GlobFiles(data.ZipSourceControlCatalogDesktopDir, "*.so")).Concat( + GlobFiles(data.ZipSourceControlCatalogDesktopDir, "*.dylib")).Concat( + GlobFiles(data.ZipSourceControlCatalogDesktopDir, "*.exe"))); + }); + + Target CreateNugetPackages => _ => _ + .DependsOn(Compile) + .After(RunTests) + .Executes(() => + { + if (Parameters.IsRunningOnWindows) + + MSBuild(Parameters.MSBuildSolution, c => c + .SetConfiguration(Parameters.Configuration) + .SetVerbosity(MSBuildVerbosity.Minimal) + .AddProperty("PackageVersion", Parameters.Version) + .AddProperty("iOSRoslynPathHackRequired", "true") + .SetToolsVersion(MSBuildToolsVersion._15_0) + .AddTargets("Pack")); + else + DotNetPack(Parameters.MSBuildSolution, c => + c.SetConfiguration(Parameters.Configuration) + .AddProperty("PackageVersion", Parameters.Version)); + }); + + Target RunTests => _ => _ + .DependsOn(RunCoreLibsTests) + .DependsOn(RunRenderTests) + .DependsOn(RunDesignerTests) + .DependsOn(RunLeakTests); + + Target Package => _ => _ + .DependsOn(RunTests) + .DependsOn(CreateNugetPackages); + + Target CiAzureLinux => _ => _ + .DependsOn(RunTests); + + Target CiAzureOSX => _ => _ + .DependsOn(Package) + .DependsOn(ZipFiles); + + Target CiAzureWindows => _ => _ + .DependsOn(Package) + .DependsOn(ZipFiles); + + + public static int Main() => + RuntimeInformation.IsOSPlatform(OSPlatform.Windows) + ? Execute(x => x.Package) + : Execute(x => x.RunTests); + +} diff --git a/nukebuild/BuildParameters.cs b/nukebuild/BuildParameters.cs new file mode 100644 index 00000000000..9029aef60d8 --- /dev/null +++ b/nukebuild/BuildParameters.cs @@ -0,0 +1,140 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Xml.Linq; +using Nuke.Common; +using Nuke.Common.BuildServers; +using Nuke.Common.Execution; +using Nuke.Common.IO; +using static Nuke.Common.IO.FileSystemTasks; +using static Nuke.Common.IO.PathConstruction; +using static Nuke.Common.Tools.MSBuild.MSBuildTasks; + +public partial class Build +{ + [Parameter("configuration")] + public string NukeArgConfiguration { get; set; } + + [Parameter("skip-tests")] + public bool NukeArgSkipTests { get; set; } + + [Parameter("force-nuget-version")] + public string NukeArgForceNugetVersion { get; set; } + + public class BuildParameters + { + public string Configuration { get; } + public bool SkipTests { get; } + public string MainRepo { get; } + public string MasterBranch { get; } + public string RepositoryName { get; } + public string RepositoryBranch { get; } + public string ReleaseConfiguration { get; } + public string ReleaseBranchPrefix { get; } + public string MSBuildSolution { get; } + public bool IsLocalBuild { get; } + public bool IsRunningOnUnix { get; } + public bool IsRunningOnWindows { get; } + public bool IsRunningOnAzure { get; } + public bool IsPullRequest { get; } + public bool IsMainRepo { get; } + public bool IsMasterBranch { get; } + public bool IsReleaseBranch { get; } + public bool IsReleasable { get; } + public bool IsMyGetRelease { get; } + public bool IsNuGetRelease { get; } + public bool PublishTestResults { get; } + public string Version { get; } + public AbsolutePath ArtifactsDir { get; } + public AbsolutePath NugetRoot { get; } + public AbsolutePath ZipRoot { get; } + public AbsolutePath BinRoot { get; } + public AbsolutePath TestResultsRoot { get; } + public string DirSuffix { get; } + public List BuildDirs { get; } + public string FileZipSuffix { get; } + public AbsolutePath ZipCoreArtifacts { get; } + public AbsolutePath ZipNuGetArtifacts { get; } + public AbsolutePath ZipSourceControlCatalogDesktopDir { get; } + public AbsolutePath ZipTargetControlCatalogDesktopDir { get; } + + + public BuildParameters(Build b) + { + // ARGUMENTS + Configuration = b.NukeArgConfiguration ?? "Release"; + SkipTests = b.NukeArgSkipTests; + + // CONFIGURATION + MainRepo = "https://github.com/AvaloniaUI/Avalonia"; + MasterBranch = "refs/heads/master"; + ReleaseBranchPrefix = "refs/heads/release/"; + ReleaseConfiguration = "Release"; + MSBuildSolution = RootDirectory / "dirs.proj"; + + // PARAMETERS + IsLocalBuild = Host == HostType.Console; + IsRunningOnUnix = Environment.OSVersion.Platform == PlatformID.Unix || + Environment.OSVersion.Platform == PlatformID.MacOSX; + IsRunningOnWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows); + IsRunningOnAzure = Host == HostType.TeamServices || + Environment.GetEnvironmentVariable("LOGNAME") == "vsts"; + + if (IsRunningOnAzure) + { + RepositoryName = TeamServices.Instance.RepositoryUri; + RepositoryBranch = TeamServices.Instance.SourceBranch; + IsPullRequest = TeamServices.Instance.PullRequestId.HasValue; + IsMainRepo = StringComparer.OrdinalIgnoreCase.Equals(MainRepo, TeamServices.Instance.RepositoryUri); + } + IsMainRepo = + StringComparer.OrdinalIgnoreCase.Equals(MainRepo, + RepositoryName); + IsMasterBranch = StringComparer.OrdinalIgnoreCase.Equals(MasterBranch, + RepositoryBranch); + IsReleaseBranch = RepositoryBranch?.StartsWith(ReleaseBranchPrefix, StringComparison.OrdinalIgnoreCase) == + true; + + IsReleasable = StringComparer.OrdinalIgnoreCase.Equals(ReleaseConfiguration, Configuration); + IsMyGetRelease = IsReleasable; + IsNuGetRelease = IsMainRepo && IsReleasable && IsReleaseBranch; + + // VERSION + Version = b.NukeArgForceNugetVersion ?? GetVersion(); + + if (IsRunningOnAzure) + { + if (!IsNuGetRelease) + { + // Use AssemblyVersion with Build as version + Version += "-build" + Environment.GetEnvironmentVariable("BUILD_BUILDID") + "-beta"; + } + + PublishTestResults = true; + } + + // DIRECTORIES + ArtifactsDir = RootDirectory / "artifacts"; + NugetRoot = ArtifactsDir / "nuget"; + ZipRoot = ArtifactsDir / "zip"; + BinRoot = ArtifactsDir / "bin"; + TestResultsRoot = ArtifactsDir / "test-results"; + BuildDirs = GlobDirectories(RootDirectory, "**bin").Concat(GlobDirectories(RootDirectory, "**obj")).ToList(); + DirSuffix = Configuration; + FileZipSuffix = Version + ".zip"; + ZipCoreArtifacts = ZipRoot / ("Avalonia-" + FileZipSuffix); + ZipNuGetArtifacts = ZipRoot / ("Avalonia-NuGet-" + FileZipSuffix); + ZipSourceControlCatalogDesktopDir = + RootDirectory / ("samples/ControlCatalog.Desktop/bin/" + DirSuffix + "/net461"); + ZipTargetControlCatalogDesktopDir = ZipRoot / ("ControlCatalog.Desktop-" + FileZipSuffix); + } + + private static string GetVersion() + { + var xdoc = XDocument.Load("./build/SharedVersion.props"); + return xdoc.Descendants().First(x => x.Name.LocalName == "Version").Value; + } + } + +} diff --git a/nukebuild/Shims.cs b/nukebuild/Shims.cs new file mode 100644 index 00000000000..1ba72494d75 --- /dev/null +++ b/nukebuild/Shims.cs @@ -0,0 +1,79 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.IO.Compression; +using System.Linq; +using Nuke.Common; +using Nuke.Common.IO; + +public partial class Build +{ + static void Information(string info) + { + Logger.Info(info); + } + + static void Information(string info, params object[] args) + { + Logger.Info(info, args); + } + + private void Zip(PathConstruction.AbsolutePath target, params string[] paths) => Zip(target, paths.AsEnumerable()); + + private void Zip(PathConstruction.AbsolutePath target, IEnumerable paths) + { + var targetPath = target.ToString(); + bool finished = false, atLeastOneFileAdded = false; + try + { + using (var targetStream = File.Create(targetPath)) + using(var archive = new System.IO.Compression.ZipArchive(targetStream, ZipArchiveMode.Create)) + { + void AddFile(string path, string relativePath) + { + var e = archive.CreateEntry(relativePath.Replace("\\", "/"), CompressionLevel.Optimal); + using (var entryStream = e.Open()) + using (var fileStream = File.OpenRead(path)) + fileStream.CopyTo(entryStream); + atLeastOneFileAdded = true; + } + + foreach (var path in paths) + { + if (Directory.Exists(path)) + { + var dirInfo = new DirectoryInfo(path); + var rootPath = Path.GetDirectoryName(dirInfo.FullName); + foreach(var fsEntry in dirInfo.EnumerateFileSystemInfos("*", SearchOption.AllDirectories)) + { + if (fsEntry is FileInfo) + { + var relPath = Path.GetRelativePath(rootPath, fsEntry.FullName); + AddFile(fsEntry.FullName, relPath); + } + } + } + else if(File.Exists(path)) + { + var name = Path.GetFileName(path); + AddFile(path, name); + } + } + } + + finished = true; + } + finally + { + try + { + if (!finished || !atLeastOneFileAdded) + File.Delete(targetPath); + } + catch + { + //Ignore + } + } + } +} diff --git a/nukebuild/_build.csproj b/nukebuild/_build.csproj new file mode 100644 index 00000000000..ed94116a931 --- /dev/null +++ b/nukebuild/_build.csproj @@ -0,0 +1,35 @@ + + + + Exe + netcoreapp2.0 + false + + False + CS0649;CS0169 + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/nukebuild/_build.csproj.DotSettings b/nukebuild/_build.csproj.DotSettings new file mode 100644 index 00000000000..9aac7d8e8d4 --- /dev/null +++ b/nukebuild/_build.csproj.DotSettings @@ -0,0 +1,24 @@ + + False + Implicit + Implicit + ExpressionBody + 0 + NEXT_LINE + True + False + 120 + IF_OWNER_IS_SINGLE_LINE + WRAP_IF_LONG + False + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + True + True + True + True + True + True + True + True + True diff --git a/readme.md b/readme.md index 9d113cf2ef4..9280125323e 100644 --- a/readme.md +++ b/readme.md @@ -2,9 +2,9 @@ # Avalonia -| Gitter Chat | Build Status (Win, Linux, OSX) | Appveyor Build Status | Open Collective | -|---|---|---|---| -| [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/AvaloniaUI/Avalonia?utm_campaign=pr-badge&utm_content=badge&utm_medium=badge&utm_source=badge) | [![Build Status](https://dev.azure.com/AvaloniaUI/AvaloniaUI/_apis/build/status/AvaloniaUI.Avalonia)](https://dev.azure.com/AvaloniaUI/AvaloniaUI/_build/latest?definitionId=4) | [![Build status](https://ci.appveyor.com/api/projects/status/hubk3k0w9idyibfg/branch/master?svg=true)](https://ci.appveyor.com/project/AvaloniaUI/Avalonia/branch/master) | [![Backers on Open Collective](https://opencollective.com/Avalonia/backers/badge.svg)](#backers) [![Sponsors on Open Collective](https://opencollective.com/Avalonia/sponsors/badge.svg)](#sponsors) | +| Gitter Chat | Build Status (Win, Linux, OSX) | Open Collective | +|---|---|---| +| [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/AvaloniaUI/Avalonia?utm_campaign=pr-badge&utm_content=badge&utm_medium=badge&utm_source=badge) | [![Build Status](https://dev.azure.com/AvaloniaUI/AvaloniaUI/_apis/build/status/AvaloniaUI.Avalonia)](https://dev.azure.com/AvaloniaUI/AvaloniaUI/_build/latest?definitionId=4) | [![Backers on Open Collective](https://opencollective.com/Avalonia/backers/badge.svg)](#backers) [![Sponsors on Open Collective](https://opencollective.com/Avalonia/sponsors/badge.svg)](#sponsors) | ## About